diff options
author | Sunil Thaha <sunil.thaha@nokia.com> | 2012-08-21 15:11:48 +1000 |
---|---|---|
committer | Sunil Thaha <sunil.thaha+qt@gmail.com> | 2012-08-21 07:29:26 +0200 |
commit | 8b3982051badc30d387366bea517cbaaf0a44455 (patch) | |
tree | 56de6eb123760620910f5360407ee0929224777f | |
parent | eeb6f6284e40dd0182070b11f2e106437a31b7e1 (diff) |
QtSystemTest rocks
Initial version of QtSystemTest based on the former QtUiTest
Change-Id: I99b72d26dc623ce5e4a665d3dda380b9fe4eef9d
Reviewed-by: Shane Bradley <shane.bradley@nokia.com>
Reviewed-by: Sunil Thaha <sunil.thaha+qt@gmail.com>
Reviewed-by: David Clark <dac@dclark.org.uk>
220 files changed, 28237 insertions, 0 deletions
diff --git a/3rdparty/xunit.xsd b/3rdparty/xunit.xsd new file mode 100644 index 0000000..e71c456 --- /dev/null +++ b/3rdparty/xunit.xsd @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" + elementFormDefault="qualified" + attributeFormDefault="unqualified"> + <xs:annotation> + <xs:documentation xml:lang="en">Jenkins xUnit test result schema. + </xs:documentation> + </xs:annotation> + <xs:element name="testsuite" type="testsuite"/> + <xs:simpleType name="ISO8601_DATETIME_PATTERN"> + <xs:restriction base="xs:dateTime"> + <xs:pattern value="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}"/> + </xs:restriction> + </xs:simpleType> + <xs:element name="testsuites"> + <xs:annotation> + <xs:documentation xml:lang="en">Contains an aggregation of testsuite results</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element name="testsuite" minOccurs="0" maxOccurs="unbounded"> + <xs:complexType> + <xs:complexContent> + <xs:extension base="testsuite"> + <xs:attribute name="package" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Derived from testsuite/@name in the non-aggregated documents</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="id" type="xs:int" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Starts at '0' for the first testsuite and is incremented by 1 for each following testsuite</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:complexContent> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:complexType name="testsuite"> + <xs:annotation> + <xs:documentation xml:lang="en">Contains the results of exexuting a testsuite</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="testcase" minOccurs="0" maxOccurs="unbounded"> + <xs:complexType> + <xs:choice minOccurs="0"> + <xs:element name="error"> + <xs:annotation> + <xs:documentation xml:lang="en">Indicates that the test errored. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. Contains as a text node relevant data for the error, e.g., a stack trace</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="pre-string"> + <xs:attribute name="message" type="xs:string"> + <xs:annotation> + <xs:documentation xml:lang="en">The error message. e.g., if a java exception is thrown, the return value of getMessage()</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="type" type="xs:string" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">The type of error that occured. e.g., if a java execption is thrown the full class name of the exception.</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="failure"> + <xs:annotation> + <xs:documentation xml:lang="en">Indicates that the test failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals. Contains as a text node relevant data for the failure, e.g., a stack trace</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="pre-string"> + <xs:attribute name="message" type="xs:string"> + <xs:annotation> + <xs:documentation xml:lang="en">The message specified in the assert</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="type" type="xs:string" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">The type of the assert.</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="skipped"> + <xs:annotation> + <xs:documentation xml:lang="en">Indicates that the test was skipped. A skipped test is a test which was ignored using framework mechanisms. e.g., @Ignore annotation.</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="pre-string"> + <xs:attribute name="type" type="xs:string" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Skip type.</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + </xs:choice> + <xs:attribute name="name" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Name of the test method</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="classname" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Full class name for the class the test method is in.</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="time" type="xs:decimal" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Time taken (in seconds) to execute the test</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:attribute name="name" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Full class name of the test for non-aggregated testsuite documents. Class name without the package for aggregated testsuites documents</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:token"> + <xs:minLength value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="timestamp" type="ISO8601_DATETIME_PATTERN" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">when the test was executed. Timezone may not be specified.</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="hostname" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Host on which the tests were executed. 'localhost' should be used if the hostname cannot be determined.</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:token"> + <xs:minLength value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="tests" type="xs:int" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">The total number of tests in the suite</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="failures" type="xs:int" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">The total number of tests in the suite that failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="errors" type="xs:int" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">The total number of tests in the suite that errored. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test.</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="skipped" type="xs:int"> + <xs:annotation> + <xs:documentation xml:lang="en">The total number of tests in the suite that skipped. A skipped test is a test which was ignored using framework mechanisms. e.g., @Ignore annotation.</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="time" type="xs:decimal" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Time taken (in seconds) to execute the tests in the suite</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + <xs:simpleType name="pre-string"> + <xs:restriction base="xs:string"> + <xs:whiteSpace value="preserve"/> + </xs:restriction> + </xs:simpleType> +</xs:schema>
\ No newline at end of file diff --git a/QtSystemTester.pro b/QtSystemTester.pro new file mode 100644 index 0000000..c427252 --- /dev/null +++ b/QtSystemTester.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS = src tests diff --git a/examples/tutorial/main.cpp b/examples/tutorial/main.cpp new file mode 100644 index 0000000..b7928ae --- /dev/null +++ b/examples/tutorial/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> +#include "tpgame.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + a.setApplicationName("tenpinGame"); + TPGame w; + w.show(); + + return a.exec(); +} diff --git a/examples/tutorial/tests/01_parts/PartsTest.qml b/examples/tutorial/tests/01_parts/PartsTest.qml new file mode 100644 index 0000000..7570353 --- /dev/null +++ b/examples/tutorial/tests/01_parts/PartsTest.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtSystemTest 1.0 + +Test { + name: 'Parts' + description: 'Demonstrates parts of a test object' + + function setup() { + print( "Init test function." ); + } + + function run() { + print( "Hello World!" ); + } + + function cleanup() { + print( "Finalize test function." ); + } +} diff --git a/examples/tutorial/tests/02_validate/ValidateTest.qml b/examples/tutorial/tests/02_validate/ValidateTest.qml new file mode 100644 index 0000000..f701dcc --- /dev/null +++ b/examples/tutorial/tests/02_validate/ValidateTest.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtSystemTest 1.0 + +Test { + name: 'Validate' + description: 'Demonstrates validating values' + + function run() { + var count = 3; + + expect(count).toBe(3); + expect(count).not.toBe(2); + expect(count).toBeBetween(2, 4); + } +} diff --git a/examples/tutorial/tests/03_applicationUnderTest/ApplicationUnderTest.qml b/examples/tutorial/tests/03_applicationUnderTest/ApplicationUnderTest.qml new file mode 100644 index 0000000..e1d6150 --- /dev/null +++ b/examples/tutorial/tests/03_applicationUnderTest/ApplicationUnderTest.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: 'Start Application' + description: 'Start an existing application' + + property string executableName: 'tenpinGame' + property Application app + property alias remote: host + + remotes: [ + Remote { + id: host + host: config.remotes.localhost.address + } + ] + + function setup() { + expect(executableName).not.toBe(''); + app = host.startApplication(executableName); + } + + function run() { + var game = app.item({ + inherits: 'TPGame' + }); + expect(game).not.toBe(undefined); + } + + function cleanup() { + app.terminate(); + } +} diff --git a/examples/tutorial/tests/04_findItem/FindItemTest.qml b/examples/tutorial/tests/04_findItem/FindItemTest.qml new file mode 100644 index 0000000..505b753 --- /dev/null +++ b/examples/tutorial/tests/04_findItem/FindItemTest.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +TenPinTest { + function data() {} + + function setup() { + startApplication(); + + data.main = app.items({inherits: 'TPFrame'})[0]; + expect(data.main).not.toBe(null); + expect(data.main).not.toBe(undefined); + + data.first = data.main.descendants({inherits: 'TPFrameBall'})[0]; + expect(data.first).not.toBe(null); + data.second = data.main.descendants({inherits: 'TPFrameBall'})[1]; + expect(data.second).not.toBe(null); + } + + function run() { + expect(data.main.property('display')).toBe(''); + expect(data.first.property('display')).toBe(''); + expect(data.second.property('display')).toBe(''); + } + + function cleanup() { + terminateApplication(); + } +} diff --git a/examples/tutorial/tests/04_findItem/TenPinTest.qml b/examples/tutorial/tests/04_findItem/TenPinTest.qml new file mode 100644 index 0000000..961321d --- /dev/null +++ b/examples/tutorial/tests/04_findItem/TenPinTest.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: 'Start Application' + description: 'Start an existing application' + + property string executableName: 'tenpinGame' + property alias remote: host + + property Application app + + remotes: [ + Remote { + id: host + host: config.remotes.localhost.address + } + ] + + function startApplication() { + expect(executableName).not.toBe(''); + app = host.startApplication(executableName); + expect(app).not.toBe(null); + } + + function terminateApplication() { + app.terminate(); + } +} diff --git a/examples/tutorial/tests/05_input/InputTest.qml b/examples/tutorial/tests/05_input/InputTest.qml new file mode 100644 index 0000000..ddfabd1 --- /dev/null +++ b/examples/tutorial/tests/05_input/InputTest.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +TenPinTest { + function data() {} + + function setup() { + startApplication(); + + data.main = app.items({inherits: 'TPFrame'})[0]; + expect(data.main).not.toBe(null); + expect(data.main).not.toBe(undefined); + + data.first = data.main.descendants({inherits: 'TPFrameBall'})[0]; + expect(data.first).not.toBe(null); + data.second = data.main.descendants({inherits: 'TPFrameBall'})[1]; + expect(data.second).not.toBe(null); + } + + function run() { + expect(data.first.property('display')).toBe(''); + expect(data.second.property('display')).toBe(''); + expect(data.main.property('display')).toBe(''); + + app.mouseClick(data.first); + app.keyPress(Qt.Key_3); + app.mouseClick(data.second); + app.keyPress(Qt.Key_6); + + expect(data.first.property('display')).toBe('3'); + expect(data.second.property('display')).toBe('6'); + expect(data.main.property('display')).toBe('9'); + } + + function cleanup() { + terminateApplication(); + } +} diff --git a/examples/tutorial/tests/05_input/TenPinTest.qml b/examples/tutorial/tests/05_input/TenPinTest.qml new file mode 100644 index 0000000..961321d --- /dev/null +++ b/examples/tutorial/tests/05_input/TenPinTest.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: 'Start Application' + description: 'Start an existing application' + + property string executableName: 'tenpinGame' + property alias remote: host + + property Application app + + remotes: [ + Remote { + id: host + host: config.remotes.localhost.address + } + ] + + function startApplication() { + expect(executableName).not.toBe(''); + app = host.startApplication(executableName); + expect(app).not.toBe(null); + } + + function terminateApplication() { + app.terminate(); + } +} diff --git a/examples/tutorial/tests/06_data/InputTest.qml b/examples/tutorial/tests/06_data/InputTest.qml new file mode 100644 index 0000000..1b6610f --- /dev/null +++ b/examples/tutorial/tests/06_data/InputTest.qml @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +TenPinTest { + name: 'Input Test' + description: 'Add some ball values and validate displays' + + property variant firstEntry: ['3'] + property variant secondEntry: ['6'] + + property string first: '3' + property string second: '6' + property string display: '9' + + function data() {} + + function setup() { + startApplication(); + + data.main = app.items({inherits: 'TPFrame'})[0]; + expect(data.main).not.toBe(null); + expect(data.main).not.toBe(undefined); + + data.first = data.main.descendants({inherits: 'TPFrameBall'})[0]; + expect(data.first).not.toBe(null); + data.second = data.main.descendants({inherits: 'TPFrameBall'})[1]; + expect(data.second).not.toBe(null); + } + + function run() { + expect(data.first.property('display')).toBe(''); + expect(data.second.property('display')).toBe(''); + expect(data.main.property('display')).toBe(''); + + app.mouseClick(data.first); + firstEntry.forEach(function(item) { + app.keyPress(item); + }); + app.mouseClick(data.second); + secondEntry.forEach(function(item) { + app.keyPress(item); + }); + + expect(data.first.property('display')).toBe(first); + expect(data.second.property('display')).toBe(second); + expect(data.main.property('display')).toBe(display); + } + + function cleanup() { + terminateApplication(); + } +} diff --git a/examples/tutorial/tests/06_data/InputTests.qml b/examples/tutorial/tests/06_data/InputTests.qml new file mode 100644 index 0000000..d76a8a2 --- /dev/null +++ b/examples/tutorial/tests/06_data/InputTests.qml @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtSystemTest 1.0 + +TestCollection { + name: 'Input test collection' + description: 'enter various values for first frame and validate display' + + InputTest { + name: 'Gutter Ball' + firstEntry: ['0'] + secondEntry: ['0'] + + first: '0' + second: '0' + display: '0' + } + InputTest { + name: 'Strike' + + firstEntry: ['1', '0'] + secondEntry: [] + + first: 'X' + second: '' + display: '' + } + InputTest { + name: 'Three Seven Spare' + + firstEntry: ['3'] + secondEntry: ['7'] + + first: '3' + second: '/' + display: '' + } + InputTest { + name: 'Three Zero' + firstEntry: ['3'] + secondEntry: ['0'] + + first: '3' + second: '0' + display: '3' + } + InputTest { + name: 'Zero Ten Spare' + + firstEntry: ['0'] + secondEntry: ['1', '0'] + + first: '0' + second: '/' + display: '' + } + InputTest { + name: 'Zero Three' + firstEntry: ['0'] + secondEntry: ['3'] + + first: '0' + second: '3' + display: '3' + } +} diff --git a/examples/tutorial/tests/06_data/TenPinTest.qml b/examples/tutorial/tests/06_data/TenPinTest.qml new file mode 100644 index 0000000..961321d --- /dev/null +++ b/examples/tutorial/tests/06_data/TenPinTest.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: 'Start Application' + description: 'Start an existing application' + + property string executableName: 'tenpinGame' + property alias remote: host + + property Application app + + remotes: [ + Remote { + id: host + host: config.remotes.localhost.address + } + ] + + function startApplication() { + expect(executableName).not.toBe(''); + app = host.startApplication(executableName); + expect(app).not.toBe(null); + } + + function terminateApplication() { + app.terminate(); + } +} diff --git a/examples/tutorial/tpframe.cpp b/examples/tutorial/tpframe.cpp new file mode 100644 index 0000000..bd71d0a --- /dev/null +++ b/examples/tutorial/tpframe.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tpframe.h" +#include "ui_tpframe.h" + +#include <QDebug> + +TPFrame::TPFrame(QWidget *parent) : + QFrame(parent), + ui(new Ui::TPFrame), + m_previous(0), + m_next(0), + m_score(-1) +{ + ui->setupUi(this); + connect(ui->firstBall, SIGNAL(ballChanged(int)), ui->secondBall, SLOT(setPreviousBall(int))); + + connect(ui->firstBall, SIGNAL(scoreChanged(int)), this, SIGNAL(ballsChanged())); + connect(ui->secondBall, SIGNAL(scoreChanged(int)), this, SIGNAL(ballsChanged())); + connect(ui->thirdBall, SIGNAL(scoreChanged(int)), this, SIGNAL(ballsChanged())); + + connect(this, SIGNAL(ballsChanged()), this, SLOT(updateScore())); +} + +TPFrame::~TPFrame() +{ + delete ui; +} + +int TPFrame::first() const +{ + return ui->firstBall->ball(); +} + +int TPFrame::second() const +{ + if (m_next) + return ui->firstBall->isStrike() ? m_next->first() : ui->secondBall->ball(); + return ui->secondBall->ball(); +} + +int TPFrame::third() const +{ + if (m_next) + return ui->firstBall->isStrike() ? m_next->second() : m_next->first(); + return ui->thirdBall->ball(); +} + +int TPFrame::runningTotal() const +{ + if (m_previous) { + int prevTotal = m_previous->runningTotal(); + if (prevTotal != -1 && m_score != -1) + return prevTotal + m_score; + return -1; + } + return m_score; +} + +void TPFrame::setPreviousFrame(TPFrame *frame) +{ + if (m_previous) + disconnect(m_previous, 0, this, 0); + + m_previous = frame; + + if (m_previous) { + connect(m_previous, SIGNAL(runningTotalChanged(int)), this, SLOT(updateTotal())); + updateTotal(); + } +} + +void TPFrame::setNextFrame(TPFrame *frame) +{ + if (m_next) + disconnect(m_next, 0, this, 0); + + m_next = frame; + + if (m_next) { + ui->firstBall->setLastFrame(false); + ui->secondBall->setLastFrame(false); + ui->thirdBall->setLastFrame(false); + ui->thirdBall->hide(); + connect(m_next, SIGNAL(ballsChanged()), this, SIGNAL(ballsChanged())); + } else { + ui->firstBall->setLastFrame(true); + ui->secondBall->setLastFrame(true); + ui->thirdBall->setLastFrame(true); + ui->thirdBall->show(); + } +} + +void TPFrame::reset() +{ + ui->firstBall->setBall(-1); + ui->secondBall->setBall(-1); + ui->thirdBall->setBall(-1); +} + +void TPFrame::updateScore() +{ + int score = -1; + int f = first(); + int s = second(); + int t = third(); + if (ui->firstBall->isStrike()) { + if (s != -1 && t != -1) + score = 10 + s + t; + } else if (ui->secondBall->isSpare()) { + if (t != -1) + score = 10 + t; + } else { + if (f != -1 && s != -1) + score = f + s; + } + if (score == m_score) + return; + m_score = score; + emit scoreChanged(m_score); + updateTotal(); +} + +void TPFrame::updateTotal() +{ + int total = runningTotal(); + emit runningTotalChanged(total); + ui->frameDisplay->setText(total == -1 ? QString() : QString::number(total)); +} + +QString TPFrame::display() const +{ + return ui->frameDisplay->text(); +} diff --git a/examples/tutorial/tpframe.h b/examples/tutorial/tpframe.h new file mode 100644 index 0000000..e0416ba --- /dev/null +++ b/examples/tutorial/tpframe.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TPFRAME_H +#define TPFRAME_H + +#include <QFrame> + +namespace Ui { +class TPFrame; +} + +class TPFrame : public QFrame +{ + Q_OBJECT + Q_PROPERTY(int first READ first DESIGNABLE false STORED false) + Q_PROPERTY(int second READ second DESIGNABLE false STORED false) + Q_PROPERTY(int third READ third DESIGNABLE false STORED false) + Q_PROPERTY(int score READ score NOTIFY scoreChanged DESIGNABLE false STORED false) + Q_PROPERTY(QString display READ display DESIGNABLE false STORED false) + Q_PROPERTY(int runningTotal READ runningTotal NOTIFY runningTotalChanged DESIGNABLE false STORED false) + + Q_PROPERTY(TPFrame *previousFrame READ previousFrame WRITE setPreviousFrame DESIGNABLE false STORED false) + Q_PROPERTY(TPFrame *nextFrame READ nextFrame WRITE setNextFrame DESIGNABLE false STORED false) + +public: + explicit TPFrame(QWidget *parent = 0); + ~TPFrame(); + + int first() const; + int second() const; + int third() const; + int score() const { return m_score; } + int runningTotal() const; + QString display() const; + + TPFrame *previousFrame() const { return m_previous; } + TPFrame *nextFrame() const { return m_next; } + + void setPreviousFrame(TPFrame *); + void setNextFrame(TPFrame *); + +public slots: + void reset(); + +signals: + void runningTotalChanged(int); + void scoreChanged(int); + void ballsChanged(); + +private slots: + void updateScore(); + void updateTotal(); + +private: + Ui::TPFrame *ui; + TPFrame *m_previous; + TPFrame *m_next; + int m_score; +}; + +#endif // TPFRAME_H diff --git a/examples/tutorial/tpframe.ui b/examples/tutorial/tpframe.ui new file mode 100644 index 0000000..6795608 --- /dev/null +++ b/examples/tutorial/tpframe.ui @@ -0,0 +1,357 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TPFrame</class> + <widget class="QFrame" name="TPFrame"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="palette"> + <palette> + <active> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>170</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>170</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>170</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>170</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>20</red> + <green>19</green> + <blue>18</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>20</red> + <green>19</green> + <blue>18</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <layout class="QGridLayout" name="gridLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="horizontalSpacing"> + <number>0</number> + </property> + <item row="0" column="0"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>56</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="2"> + <widget class="TPFrameBall" name="secondBall" native="true"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="TPFrameBall" name="firstBall" native="true"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="TPFrameBall" name="thirdBall" native="true"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QLabel" name="frameDisplay"> + <property name="palette"> + <palette> + <active> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>20</red> + <green>19</green> + <blue>18</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>20</red> + <green>19</green> + <blue>18</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>TPFrameBall</class> + <extends>QWidget</extends> + <header>tpframeball.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/examples/tutorial/tpframeball.cpp b/examples/tutorial/tpframeball.cpp new file mode 100644 index 0000000..d69884a --- /dev/null +++ b/examples/tutorial/tpframeball.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tpframeball.h" +#include <QKeyEvent> +#include <QPainter> +#include <QPaintEvent> +#include <QTextOption> + +#include <QDebug> + +TPFrameBall::TPFrameBall(QWidget *parent) : + QWidget(parent), + m_score(-1), + m_ball(-1), + m_previousBall(-1), + m_lastFrame(true) +{ + setFocusPolicy(Qt::StrongFocus); +} + +void TPFrameBall::setBall(int value) +{ + if (value < 0 || value > 10) + value = -1; + if (value == m_ball) + return; + m_ball = value; + emit ballChanged(m_ball); + updateScore(); +} + +void TPFrameBall::setPreviousBall(int value) +{ + if (value < 0 || value > 10) + value = -1; + if (m_lastFrame && value == 10) + value = -1; + if (value == m_previousBall) + return; + m_previousBall = value; + updateScore(); +} + +void TPFrameBall::mousePressEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + setFocus(); +} + +void TPFrameBall::keyPressEvent(QKeyEvent *event) +{ + switch(event->key()) { + case Qt::Key_0: + if (m_ball == 1) + setBall(10); + else + setBall(0); + break; + case Qt::Key_1: + case Qt::Key_2: + case Qt::Key_3: + case Qt::Key_4: + case Qt::Key_5: + case Qt::Key_6: + case Qt::Key_7: + case Qt::Key_8: + case Qt::Key_9: + setBall(event->key() - Qt::Key_0); + break; + case Qt::Key_Backspace: + if (m_ball == 10) + setBall(1); + else + setBall(-1); + break; + case Qt::Key_X: + setBall(10); + break; + case Qt::Key_Slash: + if (m_previousBall != -1) + setBall(10 - m_previousBall); + break; + default: + break; + } +} + +void TPFrameBall::updateScore() +{ + int score = -1; + if (m_ball != -1 && m_previousBall != -1) + score = m_ball + m_previousBall; + else if (m_ball != -1) + score = m_ball; + + if (m_score != score) { + m_score = score; + emit scoreChanged(m_score); + } + + QString text; + if (isStrike()) + text = QString::fromLatin1("X"); + else if (isSpare()) + text = QString::fromLatin1("/"); + else if (m_ball == -1) + text = QString(); + else if (m_score < 0 || m_score > 10) + text = tr("E", "Error letter, not X or /"); + else + text = QString::number(m_ball); + + if (text != m_display) { + m_display = text; + update(); + } +} + +void TPFrameBall::paintEvent(QPaintEvent *event) +{ + QPainter p(this); + p.setClipRect(event->rect()); + + QPen pen(Qt::red); + QBrush brush(hasFocus() ? Qt::blue : Qt::black); + p.setPen(pen); + p.setBrush(brush); + p.drawRect(0, 0, width(), height()-1); + + pen.setColor(Qt::white); + QFont f = font(); + f.setWeight(QFont::Bold); + p.setPen(pen); + p.drawText(0, 0, width(), height(), Qt::AlignHCenter | Qt::AlignVCenter, m_display); +} + +void TPFrameBall::focusInEvent(QFocusEvent *) +{ + update(); +} + +void TPFrameBall::focusOutEvent(QFocusEvent *) +{ + update(); +} diff --git a/examples/tutorial/tpframeball.h b/examples/tutorial/tpframeball.h new file mode 100644 index 0000000..bf9602e --- /dev/null +++ b/examples/tutorial/tpframeball.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TPBALL_H +#define TPBALL_H + +#include <QWidget> + +#include <QDebug> + +class QLabel; + +class TPFrameBall : public QWidget +{ + Q_OBJECT + Q_PROPERTY(int ball READ ball WRITE setBall NOTIFY ballChanged USER true) + Q_PROPERTY(int previousBall READ previousBall WRITE setPreviousBall) + Q_PROPERTY(int score READ score NOTIFY scoreChanged DESIGNABLE false STORED false) + Q_PROPERTY(QString display READ display DESIGNABLE false STORED false) + Q_PROPERTY(bool isStrike READ isStrike DESIGNABLE false STORED false) + Q_PROPERTY(bool isSpare READ isSpare DESIGNABLE false STORED false) + Q_PROPERTY(bool isLastFrame READ isLastFrame WRITE setLastFrame) +public: + explicit TPFrameBall(QWidget *parent = 0); + + QString display() const { return m_display; } + int ball() const { return m_ball; } + int previousBall() const { return m_previousBall; } + int score() const { return m_score; } + bool isStrike() const { return m_previousBall == -1 && score() == 10; } + bool isSpare() const { return m_previousBall != 10 && score() == 10; } + bool isLastFrame() const { return m_lastFrame; } + void setLastFrame(bool value) { m_lastFrame = value; updateScore(); } + +public slots: + void setBall(int); + void setPreviousBall(int); + +signals: + void ballChanged(int); + void scoreChanged(int); + +protected: + void mousePressEvent(QMouseEvent *); + void keyPressEvent(QKeyEvent *); + + void paintEvent(QPaintEvent *); + void focusInEvent(QFocusEvent *); + void focusOutEvent(QFocusEvent *); + +private slots: + void updateScore(); + +private: + QString m_display; + int m_score; + int m_ball; + int m_previousBall; + QLabel *m_label; + + bool m_lastFrame; +}; + +#endif // TPBALL_H diff --git a/examples/tutorial/tpgame.cpp b/examples/tutorial/tpgame.cpp new file mode 100644 index 0000000..80f2da4 --- /dev/null +++ b/examples/tutorial/tpgame.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tpgame.h" +#include "tpframe.h" +#include <QScrollArea> +#include <QHBoxLayout> + +TPGame::TPGame(QWidget *parent) : + QWidget(parent) +{ + QHBoxLayout *layout = new QHBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + TPFrame *last = 0; + for (int i = 0; i < 10; i++) { + TPFrame *frame = new TPFrame; + layout->addWidget(frame); + m_frames.append(frame); + frame->setPreviousFrame(last); + if (last) + last->setNextFrame(frame); + last = frame; + } + setLayout(layout); +} + +TPGame::~TPGame() +{ +} + +void TPGame::reset() +{ + foreach(TPFrame *frame, m_frames) { + frame->reset(); + } +} diff --git a/examples/tutorial/tpgame.h b/examples/tutorial/tpgame.h new file mode 100644 index 0000000..a884211 --- /dev/null +++ b/examples/tutorial/tpgame.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TENPINGAME_H +#define TENPINGAME_H + +#include <QWidget> + +class TPFrame; + +class TPGame : public QWidget +{ + Q_OBJECT + +public: + explicit TPGame(QWidget *parent = 0); + ~TPGame(); + +public slots: + void reset(); +private: + QList<TPFrame *> m_frames; +}; + +#endif // TENPINGAME_H diff --git a/examples/tutorial/tutorial.pro b/examples/tutorial/tutorial.pro new file mode 100644 index 0000000..7570b77 --- /dev/null +++ b/examples/tutorial/tutorial.pro @@ -0,0 +1,18 @@ +QT += core gui + +TARGET = tenpinGame +TEMPLATE = app + + +SOURCES += main.cpp\ + tpframe.cpp \ + tpframeball.cpp \ + tpgame.cpp + +HEADERS += \ + tpframe.h \ + tpframeball.h \ + tpgame.h + +FORMS += \ + tpframe.ui diff --git a/scripts/update_license.pl b/scripts/update_license.pl new file mode 100644 index 0000000..9644759 --- /dev/null +++ b/scripts/update_license.pl @@ -0,0 +1,56 @@ +@lines = <STDIN>; +$in_license = true; +foreach (@lines) { + if ($in_license && /^\*\*/ || /\*\*$/) { + ; + } else { + $in_license = false; + push @code_lines, $_; + } +} + +print <<END; +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** \$QT_BEGIN_LICENSE:LGPL\$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** \$QT_END_LICENSE\$ +** +****************************************************************************/ + +END + +print(@code_lines); diff --git a/scripts/update_licenses.sh b/scripts/update_licenses.sh new file mode 100755 index 0000000..dd01af9 --- /dev/null +++ b/scripts/update_licenses.sh @@ -0,0 +1,6 @@ +for f in `grep -d recurse -l QT_BEGIN_LICENSE ./src` +do + mv $f $f.orig + perl update_license.pl < $f.orig > $f + rm $f.orig +done diff --git a/src/interpreter/imports/imports.pro b/src/interpreter/imports/imports.pro new file mode 100644 index 0000000..dd43ea0 --- /dev/null +++ b/src/interpreter/imports/imports.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS += qtsystemtest \ + runner diff --git a/src/interpreter/imports/qtsystemtest/qml/Application.qml b/src/interpreter/imports/qtsystemtest/qml/Application.qml new file mode 100644 index 0000000..36c9cdb --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/Application.qml @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import "../scripts/QstCore.js" as Core + +QtObject { + id: app + + property Remote remote + property variant pid: null + property variant __id + + function item(query) { + var matches = __queryProperties(query); + if ( matches.length !== 1 ) { + throw new Core.Qtt.Fail('Error: ' + matches.length + + ' items match query, expected a single match', 1); + } + return __handlerForObject(matches[0]); + } + + function items(query) { + var matches = __queryProperties(query); + var handlers = matches.map(function(obj) { + return __handlerForObject(obj); + }); + return handlers; + } + + function activeWidgetInfo() { return __sendQuery(arguments.callee.name); } + + function applicationData() { + return __sendQuery(arguments.callee.name).applicationdata; + } + + + function keyPress(key) { + __sendQuery(arguments.callee.name, { key: key }); + } + + function keyRelease(key) { + __sendQuery(arguments.callee.name, { key: key }); + } + + function keyClick(key) { + __sendQuery(arguments.callee.name, { key: key }); + } + + + function mousePress(pos, buttons) { + __inputEvent(arguments.callee.name, pos, buttons); + } + + function mouseRelease(pos, buttons) { + __inputEvent(arguments.callee.name, pos, buttons); + } + + function mouseClick(pos, buttons) { + __inputEvent(arguments.callee.name, pos, buttons); + } + + function mouseDoubleClick(pos, buttons) { + __inputEvent(arguments.callee.name, pos, buttons); + } + + function terminate() { + remote.runProcess( { program: "kill", arguments: [ pid ], timeout: 500 } ); + } + + function __queryProperties(query) { + // traverse the query object replacing any QstObject with its __internals + (function prepare(query) { + var prop, v; + for (prop in query) { + v = query[prop]; + if ( typeof(v) !== 'object' ) { continue; } + + if( v.__isQmlWrapper === true ) { + query[prop] = v.__internals; + } else { + prepare(v); + } + } + })(query); + + var items = __sendQuery("queryProperties", { + searchvalues: query + }).queryproperties; + return items || []; + } + + function __handlerForObject(obj) { + var ItemFactory = Core.ItemFactory; + var component = ItemFactory.handlerForObject(obj, {application: app}); + return component.createObject( + __runner.currentTestItem, { + application: app, + __internals: obj, + } + ); + + } + + + function __inheritanceTree(o) { + return __sendQuery('inheritance',{}, o).inheritance; + } + + function __inputEvent(event, pos, buttons) { + buttons = buttons || Qt.LeftButton; + + if (pos.__isQmlWrapper === true) { + return __sendQuery(event, {buttons: buttons}, pos.__internals); + } + + return remote.__sendPositionQuery(event, {buttons: buttons}, pos); + } + + + function __sendQuery() { + return remote.__sendQuery.apply(remote, arguments); + } +} diff --git a/src/interpreter/imports/qtsystemtest/qml/ApplicationObjectsCache.js b/src/interpreter/imports/qtsystemtest/qml/ApplicationObjectsCache.js new file mode 100644 index 0000000..15fdc67 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/ApplicationObjectsCache.js @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +var __hosts = {}; + +function host(address) { + if ( __hosts[address] === undefined) { + __hosts[address] = new Host(address); + } + + return __hosts[address]; +} + +function Host(address) { + this.address = address; + this._store = {}; +} + +Host.prototype.store = function(appId, props) { + if ( !(appId in this._store) ){ + this._store[appId] = props; + return; + } + + var s = this._store[appId]; + for (var x in props) { + s[x] = props[x]; + } +} + +Host.prototype.data = function(appId) { + return appId in this._store + ? this._store[appId] + : null; +} diff --git a/src/interpreter/imports/qtsystemtest/qml/Js.qml b/src/interpreter/imports/qtsystemtest/qml/Js.qml new file mode 100644 index 0000000..703c564 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/Js.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import '../scripts/QstCore.js' as Core + +QtObject { + function core() { + return Core; + } +} diff --git a/src/interpreter/imports/qtsystemtest/qml/Remote.qml b/src/interpreter/imports/qtsystemtest/qml/Remote.qml new file mode 100644 index 0000000..255a291 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/Remote.qml @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import '../scripts/QstCore.js' as Core +import 'ApplicationObjectsCache.js' as Cache + +QtObject { + id: remote + property string host + property int port: 5656 + property int applicationStartTimeout: 5000 + property int appStartRefreshInterval: 250 + + property bool __needToReconnect: true + property bool __debug_showMessageReceived: false + + onHostChanged: { __needToReconnect = true; } + onPortChanged: { __needToReconnect = true; } + + + function runProcess(params) { + return __sendQuery(arguments.callee.name, { cmd: params } ); + } + + function startApplication(app, args) { + args = args || [] + args.push("-style", "qtuitestd"); + var currentAppId = __currentAppId(); + var output = runProcess({ + program: app, + arguments: args, + detached: true + }); + + var timeout = 0; + while( __currentAppId() === currentAppId + && timeout < applicationStartTimeout) { + sleep(appStartRefreshInterval); + timeout += appStartRefreshInterval; + } + + var newAppId = __currentAppId(); + if (currentAppId === newAppId) { + throw new Core.Qtt.Fail('Application failed to start', 1); + } + Cache.host(host).store(newAppId, { + executable: app, + pid: output.pid, + }); + return applicationForId(newAppId) + } + + + + function currentApplication() { + var appId = __currentAppId(); + + if (appId === '') { + throw new Core.Qtt.Fail('No Current application', 1); + } + + return applicationForId(appId); + } + + function applicationForId(appId) { + // there should be data in the cache already + var cache = Cache.host(host); + var appData = cache.data(appId); + if (appData === null) { + throw new Core.Qtt.Fail('Application for Id not found', 1); + } + + if (appData.application !== undefined) { + return appData.application; + } + + var ApplicationRegistry = Core.ApplicationRegistry + var component = ApplicationRegistry.applicationForKey(appData.executable); + var app = component.createObject(__runner.currentTestItem, { + remote: remote, + __id: appId, + pid: appData.pid, + }); + if (app === null) { + throw new Core.Qtt.Error('Failed to create an application object for : ' + appId); + } + cache.store(appId, {application: app}); + return app; + } + + function applications() { + } + + function __connection() { + if (__needToReconnect == false) { + return __connection.object; + } + __connection.object = ConnectionManager.connectionForHost(host, port); + __connection.object.messageReceived.connect(__messageReceived); + var ok = __connection.object.connectToRemote(); + if ( !ok ) { + var e = new Core.Qtt.Fail('Error: Connection to : \ + host ' + host + 'port :' + port + ' failed', 2); + throw e; + } + __needToReconnect = false; + return __connection.object; + } + + function __sendQuery(event, params, widgetSpecifier) { + return __connection().sendQuery(event, params, widgetSpecifier); + } + + function __sendPositionQuery(event, params, position) { + return __connection().sendPositionQuery(event, params, position); + } + + function __currentAppId() { + return __sendQuery('currentApplication').currentapplication; + } + + function __messageReceived(event, context, data) { + if ( __debug_showMessageReceived ) { + console.log("Message received: ", + event, " context(" + context + ")", + 'data: ', Core.stringify(data)); + } + } +} diff --git a/src/interpreter/imports/qtsystemtest/qml/Test.qml b/src/interpreter/imports/qtsystemtest/qml/Test.qml new file mode 100644 index 0000000..df7f815 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/Test.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import "../scripts/QstCore.js" as Core + +TestItem { + id: root + + property string __status: Core.Qtt.Status.Untested ///'' // passed, failed, skipped + property bool __isTest: true + property variant __mustHaves: ['name', 'description', 'run'] + + function __validate() { + var missingMustHave; + var allMustHaves = __mustHaves.every(function(k) { + missingMustHave =k; + return (k in root) && root[k] !== ''; + }); + + if (!allMustHaves) { + return __error('Test Item: ', root.name, ' does not define property or function', + '\'', missingMustHave, '\' the must haves are: ', __mustHaves); + } + + return __ok(); + } + +} + diff --git a/src/interpreter/imports/qtsystemtest/qml/TestCollection.qml b/src/interpreter/imports/qtsystemtest/qml/TestCollection.qml new file mode 100644 index 0000000..87e5b86 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/TestCollection.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import "../scripts/QstCore.js" as Core + +TestItem { + id: root + property list<TestItem> __subset + default property alias children: root.__subset + + function __validate() { + var missingMustHave; + var allMustHaves = __mustHaves.every(function(k) { + missingMustHave =k; + return (k in root) && root[k] !== ''; + }); + + if (!allMustHaves) { + return __error('Test Item: ', root.name, ' does not define property', + '\'', missingMustHave, '\' the must haves are: ', __mustHaves); + } + + if( root.__subset.length > 0 && 'run' in root && typeof(root.run) === 'function' ) { + return __error('Invalid test: Cannot have sub test-sets and run() defined for ', root.name); + } + + if(__subset === null) { + return __ok(); + } + + for( var i = 0; i < __subset.length; i++) { + var s = __subset[i]; + var v = s.__validate(); + if( v.valid === false) { + return v; + } + } + + return __ok(); + } +} diff --git a/src/interpreter/imports/qtsystemtest/qml/TestItem.qml b/src/interpreter/imports/qtsystemtest/qml/TestItem.qml new file mode 100644 index 0000000..04fda39 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/TestItem.qml @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import "../scripts/QstCore.js" as Core + +TestMethod { + id: root + property string name:'' + property string description: '' + property bool enabled: true + + property list<Remote> remotes + + property variant __mustHaves: ['name', 'description'] + property bool __isTest: false + + function __ok() { + var path = Core.Js.__validationRoot__; + if ( path !== undefined) { + path.pop(); + if (path.length === 0) { + delete Core.Js.__validationRoot__; + } + } + return { + valid: true, + }; + } + + function __error() { + var runner = __runner, + msg = Array.prototype.slice.call(arguments).join(' '), + e = new Core.Qtt.Error(msg), + loc = runner.locationOf(root), + err; + + err = e.toString() + '\n' + + 'Location: ' + loc.url + '(' + loc.lineNumber + ')'; + return { + valid: false, + error : err + }; + } +} diff --git a/src/interpreter/imports/qtsystemtest/qml/TestMethod.qml b/src/interpreter/imports/qtsystemtest/qml/TestMethod.qml new file mode 100644 index 0000000..55cb64d --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/TestMethod.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import '../scripts/QstCore.js' as Core + +QtObject { + // make core c++ stuff internal + property variant __core: CoreApi {} + function core() { return Core; } + + /*! + Causes the current test object to fail immediately + */ + function fail(message) { + var msg = Core.stringify.apply(null, arguments); + var e = new Core.Qtt.Fail(msg); + e.discardCallSites(); + throw e; + } + + function skip(message) { + var msg = Core.stringify.apply(null, arguments); + var e = new Core.Qtt.Skip(msg); + e.discardCallSites(); + throw e; + } + + function log() { + __runner.log.apply(__runner, arguments); + } + + function expect(o) { + return core().expect(o); + } + + function sleep(ms) { + // calls cpp method + __core.sleep(ms); + } +} diff --git a/src/interpreter/imports/qtsystemtest/qml/itemhandlers/QstObject.qml b/src/interpreter/imports/qtsystemtest/qml/itemhandlers/QstObject.qml new file mode 100644 index 0000000..6cbee20 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/itemhandlers/QstObject.qml @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import '..' +import "../../scripts/QstCore.js" as Core + +QtObject { + id: me + + property Application application + property variant __internals + property bool __isQmlWrapper: true + property string handles: 'QObject' + + function property(name) { + return __sendQuery('getProperty', {property: name}).getproperty; + } + + function setProperty(name, value) { + return __sendQuery('setProperty', { + property: name, + value: value, + }); + } + + function descendants(filter) { + filter = filter || {}; + filter.descendant_of = me; + return application.items(filter); + } + + function ancestors(filter) { + filter = filter || {}; + filter.ancestor_of = me; + return application.items(filter); + } + + function parent() { + return application.item({parent_of: me}); + } + + function isValid() { + try { + var x = type(); + } catch(e) { + return false; + } + return true; + + } + + function type() { + return __sendQuery('typeOf')['typeof']; + } + +// method: function(methodSignature) { +// return new QtUiTestMethod(this, methodSignature); +// }, + +// equals: function(other) { +// // FIXME other should be checked if it is a QtUiTestObject +// // but that test fails since for _prefetched_ objects the +// // type is set as Object and not QtUiTestWidget or QtUiTestObject +// // try: print(other.constructor.name) +// return other._signature_ !== undefined +// && this._signature_ === other._signature_; +// }, + + function toString() { + return this._signature_; + } + + function __sendQuery(event, params) { + params = params || {}; + return application.__sendQuery(event, params, __internals); + } + +} diff --git a/src/interpreter/imports/qtsystemtest/qml/itemhandlers/QstWidget.qml b/src/interpreter/imports/qtsystemtest/qml/itemhandlers/QstWidget.qml new file mode 100644 index 0000000..4eaa33f --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qml/itemhandlers/QstWidget.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import "../../scripts/QstCore.js" as Core + +QstObject { + id: me + handles: 'QWidget' +} diff --git a/src/interpreter/imports/qtsystemtest/qmldir b/src/interpreter/imports/qtsystemtest/qmldir new file mode 100644 index 0000000..06f9958 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qmldir @@ -0,0 +1,11 @@ +plugin qtsystemtest +Application 1.0 qml/Application.qml +Remote 1.0 qml/Remote.qml +TestData 1.0 qml/TestData.qml +TestItem 1.0 qml/TestItem.qml +Test 1.0 qml/Test.qml +TestCollection 1.0 qml/TestCollection.qml +QstObject 1.0 qml/itemhandlers/QstObject.qml +QstWidget 1.0 qml/itemhandlers/QstWidget.qml +Js 1.0 qml/Js.qml +Core 1.0 scripts/QstCore.js diff --git a/src/interpreter/imports/qtsystemtest/qtsystemtest.json b/src/interpreter/imports/qtsystemtest/qtsystemtest.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qtsystemtest.json @@ -0,0 +1 @@ +{} diff --git a/src/interpreter/imports/qtsystemtest/qtsystemtest.pro b/src/interpreter/imports/qtsystemtest/qtsystemtest.pro new file mode 100644 index 0000000..566a570 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/qtsystemtest.pro @@ -0,0 +1,74 @@ +TARGET = qtsystemtest +TARGETPATH = QtSystemTest + + +TEMPLATE = lib +CONFIG += no_clean qt plugin + +QT += declarative declarative-private testlib + +INCLUDEPATH += ../../../../include +LIBS += -L../../../../lib +LIBS += -lQstProtocol + +SOURCES += src/imports.cpp \ + src/qstcoreapi.cpp \ + src/qstutils.cpp \ + src/qstlocalprocess.cpp + +HEADERS += src/imports.h \ + src/qstcoreapi.h \ + src/qstutils.h \ + src/qstlocalprocess.h + +OTHER_FILES += \ + qtsystemtest.json \ + +target.path += $$[QT_INSTALL_IMPORTS]/QtSystemTest + +# public api +QML_IMPORT_FILES = \ + qml/TestMethod.qml \ + qml/TestItem.qml \ + qml/Test.qml \ + qml/TestCollection.qml \ + qml/Remote.qml \ + qml/Application.qml \ + qml/itemhandlers/QstObject.qml \ + qml/Js.qml \ + +qmlImportFiles.files += $$PWD/qml +qmlImportFiles.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH + +# scripts +SCRIPT_FILES = \ + scripts/api.js \ + scripts/Datatype.js \ + scripts/Functional.js \ + scripts/JsCore.js \ + scripts/SourceBuilder.js \ + scripts/Class.js \ + scripts/QstCore.js \ + scripts/Console.js \ + scripts/Expect.js \ + scripts/Exception.js \ + scripts/ComponentCacher.js \ + scripts/ApplicationRegistry.js \ + scripts/ItemFactory.js \ + +scriptFiles.files += $$SCRIPT_FILES +scriptFiles.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH/scripts + +# qmldir +QMLDIR_FILE = qmldir +qmldirFile.files += $$QMLDIR_FILE +qmldirFile.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH + +# show in QtCreator +OTHER_FILES += $$QML_IMPORT_FILES \ + $$SCRIPT_FILES \ + qmldir \ + + +INSTALLS += qmlImportFiles scriptFiles qmldirFile target + diff --git a/src/interpreter/imports/qtsystemtest/scripts/ApplicationRegistry.js b/src/interpreter/imports/qtsystemtest/scripts/ApplicationRegistry.js new file mode 100644 index 0000000..9566179 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/ApplicationRegistry.js @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +Js.include_check(ApplicationRegistry === undefined, 'ApplicationRegistry.js already included'); + +Js.require('ComponentCacher.js'); +Js.require('Exception.js'); + +// create a factory and make that singleton +var ApplicationRegistry = function() { + var Factory = ComponentCacher.extend(function() { + this._super(); + this.setDefaultItemFile('../qml/Application.qml'); + + function applicationForKey(key) { + var component = this.componentForKey(key); + if (component === null) { + throw new Qtt.Fail('Error creating an Application handler for: ' + key + + ' using file: ' + this.fileForKey(key) , 2); + } + return component; + } + + + return { + applicationForKey: applicationForKey + }; + }); + return new Factory(); +}(); diff --git a/src/interpreter/imports/qtsystemtest/scripts/Class.js b/src/interpreter/imports/qtsystemtest/scripts/Class.js new file mode 100644 index 0000000..e59c7f7 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/Class.js @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +Js.include_check(Class.isFn === undefined, 'Class.js already included'); + +function Class(){ }; + +Class.DebugEnabled = false; +//Class.DebugEnabled = true; +Class.debug = function debug() { + if (Class.DebugEnabled) { + var str = ''; + for (var i=0; i<arguments.length; i++) { + str += arguments[i]; + } + console.log(str); + } +} + +Class.isFn = function(fn) { return typeof fn === 'function'; }; +Class.isBothFn = function (fn, superFn) { + var debug = Class.debug; + debug('\t is fn ', (fn ? fn.name: undefined), ', superFn: ', (superFn ? superFn.name : undefined) , ' is a function'); + return Class.isFn(fn) && Class.isFn(superFn) +}; + +Class.create = function(superClass, constructor) { + // if 2 args are passed, then SuperClass is specified and else it is of the + // from X.extend(definition-of-y) + // SuperClass need not be specified in that case, SubClass definition will be + // in the SuperClass arg + var SuperClass, SubClass, + debug = Class.debug; + if( arguments.length == 1) { + SuperClass = this; + SubClass = superClass; // has the definition + + }else { + SubClass = constructor; + SuperClass = superClass; + } + debug('Superclass is ', SuperClass.name); + + // NOTE constructor.name for the object created using this is empty + var definition = function () { + // about to call the constructor of this object, so the super classes are already + // constructor and the prototype of this is already set. + var myProto = this; + debug('My Prototype already has : ', Object.keys(myProto)); + // define _super before calling the construtor + this._super = SuperClass; // _super from constructor should work + + // constructor returns the exported public members + var publicMembers = SubClass.apply(this, arguments); // returns the exported members + debug('Exported members are: ', Object.keys(publicMembers)); + + for (var name in publicMembers) { + debug('\t Testing if ', name, ' should be overridden'); + (function(member, superMember) { + // overide the definition in my proto if required + if ( Class.isFn(member) ) { + var s = Class.isFn(superMember) ? superMember : undefined; + myProto[name] = function() { + var tmp = this._super; + this._super = s; + var ret = member.apply(this, arguments); + this._super = tmp; + return ret; + } + } else { + myProto[name] = member; + } + + })(publicMembers[name], myProto[name]); + } + }; // definition + definition.prototype = new SuperClass; // establish prototype chain + definition.prototype.constructor = definition; // and the ctor + definition.extend = SuperClass.extend || Class.create + return definition; + +}; // Class.create + diff --git a/src/interpreter/imports/qtsystemtest/scripts/ComponentCacher.js b/src/interpreter/imports/qtsystemtest/scripts/ComponentCacher.js new file mode 100644 index 0000000..781914f --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/ComponentCacher.js @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +Js.include_check(ComponentCacher === undefined, 'ComponentCacher.js already included'); +Js.require('Exception.js'); +Js.require('Class.js'); + +var OriginalCallerDepth = 5; // explaination below +/* + the stack for factory.register(foo, bar) or this.setDefaultItemFile would lead to + 1. something.register() + 2. class.call (register) + 3. this.register + 3. absolutePathOf + 4. inside register + to get the file that called register, we would have to traverse back in stack 5 levels +*/ + + function absolutePathOf(path) { + if ( !Qt.qst.isRelativePath(path) ) { + return path; + } + // get the filename that called applicaton.register + var stack = Js.Engine.callSite(OriginalCallerDepth); + var callerFilePath = stack.last().fileName; + var lastSlash = callerFilePath.lastIndexOf('/'); + return callerFilePath.left(lastSlash + 1) + path; + } + + +var ComponentCacher = Class.create(function() { + var __registry = { + //key: qmlFile + }; + + var __componentsCache = { + //key: Component + }; + var __defaultItemFile; + var fallbackToDefault = true; + + function setDefaultItemFile(qmlFilePath) { + __defaultItemFile = absolutePathOf(qmlFilePath); + } + + function unregister(key) { + if (key in __registry) { + delete __registry[key]; + } + if (key in __componentsCache) { + delete __componentsCache[key]; + } + } + + function register(key, qmlFilePath) { + __registry[key] = absolutePathOf(qmlFilePath); + } + + function fileForKey(key) { + if (key in __registry) { + return __registry[key]; + } + if ( !fallbackToDefault) { + return null; + } + + if ( !__defaultItemFile) { + throw new Qtt.Error( 'Error: ComponentCacher - unable to find a file for ' + key); + } + return __defaultItemFile; + } + + function componentForKey(key) { + var qmlFile = this.fileForKey(key); + if (qmlFile === null) { + return null; + } + + var component = null; + if ( ! (qmlFile in __componentsCache)) { + + component = Qt.createComponent(qmlFile) + // HACK ... 1 means Component.Ready I want to access Component.Ready here... + if (component.status !== 1) { + // fix me ... Change error to accept msg and formatted msg, + throw new Qtt.Error('Component creation failed : ' + component.errorString(), 2); + } + __componentsCache[qmlFile] = component; + } else { + component = __componentsCache[qmlFile]; + } + + return component; + } + function setFallbackToDefault(value) { + fallbackToDefault = value; + } + + return { + + setFallbackToDefault: setFallbackToDefault, + setDefaultItemFile: setDefaultItemFile, + fileForKey: fileForKey, + register: register, + unregister: unregister, + componentForKey: componentForKey, + keys: function() { return Object.keys(__registry); }, + }; +}); diff --git a/src/interpreter/imports/qtsystemtest/scripts/Console.js b/src/interpreter/imports/qtsystemtest/scripts/Console.js new file mode 100644 index 0000000..3ddb6f5 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/Console.js @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +Js.include_check(Topic === undefined, 'Console.js already included'); +Js.require('Class.js'); + +var Topic = Class.create(function(name, parent) { + parent = parent || null; + var _subtopic = { + // name: Topic + }; + var loglevel = { + debug: {enabled: false, activate: false }, + warn: {enabled: false, activate: false }, + } + + var DebugEnabled = false; + function stringify() { + stringify.sb = stringify.sb || new SourceBuilder(); + var sb = stringify.sb; + var str = ''; + for (var i =0; i<arguments.length; ++i) { + str += sb.sourceFor(arguments[i]); + } + return str; + } + function _debug() { + if (DebugEnabled) { + print('Console[Debug]: ', stringify.apply(null, arguments)); + } + } + + function path() { + var parents = [name]; + for (var p = parent; p !== null; p = p.parent) { + _debug('....... type: ', typeof(p), ' ctor:', p.constructor.name ); + parents.unshift(p.name); + } + return parents; + } + + function debug(m) { + if ( loglevel.debug.activate) { + return; + } + + if (arguments.length === 0) { + return; + } + _debug('..................', name); + + function log() { + var parents = path(); + var location = Js.Engine.callSite(4).last(); + var filePath = location.fileName; + var file = filePath.right(filePath.length - filePath.lastIndexOf('/') -1); + console.log(' ', Date.timestamp(), ', ' // timestamp + + file + '(' + location.lineNumber + ') :', // file (linenumber) + parents.join('.'), ': ' + stringify.apply(null, arguments)); // topic.topic.... : msg + } +// log.apply(null, arguments); + } + + function topic(t) { + _debug('Already existing ones: ', Object.keys(_subtopic) ); + if ( t in _subtopic ){ + return _subtopic[t] + } + _debug('Creating a topic: ', name, '.' , t); + var sub = new Topic(t, this); + _subtopic[t] = sub; + _debug(Object.keys(_subtopic)); + return sub; + } + + function enable() { + + } + + return { + debug: debug, + topic: topic, + name: name, + parent: parent, + enable: enable, + }; +}); + + +var Console = new Topic('Console'); diff --git a/src/interpreter/imports/qtsystemtest/scripts/Datatype.js b/src/interpreter/imports/qtsystemtest/scripts/Datatype.js new file mode 100644 index 0000000..1b2fa7a --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/Datatype.js @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +/// FIXME: Qt5, Error.stack can be enabled by calling prepareStack once +Object.defineProperties(Error.prototype, { + __addStack: { + value: function(level) { + if (this.stack) { + return; + } + + var stack = level === undefined ? Qt.qst.stack() : Qt.qst.stack(level); + // this function (top of the stack) with the right values from Error + stack[0] = { + fileName: this.fileName, + lineNumber: this.lineNumber, + functionName: '<unknown function>' + }; + this.stack = stack; + } + } +}); + + +Object.defineProperties(Array.prototype, { + isEmpty: { + value: function() { return this.length === 0; } + }, + + clear: { + value: function() { this.length = 0; } + }, + + last: { + value: function() { return this[this.length-1]; } + }, + + first: { + value: function() { return this[0]; } + }, + + contains: { + value: function(element) { + if (this === undefined || this === null) { + throw new TypeError(); + } + return this.indexOf(element) !== -1; + } + }, + + remove: { + value: function(from, to) { + var rest = this.slice((to || from) + 1 || this.length); + this.length = from < 0 ? this.length + from : from; + return this.push.apply(this, rest); + } + } +}); + + +Object.defineProperties(String.prototype, { + startsWith: { + value: function(prefix) { return this.indexOf(prefix) === 0; } + }, + + endsWith: { + value: function(suffix) { + return this.indexOf(suffix, this.length - suffix.length) !== -1; } + }, + + left: { + value: function(len) { return this.substring(0, len); } + }, + + right: { + value: function(len) { return this.substring(this.length- len); } + }, + + repeat: { + value: function( num ) { return new Array( num + 1 ).join(this); } + }, + trim: { + value: function() { return this.replace(/^\s+|\s+$/g, ""); } + } +}); + + +Date.timestamp = function() { + function pad(n, places) { + var str = ''+n; + if ( str.length >= places) { + return str; + } + return '0'.repeat(places - str.length) + str; + } + var now = new Date(); + var timestamp = pad(now.getHours(), 2) + ':' + + pad( now.getMinutes(), 2) + ':' + + pad( now.getSeconds(), 2) + ' - ' + + pad( now.getMilliseconds(), 3); + return timestamp; +} diff --git a/src/interpreter/imports/qtsystemtest/scripts/Exception.js b/src/interpreter/imports/qtsystemtest/scripts/Exception.js new file mode 100644 index 0000000..25fdafb --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/Exception.js @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +Js.include_check(Qtt === undefined, 'Exception.js already included'); +Js.require('Class.js'); +Js.require('Console.js'); + +var Qtt = function(){ + var QttDebug = Console.topic('Qtt'); + + var Status = { + Error: 'error', + Passed: 'passed', + Failed: 'failed', + Skipped: 'skipped', + Aborted: 'aborted', + Untested: 'untested', + }; + + var QttError = Class.create(function QttError(msg, discardLevel) { + discardLevel = (discardLevel || 0 ) + 2; + this.name = arguments.callee.name; + this.stack = Qt.qst.stack(); + Js.discardCallSites.call(this, discardLevel); + return { + status : Status.Error, + type: 'QttError', + message: msg, + __addStack : function(){}, + discardCallSites: Js.discardCallSites, + toString: function() { return this.message; } + }; + }); + + var Skip = QttError.extend(function Skip(msg, discardLevel) { + discardLevel = (discardLevel || 0 ) + 2; + this._super(msg, discardLevel); + this.type = 'Skip'; + this.status = Status.Skipped; + return { }; + }); + + var Abort = QttError.extend(function Abort(msg, discardLevel) { + discardLevel = (discardLevel || 0 ) + 2; + this._super(msg, discardLevel); + this.type = 'Abort'; + this.status = Status.Aborted; + return { }; + }); + + var Fail = QttError.extend(function Fail(msg, discardLevel) { + discardLevel = (discardLevel || 0 ) + 2; + this._super(msg, discardLevel); + this.type = 'Fail'; + this.status =Status.Failed; + return { }; + }); + + + return { + Error: QttError, + Skip: Skip, + Fail: Fail, + Abort: Abort, + Status: Status + }; +}(); diff --git a/src/interpreter/imports/qtsystemtest/scripts/Expect.js b/src/interpreter/imports/qtsystemtest/scripts/Expect.js new file mode 100644 index 0000000..fc7cee0 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/Expect.js @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +Js.include_check(Expectation === undefined, 'Expect.js already included'); +Js.require('Class.js'); +Js.require('Exception.js'); + +var Expectation = Class.create(function(actual, value){ + var ok = value === undefined ? true : value; + + function _not_() { + return ok === true? ' ' : ' not '; + } + + function toBeBetween(low, high){ + if ( ( low < actual && actual < high) !== ok) { + var msg = 'Expected actual value to be' + _not_() + 'between low and high value.'; + var formatted = 'Expected (' + actual + ') to be' + _not_() + + 'between (' + low + ', ' + high + ')'; + var e = new Qtt.Fail(msg, formatted, 2); + e.meta = { + actual: actual, + low: low, + high: high + }; + throw e; + } + } + + function toBe(expectation){ + if ( (actual === expectation) !== ok) { + var msg = 'Expected actual value to be' + _not_() + 'expected value.'; + var e = new Qtt.Fail(msg, 2); + e.meta = { + actual: actual, + expected: expectation + }; + e.formatted = 'Expected (' + actual + ') to be' + _not_() + + '(' + expectation + ')'; + throw e; + } + } + + function toThrow(expection){ + } + + function instanceOf(expectation){ + if( (actual instanceof expectation) !== ok) { + var msg = 'Expected actual value to be' + _not_() + 'an instance of expected type.'; + var e = new Qtt.Fail(msg, 2); + e.meta = { + actual: actual, + expected: expectation.name + }; + e.formated = 'Expected (' + actual + ') to be' + _not_() + + 'instance of (' + expectation.name + ')'; + throw e; + } + } + + + return { + toBe: toBe, + toBeBetween: toBeBetween, + instanceOf: instanceOf + } +}); + + +function expect(actual) { + var x = new Expectation(actual); + x.not = new Expectation(actual, false) + return x; +} diff --git a/src/interpreter/imports/qtsystemtest/scripts/Functional.js b/src/interpreter/imports/qtsystemtest/scripts/Functional.js new file mode 100644 index 0000000..ddce3f8 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/Functional.js @@ -0,0 +1,298 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +/*! + Returns a function that suppresses throwing the expection when the + function \a being wrapped either fails or throws an exception. + + The exception generated is stored in an exception property. + The failed property indicates if the function threw an exception. + + Usage: + \code + var itemExists = findUniqueItem.nothrow(); + var item = itemExists({QMLTYPE: 'QQuickItem'}); + + if (!itemExists.failed) { + print(item.property('x')); + } else { + // item is undefined + fail(itemExists.exception.message); + } + \endcode +*/ +Function.prototype.nothrow = function nothrow() { + var fn = this; + function nothrow() { + try { + var result = fn.apply(this, arguments); + arguments.callee.failed = false; + return result; + } catch(e) { + arguments.callee.exception = e; + arguments.callee.failed = true; + } + return undefined; + } + + // reduce nothrow().nothrow() to a single nothrow + return fn.toString() === nothrow.toString() ? fn : nothrow; +} + +/*! + Returns a function that retries the \a fn after every \a interval milliseconds + until it doesn't result in a 'fail' or times out after \a timeout milliseconds. + + Usage: + \code + var item = findUniqueItem.retry({timeout: 1000, interval: 250}); + var obj = item({QMLTYPE: 'Button', QMLID: 'aButton'}) + \endcode + + is equal to writing + + \code + var obj; + var excp; + var timeout = 1000; + var poll = 250; + try { + expect( function() { + try { + obj = findUniqueItem({QMLTYPE: 'Button', QMLID: 'aButton'}) + return true; + }catch(e) { + excp = e; + } + return false; + }, timeout, Math.floor(timeout/poll)); + } catch(e) { + fail(excp.message, ' after ', timeout, 'ms' ); + } + \endcode + +*/ +//Function.prototype.retry = function(config) { +// if (!config){ +// throw new Error('Missing args: no timeout and interval specified. \n' +// + 'Usage retry({timeout: <timeout>, interval: <interval> })'); +// } + +// if (typeof(config.timeout) !== 'number') { +// throw new TypeError('timeout: not a number \n' +// + 'Usage retry({timeout: <timeout>, interval: <interval> })'); +// } +// if (typeof(config.interval) !== 'number') { +// throw new TypeError('interval: not a number \n' +// + 'Usage retry({timeout: <timeout>, interval: <interval> })'); +// } + +// var method = this.nothrow(); + +// function retry() { +// // store the original method +// retry.original = this; +// var result; +// var args = Private.Utils.makeArray(arguments) ; +// var passes = Private.Utils.poll(function autoPoll() { +// result = method.apply(this, args); +// return method.failed === false; +// }, config.timeout, config.interval); + +// if (!passes) { +// fail(method.exception.message, ' after ', config.timeout, ' ms'); +// } +// return result; +// } + +// // error on retry().retry(); +// if (this.toString() === retry.toString()) { +// var originalMethod = this.original.name === '' ? '[anonymous]' +// : this.original.name; +// return new Error('Cannot create a retry version of already retry version of method: ' +// + originalMethod); +// } +// return retry; +//} + +/*! + Partially intialize first few arguments of a function + + \code + function sum(a, b) { return a+b;}; + var add5 = sum.curry(5); + var x = add5(10); // x = 15 now + \endcode + +*/ +Function.prototype.bind = function(scope) { + var fn = this; + var toArray = Array.prototype.slice; + var args = toArray.call(arguments); + var scope = args.shift(); + return function() { + return fn.apply(scope, args.concat(toArray.call(arguments))); + }; +}; + +Function.prototype.curry = function() { + var fn = this; + var toArray = Array.prototype.slice; + var args = toArray.call(arguments); + return function() { + return fn.apply(this, args.concat( toArray.call(arguments))); + }; +}; + + +/*! + Partially intialize arguments of a function, using undefined as placeholders for + arguments to be filled in later. + + \code + function sum(a, b) { return a+b;}; + var add5 = sum.partial(undefined, 5); + + var x = add5(10); // x = 15 now + \endcode + +*/ +Function.prototype.partial = function(){ + var fn = this; + var toArray = Array.prototype.slice; + var partialArgs = toArray.call(arguments); + return function(){ + var args = partialArgs.slice(); // copy partial + var arg = 0; + for ( var i = 0; i < args.length && arg < arguments.length; i++ ) { + if ( args[i] === undefined ) { + args[i] = arguments[arg++]; + } + } + return fn.apply(this, args); + }; +} + +var FunctionHelper = function() { + /*! + Validate number of the arguments passed to a function \a fn, throws an exception + if the number of args passed to the \a fn is less than the minArgsRequired. + + if no minimumArgs is passed, uses the number of named arguments in \a fn + + Usage: + \code + var findItems = FunctionHelper.validateArgs(function findItems( filter, fetch, mode) { + }, 1); // ensures 1 arg is passed when findItems + \endcode + */ + function validateArgs(fn, minArgsRequired) { + if( typeof(fn) !== 'function' || fn.name === '' ) { + throw new Error('The first argument to validateArgs should be a named function'); + } + minArgsRequired = minArgsRequired || fn.length; + return function() { + if (arguments.length < minArgsRequired) { + fail(fn.name, ' expects atleast ', minArgsRequired, + ' arguments, whereas only ', arguments.length, ' passed'); + } + return fn.apply(this, arguments) + }; + } + + /*! + Deprecates a function with the name \a fnName and replaced by \a replacedBy. Would print of the + msg if one is passed or generates one. + + Usage: + \code + var findWidget = FunctionHelper.deprecate('findWidget', findItems); + or + var findWidget = FunctionHelper.deprecate('findWidget', findItems, + 'Usage of findWidget is deprecated, use findItems instead') + var findWidget = FunctionHelper.deprecate('findWidget', + {replacedBy: findItems, name: 'findItems'}); + \endcode + */ + function deprecate(fnName, replacedBy, msg, config) { + msg = msg || 'Usage of deprecated function: ' + fnName + ', use ' + replacedBy.name + ' instead.'; + config = config || { + FailOnInvoke : false + }; + return function() { + if ( config.FailOnInvoke ) { + throw new Error('Error: ' + msg); + } + warn(msg); + // use the function if replacedBy is a Function else if it an object, then use the replacedBy property + var fn = replacedBy instanceof Function ? replacedBy : replacedBy.replacedBy; + return fn.apply(this, arguments); + }; + } + + + /*! + Helper function that wraps an object of type anything other than function + inside an anonymous function, invoking which returns the object; + + Usage: + \code + var x = 10; + x = FunctionHelper.toFunction(x); + var y = x(); // y is 10; + \endcode + */ + function toFunction(x) { + return typeof(x) === 'function' ? x : function(){ return x;}; + } + + function isFunction(x) { + return typeof(x) === 'function'; + } + return { + validateArgs: validateArgs, + deprecate: deprecate, + toFunction: toFunction, + isFunction: isFunction + }; +} diff --git a/src/interpreter/imports/qtsystemtest/scripts/ItemFactory.js b/src/interpreter/imports/qtsystemtest/scripts/ItemFactory.js new file mode 100644 index 0000000..93c2a2f --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/ItemFactory.js @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// create a factory and make that singleton +var ItemFactory = function() { + /// FIXME: itemshandlers can be resitered or unregistered at run time + /// so, the keyForObject.cache would get invalidated + var Factory = ComponentCacher.extend(function() { + this._super(); + this.setFallbackToDefault(false); + var _handlerForItemCache = {}; + + function keyForObject(obj, application) { + var key = obj._type_; + + function handlerExists(k) { + if ( this.fileForKey(k) !== null ) { + handlerExists.key = k; + return true; + } + return false; + } + + // perfect match + if ( handlerExists.call(this, key) ) { + return key; + } + + if ( key in _handlerForItemCache) { + return _handlerForItemCache[key]; + } + + var tree = application.__inheritanceTree(obj); + tree.shift(); + var ret = tree.some(handlerExists, this) + ? handlerExists.key + : null; + _handlerForItemCache[key] = ret; + return ret; + } + + function itemForKey(obj, props) { + if ( !('_type_' in obj ) ) { + throw new Qtt.Fail('Invalid object passed to handlerForObject: _type_ does not exist ', 2); + } + + var key = keyForObject.call(this, obj, props.application); + if (key === null) { + throw new Qtt.Fail('Error finding a Item handler for: ' + obj._type_ , 2); + } + var component = this.componentForKey(key); + if (component === null) { + throw new Qtt.Fail('Error creating an Item handler for: ' + obj._type_ , 2); + } + return component; + } + + function register(k, path) { + path = absolutePathOf(path); + this._super(k, path); + _handlerForItemCache = {}; + } + + function unregister(key) { + this._super(key); + _handlerForItemCache = {}; + } + + return { + handlerForObject: itemForKey, + register: register, + unregister: unregister + }; + }); + var singleton = new Factory(); + singleton.register('QObject', '../qml/itemhandlers/QstObject.qml'); + singleton.register('QWidget', '../qml/itemhandlers/QstWidget.qml'); + return singleton; +}(); diff --git a/src/interpreter/imports/qtsystemtest/scripts/JsCore.js b/src/interpreter/imports/qtsystemtest/scripts/JsCore.js new file mode 100644 index 0000000..30b3736 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/JsCore.js @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +if( typeof(Js) !== 'undefined') { + Js.include_check(Js === undefined, 'JsCore.js already included'); +} + +Qt.include('Datatype.js') +Qt.include('Functional.js'); + +var Js = function() { + + var Core = { + Error: { + maxStack: 17 + } + }; + +// var DebugEnabled = true; + var DebugEnabled = false; + function _debug() { + var str = '', + arg, + i, + now, + timestamp; + + if (!DebugEnabled) { + return; + } + + for (i =0; i<arguments.length; ++i) { + arg = arguments[i] + if (arg != null) { + str += arg.toString(); + } else { + str += 'undefined' + } + } + console.log(Date.timestamp(), 'JsCore[Debug]:', str); + } + + function discardCallSites(num) { + num = num || 1; + if (!this.stack) return; + var stack = this.stack; + if( stack.length < num ) { + _debug(' Error: insufficient stack depth'); + throw new Error('Insufficient stack depth'); + } + while ( num-- > 0 ) { + this.stack.shift(); + } + } + + var JsError = (function() { + function JsError(msg) { + Error.call(this); + this.message = msg; + this.name = arguments.callee.name; + this.stack = Qt.qst.stack(); + this._discardCallSites(); + } + JsError.prototype = new Error(); + JsError.prototype._discardCallSites = discardCallSites; + return JsError; + })(); + + var IncludeError = (function() { + function IncludeError(msg) { + JsError.call(this, msg); + _debug(' Creating include error :', this.message); + this.name = arguments.callee.name; + this._discardCallSites(); + } + + IncludeError.prototype = new JsError(); + IncludeError.prototype.constructor = IncludeError; + return IncludeError; + })(); + + function require(filename) { + require.level = require.level || 0; + + function repeat(c, t){ + var str = ''; + for(var i=0; i< t; ++i){ + str += c; + } + return str; + } + var spaces = repeat(' ', require.level*4); + _debug('including .... '+ spaces + (require.level !==0? '+--': '') + '[', filename, ']'); + + require.level++; + try { + var include = Qt.include(filename); + } catch(e) { + console.log('Exception caught loading', filename, e.message); + console.log('Stack', e.stack.join('\n')); + } + + if( include && include.status === include.EXCEPTION) { + var ex = include.exception; + if (!(ex instanceof IncludeError) ) { + console.log('Exception including : ', filename, ': ', ex.message, ex.filename); + if ( ex.stack instanceof Array) { + ex.stack.forEach( function(cs) { + console.log( cs.fileName, ':', s.lineNumber); + }); + } + throw ex; + } else { + _debug('Exception including : ', filename, " exception: ", ex); + } + } + // _debug('including .... [', filename, ']done'); + require.level--; + } + + function include_check(condition, msg) { + if(!condition) { + throw new IncludeError(msg); + } + } + + + var JsEngine = function() { + function callSite(depth) { + var stack = depth === undefined + ? Qt.qst.stack() + : Qt.qst.stack(depth++); + return stack; + } + + function currentFile() { + var cs = callSite(3); + return cs.last().fileName; + } + + function currentPath() { + var cs = callSite(3); + var filePath = cs.last().fileName; + var fileStart = filePath.lastIndexOf('/'); + return filePath.substring(fileStart + 1); + } + + function currentLine() { + var cs = callSite(3); + return cs.last().lineNumber; + } + + return { + currentPath: currentPath, + currentFile: currentFile, + currentLine: currentLine, + callSite: callSite + } + }(); + + return { + require: require, + include_check: include_check, + Core: Core, + Error: JsError, + discardCallSites: discardCallSites, + Engine: JsEngine, + _debug: _debug, + } +}(); + + +function assert(condition, msg) { + if (!condition) { + throw new JsError(msg); + } +} diff --git a/src/interpreter/imports/qtsystemtest/scripts/QstCore.js b/src/interpreter/imports/qtsystemtest/scripts/QstCore.js new file mode 100644 index 0000000..da422be --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/QstCore.js @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +Qt.include('JsCore.js'); +Js.require('SourceBuilder.js'); + +Js.require('Class.js'); +Js.require('Console.js'); +Js.require('Exception.js'); +Js.require('Expect.js'); +Js.require('ApplicationRegistry.js'); +Js.require('ItemFactory.js'); diff --git a/src/interpreter/imports/qtsystemtest/scripts/SourceBuilder.js b/src/interpreter/imports/qtsystemtest/scripts/SourceBuilder.js new file mode 100644 index 0000000..014f118 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/SourceBuilder.js @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +Js.include_check(SourceBuilder === undefined, 'SourceBuilder.js already included'); + +var SourceBuilder = function() { + var DebugEnabled = false; + function debug(enabled){ + if (enabled && DebugEnabled) { + console.log( msg(Array.prototype.slice.call(arguments)) ); + } + } + + function msg() { + var str = ''; + for (var i =0; i<arguments.length; i++) { + var arg = arguments[i]; + str += arg; + } + return str; + } + + // converters + function arrayToString(a, level) { + if (a.length === 0 ) { + return '[]'; + } + + var str = '['; + var quote; + for (var i =0; i < a.length; ++i) { + quote = typeOf(a[i]) === 'String' ? "'" : ''; + str += quote + stringify(a[i]) + quote; + str += i < (a.length -1) ? ', ' : ']' + } + return str; + } + + function objectToString(obj, level) { + debug(DebugEnabled && msg(arguments.callee.name)); + + // if toString for the object is overridden then, use that version + if ( obj.toString !== Object.prototype.toString) { + return obj.toString(); + } + + var indentation = indentText.repeat(level); + var propertyCount = Object.keys(obj).length; + var terminator = propertyCount > 1 ? '\n': '' + var propertyIndentation = propertyCount > 1 ? (indentation + indentText) : '' + var objectType = typeOf(obj) + + function stripObject(o) { + return o === 'Object' ? '' : o; + } + // don't print 'Object', if the type is Object + var str = stripObject(objectType) + '{' + terminator; + var contents = ''; + for (var prop in obj) { + // add a quote if the value is of type string + var quote = typeof(obj[prop]) == 'string' ? "'" : ''; + + contents += propertyIndentation + prop + ': ' + + quote + stringify(obj[prop], level+1) + quote + + ',' + terminator; + } + str += contents.slice(0, -(1 + terminator.length)); // remove the , at the end of contents + str += terminator + indentation + '}' + terminator; + return str; + } + + function typeOf(o) { + debug(DebugEnabled && msg(arguments.callee.name)); + if ( o === undefined ) return 'undefined'; + if ( o === null ) return 'null'; + + // we have a valid object + var ctor = o.constructor.name; + return ctor.length === 0 ? 'Object' // no Object for a generic object + : ctor; + } + + function sameObject(x){ return x; } + function toString(x){ return x.toString(); } + function qtuitestWidget(x){ return 'QtUiTestWidget( ' + x.toString() + ' )'; } + function qtuitestObject(x){ return 'QtUiTestObject( ' + x.toString() + ' )'; } + + // converts obj to string + function stringify(obj, level) { + debug(DebugEnabled && msg(arguments.callee.name)); + debug(DebugEnabled && msg('Finding type of :', obj) ); + level = level || 0; + + var typeConverters = { + 'null': typeOf, + 'undefined': typeOf, + 'Number': toString, + 'Boolean': toString, + 'Function': toString, + 'String': sameObject, + 'Array': arrayToString, + 'QtUiTestWidget': qtuitestWidget, + 'QtUiTestObject': qtuitestObject, + 'Object': objectToString + }; + + var type = typeOf(obj); + if ( type in typeConverters) { + debug(DebugEnabled && msg('Found converter for type: ' + type + + ', using converter :' + typeConverters[type].name)); + return typeConverters[type](obj, level); + } + debug(DebugEnabled && msg('No converters Found for type: ' + type) ); + // if no converters are registered, treat the type as an object and print it + return objectToString(obj, level); + } + + var indentText = ' ';// .repeat(4); // 4 spaces for each level + return { + sourceFor: function sourceFor(obj) { + return stringify(obj); + } + }; + +}// SourceBuilder + +function stringify() { + stringify.sb = stringify.sb || new SourceBuilder(); + var str = ''; + for (var i =0; i< arguments.length; ++i) { + str += stringify.sb.sourceFor(arguments[i]); + } + return str; +} diff --git a/src/interpreter/imports/qtsystemtest/scripts/api.js b/src/interpreter/imports/qtsystemtest/scripts/api.js new file mode 100644 index 0000000..f9cf7a1 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/scripts/api.js @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +Qt.include('JsCore.js'); +Js.include_check(Private === undefined, 'api.js already included'); + + +function api() { + var component = Qt.createQmlObject( + 'import QtQuick 2.0;' + + 'import QtUiTest 1.0;' + + 'TestMethod {}', Js.__testRoot); + return component; +} + +Js._debug(' api.js ... loaded'); diff --git a/src/interpreter/imports/qtsystemtest/src/imports.cpp b/src/interpreter/imports/qtsystemtest/src/imports.cpp new file mode 100644 index 0000000..e8f1529 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/imports.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "imports.h" +#include "qstcoreapi.h" +#include "qstutils.h" +#include "qstlocalprocess.h" +#include <QtDeclarative> + +#include <QtSystemTest/QstConnection> +#include <QtSystemTest/QstConnectionManager> + +void QtSystemTestQmlModule::registerTypes(const char *uri) +{ + Q_ASSERT(QLatin1String(uri) == QLatin1String("QtSystemTest")); + qmlRegisterType<QstCoreApi>( uri, 1, 0, "CoreApi"); + qmlRegisterType<QstConnection>( uri, 1, 0, "Connection"); + qmlRegisterType<QstLocalProcess>( uri, 1, 0, "LocalProcess"); +} + +void QtSystemTestQmlModule::initializeEngine(QDeclarativeEngine *e, const char *uri) +{ + qDebug() << Q_FUNC_INFO << "Registering connection manager and Utils" << uri; + e->rootContext()->setContextProperty("ConnectionManager", new QstConnectionManager()); + e->rootContext()->setContextProperty("Utils", new QstUtils()); +} + +Q_EXPORT_PLUGIN2(qtsystemtestplugin, QtSystemTestQmlModule); diff --git a/src/interpreter/imports/qtsystemtest/src/imports.h b/src/interpreter/imports/qtsystemtest/src/imports.h new file mode 100644 index 0000000..4a41b48 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/imports.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef IMPORTS_H +#define IMPORTS_H + +#include <QDeclarativeExtensionPlugin> + +class QDeclarativeEngine; + +class QtSystemTestQmlModule : public QDeclarativeExtensionPlugin +{ + Q_OBJECT + +public: + virtual void registerTypes(const char *uri); + void initializeEngine(QDeclarativeEngine *, const char *); +}; + +#endif // IMPORTS_H diff --git a/src/interpreter/imports/qtsystemtest/src/qstcoreapi.cpp b/src/interpreter/imports/qtsystemtest/src/qstcoreapi.cpp new file mode 100644 index 0000000..979070d --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/qstcoreapi.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstcoreapi.h" + +#include <QtCore/QDebug> +#include <QtTest/QTest> + +QstCoreApi::QstCoreApi(QObject *parent) : + QObject(parent) +{ +} + +void QstCoreApi::sleep(int ms) +{ + QTest::qSleep(ms); +} + diff --git a/src/interpreter/imports/qtsystemtest/src/qstcoreapi.h b/src/interpreter/imports/qtsystemtest/src/qstcoreapi.h new file mode 100644 index 0000000..4efc473 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/qstcoreapi.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTCOREAPI_H +#define QSTCOREAPI_H + +#include <QtCore/QObject> +#include <QtCore/QVariantMap> + +class QSystemTestMaster; + +class QstCoreApi : public QObject +{ + Q_OBJECT +public: + explicit QstCoreApi(QObject *parent = 0); + + static const QLatin1String signatureProperty; + static const QLatin1String appIdProperty; + static const QLatin1String widgetSpecifierProperty; + +signals: + +public slots: + void sleep(int ms); + bool connectApplication(const QString &host, int port); + + private: + + QSystemTestMaster *m_test_app; +}; + +#endif // QSTCOREAPI_H diff --git a/src/interpreter/imports/qtsystemtest/src/qstlocalprocess.cpp b/src/interpreter/imports/qtsystemtest/src/qstlocalprocess.cpp new file mode 100644 index 0000000..cf60379 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/qstlocalprocess.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstlocalprocess.h" + +#include <QtCore/QTextCodec> + +QstLocalProcess::QstLocalProcess(QObject *parent) : + QProcess(parent), + m_inputCodec(0), + m_outputCodec(0), + m_outputDecoder(0), + m_errorDecoder(0), + m_outputMode(DeviceOutput) +{ + m_inputCodec = QTextCodec::codecForLocale(); + m_outputCodec = QTextCodec::codecForLocale(); + + connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(forwardFinished(int, QProcess::ExitStatus))); +} + +void QstLocalProcess::start(const QString &program, const QStringList &arguments) +{ + QProcess::start(program, arguments, QIODevice::ReadWrite); +} + +bool QstLocalProcess::waitForStarted(int msecs) +{ + return QProcess::waitForStarted(msecs); +} + +bool QstLocalProcess::waitForFinished(int msecs) +{ + return QProcess::waitForFinished(msecs); +} + +bool QstLocalProcess::waitForReadyRead(int msecs) +{ + return QProcess::waitForReadyRead(msecs); +} + +void QstLocalProcess::closeWriteChannel() +{ + QProcess::closeWriteChannel(); +} + +QProcess::ProcessState QstLocalProcess::state() const +{ + return QProcess::state(); +} + +QProcess::ExitStatus QstLocalProcess::exitStatus() const +{ + return QProcess::exitStatus(); +} + +int QstLocalProcess::exitCode() const +{ + return QProcess::exitCode(); +} + +QString QstLocalProcess::inputCodec() const +{ + return QString::fromLatin1(m_inputCodec->name()); +} + +void QstLocalProcess::setInputCodec(const QString &name) +{ + m_inputCodec = QTextCodec::codecForName(name.toLatin1().constData()); +} + +QString QstLocalProcess::outputCodec() const +{ + return QString::fromLatin1(m_outputCodec->name()); +} + +void QstLocalProcess::setOutputCodec(const QString &name) +{ + if (name == outputCodec()) + return; + m_outputCodec = QTextCodec::codecForName(name.toLatin1().constData()); + delete m_outputDecoder; + delete m_errorDecoder; + m_outputDecoder = 0; + m_errorDecoder = 0; +} + +void QstLocalProcess::setOutputMode(OutputMode mode) +{ + if (mode == m_outputMode) + return; + m_outputMode = mode; + if (m_outputMode == DeviceOutput) { + disconnect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(updateOutputBuffer())); + disconnect(this, SIGNAL(readyReadStandardError()), this, SLOT(updateErrorBuffer())); + } else { + setProcessChannelMode(SeparateChannels); + connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(updateOutputBuffer())); + connect(this, SIGNAL(readyReadStandardError()), this, SLOT(updateErrorBuffer())); + updateOutputBuffer(); + updateErrorBuffer(); + } +} +void QstLocalProcess::updateOutputBuffer() +{ + QByteArray bytes = readAllStandardOutput(); + if (!bytes.isEmpty()) { + if (!m_outputDecoder) + m_outputDecoder = m_outputCodec->makeDecoder(); + m_stdoutBuffer.append(m_outputDecoder->toUnicode((bytes))); + emit standardOutputChanged(m_stdoutBuffer); + } +} + +void QstLocalProcess::updateErrorBuffer() +{ + QByteArray bytes = readAllStandardOutput(); + if (!bytes.isEmpty()) { + if (!m_errorDecoder) + m_errorDecoder = m_outputCodec->makeDecoder(); + m_stderrBuffer.append(m_errorDecoder->toUnicode((bytes))); + emit standardErrorChanged(m_stderrBuffer); + } +} + +void QstLocalProcess::write(const QString &input) +{ + QProcess::write(m_inputCodec->fromUnicode(input)); +} diff --git a/src/interpreter/imports/qtsystemtest/src/qstlocalprocess.h b/src/interpreter/imports/qtsystemtest/src/qstlocalprocess.h new file mode 100644 index 0000000..215ee36 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/qstlocalprocess.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTLOCALPROCESS_H +#define QSTLOCALPROCESS_H + +#include <QtCore/QProcess> + +class QTextCodec; +class QTextDecoder; + +class QstLocalProcess : public QProcess +{ + Q_OBJECT + Q_ENUMS(ProcessState ExitStatus OutputMode) + + Q_PROPERTY(ProcessState state READ state NOTIFY stateChanged) + Q_PROPERTY(ExitStatus exitStatus READ exitStatus NOTIFY exitStatusChanged) + Q_PROPERTY(int exitCode READ exitCode NOTIFY exitCodeChanged) + + Q_PROPERTY(QString standardOutput READ standardOutput NOTIFY standardOutputChanged) + Q_PROPERTY(QString standardError READ standardError NOTIFY standardErrorChanged) + + Q_PROPERTY(QString inputCodec READ inputCodec WRITE setInputCodec) + Q_PROPERTY(QString outputCodec READ outputCodec WRITE setOutputCodec) + + Q_PROPERTY(OutputMode outputMode READ outputMode WRITE setOutputMode) + +public: + explicit QstLocalProcess(QObject *parent = 0); + + enum OutputMode { + DeviceOutput, + PropertyOutput + }; + + Q_INVOKABLE void start(const QString &program, const QStringList &arguments = QStringList()); + Q_INVOKABLE bool waitForStarted(int msecs); + Q_INVOKABLE bool waitForFinished(int msecs); + Q_INVOKABLE bool waitForReadyRead(int msecs); + Q_INVOKABLE void closeWriteChannel(); + + Q_INVOKABLE ProcessState state() const; + Q_INVOKABLE ExitStatus exitStatus() const; + Q_INVOKABLE int exitCode() const; + + Q_INVOKABLE void write(const QString &input); + + QString standardOutput() const { return m_stdoutBuffer; } + Q_INVOKABLE void clearStandardOutput() + { m_stdoutBuffer.clear(); emit standardOutputChanged(m_stdoutBuffer); } + + QString standardError() const { return m_stderrBuffer; } + Q_INVOKABLE void clearStandardError() + { m_stderrBuffer.clear(); emit standardErrorChanged(m_stderrBuffer); } + + QString inputCodec() const; + QString outputCodec() const; + void setInputCodec(const QString &); + void setOutputCodec(const QString &); + + OutputMode outputMode() const { return m_outputMode; } + void setOutputMode(OutputMode mode); + +signals: + void stateChanged(QProcess::ProcessState state); + void exitStatusChanged(QProcess::ExitStatus status); + void exitCodeChanged(int); + void standardOutputChanged(const QString &); + void standardErrorChanged(const QString &); + +private slots: + void forwardFinished(int code, QProcess::ExitStatus status) + { + emit exitStatusChanged(status); + emit exitCodeChanged(code); + } + + void updateOutputBuffer(); + void updateErrorBuffer(); + +private: + QTextCodec *m_inputCodec; + QTextCodec *m_outputCodec; + QTextDecoder *m_outputDecoder; + QTextDecoder *m_errorDecoder; + OutputMode m_outputMode; + + QString m_stdoutBuffer; + QString m_stderrBuffer; +}; + +#endif // QSTLOCALPROCESS_H diff --git a/src/interpreter/imports/qtsystemtest/src/qstutils.cpp b/src/interpreter/imports/qtsystemtest/src/qstutils.cpp new file mode 100644 index 0000000..c826094 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/qstutils.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstutils.h" +#include <QtCore/QUrl> +#include <QtCore/QDir> + +QstUtils::QstUtils(QObject *parent) + : QObject(parent) +{ +} + diff --git a/src/interpreter/imports/qtsystemtest/src/qstutils.h b/src/interpreter/imports/qtsystemtest/src/qstutils.h new file mode 100644 index 0000000..46f68b3 --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/qstutils.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTUTILS_H +#define QSTUTILS_H + +#include <QObject> +class QUrl; +class QScriptValue; + +class QstUtils : public QObject +{ + Q_OBJECT +public: + explicit QstUtils(QObject *parent = 0); + +signals: + +public slots: + +}; + +#endif // QSTUTILS_H diff --git a/src/interpreter/imports/qtsystemtest/src/qtuitestglobal.h b/src/interpreter/imports/qtsystemtest/src/qtuitestglobal.h new file mode 100644 index 0000000..66a0cef --- /dev/null +++ b/src/interpreter/imports/qtsystemtest/src/qtuitestglobal.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITEST_GLOBAL_H +#define QTUITEST_GLOBAL_H + +#include <QtGlobal> + +#if defined(Q_OS_WIN32) +# if defined(QTUITEST_TARGET) +# define QTUITEST_EXPORT Q_DECL_EXPORT +# else +# define QTUITEST_EXPORT Q_DECL_IMPORT +# endif +# if defined(QTSLAVE_TARGET) +# define QTSLAVE_EXPORT Q_DECL_EXPORT +# else +# define QTSLAVE_EXPORT Q_DECL_IMPORT +# endif +#else +# define QTUITEST_EXPORT Q_DECL_EXPORT +# define QTSLAVE_EXPORT Q_DECL_EXPORT +#endif + +#if defined(Q_OS_WIN32) || defined(Q_OS_SYMBIAN) +# if defined(QSYSTEMTEST_TARGET) +# define QSYSTEMTEST_EXPORT Q_DECL_EXPORT +# else +# define QSYSTEMTEST_EXPORT Q_DECL_IMPORT +# endif +# if defined(QTUITESTRUNNER_TARGET) +# define QTUITESTRUNNER_EXPORT Q_DECL_EXPORT +# else +# define QTUITESTRUNNER_EXPORT Q_DECL_IMPORT +# endif +#else +# define QSYSTEMTEST_EXPORT Q_DECL_EXPORT +# define QTUITESTRUNNER_EXPORT Q_DECL_EXPORT +#endif + +#define xstr(s) str(s) +#define str(s) #s +#define QTUITEST_VERSION_STR xstr(QTUITEST_VERSION) + +#endif diff --git a/src/interpreter/imports/runner/qml/Config.qml b/src/interpreter/imports/runner/qml/Config.qml new file mode 100644 index 0000000..9b5ae0e --- /dev/null +++ b/src/interpreter/imports/runner/qml/Config.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 + +QtObject { + property variant remotes: ({ + localhost: { + address: 'localhost', + port: 5656 + } + }) + + property list<Logger> loggers: [ + PlainTextLogger{ }, + XmlLogger { + path: 'result.xml' + } + ] +} diff --git a/src/interpreter/imports/runner/qml/Logger.qml b/src/interpreter/imports/runner/qml/Logger.qml new file mode 100644 index 0000000..2ec66d9 --- /dev/null +++ b/src/interpreter/imports/runner/qml/Logger.qml @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 + +QtObject { + id: logger + property variant runner: null + property list<QtObject> __list + property string path + default property alias children : logger.__list + + function setup() { + runner = __runner; + } + + function locationOf(item) { + var ret = { + fileName : '', + lineNumber: 0 + }; + + var loc = runner.locationOf(item); + if (loc.url === undefined) { + return ret; + } + var url = loc.url.toString(); + ret.fileName = url.substr(url.lastIndexOf('/')+1); + ret.lineNumber = loc.lineNumber; + return ret; + } + + + onRunnerChanged: { + if (runner == undefined || runner == null) return; + runner.aboutToStartExecution.connect(aboutToStartExecution); + runner.finishedExecution.connect(finishedExecution); + runner.testCollectionStart.connect(testCollectionStart); + runner.testCollectionEnd.connect(testCollectionEnd); + + runner.testStart.connect(testStart); + runner.testEnd.connect(testEnd); + + runner.methodStart.connect(methodStart); + runner.methodEnd.connect(methodEnd); + } + + function aboutToStartExecution() { } + function finishedExecution() { } + + function testCollectionStart(testCollection) { } + function testCollectionEnd(testCollection) { } + + function testStart(testCollection) { } + function testEnd(testCollection) { } + + function methodStart(method) { } + function methodEnd(method) { } + + function cleanup() { } + + function log(type, event) { } +} diff --git a/src/interpreter/imports/runner/qml/PlainTextLogger.qml b/src/interpreter/imports/runner/qml/PlainTextLogger.qml new file mode 100644 index 0000000..ab05906 --- /dev/null +++ b/src/interpreter/imports/runner/qml/PlainTextLogger.qml @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest.Runner 1.0 + +Logger { + id: plaintextLogger + + property PlainTextWriter writer: PlainTextWriter {} + + property int indentLevel : 0 + property bool writeFinished : true + property string indentString: ' ' + property int maxNameLen: 60 + + property variant status : ({ + }); + + function aboutToStartExecution() { + writer.filePath = plaintextLogger.path; + } + + function testCollectionStart(testCollection) { + var loc = locationOf(testCollection); + logString( 'Collection', pad("'"+ testCollection.name + "' ", maxNameLen - 2*indentLevel) + + ' : ' + loc.fileName + '('+ loc.lineNumber +')'); + indentLevel++; + } + + function testStart(test) { var loc = locationOf(test); + logString( 'Test', pad("'"+test.name + "' ", maxNameLen - 2*indentLevel) + + ' : ' + loc.fileName + '('+ loc.lineNumber +')'); + indentLevel++; + } + + + function methodStart(method) { + logString('Running', method + '()'); + writeFinished = false; + indentLevel++; + } + + function methodEnd(method) { + indentLevel--; + if ( writeFinished ) { + logString('Finished', method + '()'); + } + } + + function testEnd(test) { + indentLevel--; + var statusMap = { + error: { text: 'ERROR', foreground: PlainTextWriter.White, background: PlainTextWriter.Red }, + passed: { text: 'passed', foreground: PlainTextWriter.Green, background: PlainTextWriter.DefaultColor }, + skipped: { text: 'skipped', foreground: PlainTextWriter.Yellow, background: PlainTextWriter.DefaultColor }, + failed: { text: 'FAILED', foreground: PlainTextWriter.Red, background: PlainTextWriter.DefaultColor }, + untested: { text: 'UNTESTED', foreground: PlainTextWriter.LightRed, background: PlainTextWriter.DefaultColor } + }; + + var result = test.__status.toLowerCase(); + var status = statusMap[result]; + logString( 'Result', pad("'"+test.name + "' ", maxNameLen - 2*indentLevel, '.') + + ' : [' + writer.colorize(status.text, status.foreground, status.background) + ']'); + } + + function testCollectionEnd(testCollection) { + indentLevel--; + logString( 'Collection', testCollection.name ); + } + + + function finishedExecution() { + write('-'.repeat(80)); + var report = runner.report; + var totalTests = 0; + var keys = ['error', 'passed', 'skipped', 'failed', 'untested']; + keys.forEach(function(s) { + totalTests += report[s]; + }); + write(pad('Total Tests', 15) + ' :' + totalTests); + + keys.forEach(function(s) { + if (report[s] > 0 ) { + write(pad(s, 15) + ' :' + report[s]); + } + }); + write('-'.repeat(80)); + } + + + function log(type, event) { + var str = event.formatted || event.message; + if (event.stack) { + event.stack.forEach(function(callSite) { + var trace = Qt.qst.relativeToCurrentPath(callSite.fileName) + + '(' + callSite.lineNumber +') : ' + + callSite.functionName; + str += '\n'; + str += trace; + }); + } + logString(type, str); + } + + function logString(type, str) { + writeFinished = true; + write(pad(type, 10) + ' : ' + str); + } + + function write(str) { + var strs = str.split('\n'); + var prefix = '[' + Date.timestamp() + ']'+ indentString.repeat(indentLevel) + ' '; + for (var i = 0; i < strs.length; ++i) { + writer.writeLine(prefix + strs[i]); + } + } + + function pad(text, len, using) { + using = using || ' ' + var padding = text.length < len ? using.repeat(len - text.length) : ''; + return text + padding; + } +} diff --git a/src/interpreter/imports/runner/qml/XUnitLogger.qml b/src/interpreter/imports/runner/qml/XUnitLogger.qml new file mode 100644 index 0000000..fb66d3c --- /dev/null +++ b/src/interpreter/imports/runner/qml/XUnitLogger.qml @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtSystemTest 1.0 +import QtSystemTest.Runner 1.0 + +Logger { + id: xunitLogger + + property var writer: XUnitWriter { + filePath: xunitLogger.path + } + + property var tests: [] + property var currentTest + property var msecsMarker: 0 + property var collectionStack: 0 + property var lastCollection: ''; + + function aboutToStartExecution() { + writer.writeStartDocument(); + writer.writeStartTestSuiteSet(); + } + + function finishedExecution() { + writer.writeEndTestSuiteSet(); + writer.writeEndDocument(); + } + + function testCollectionStart(testCollection) { + if (!collectionStack) { + tests = []; + msecsMarker = new Date; + } + lastCollection = testCollection.name; + collectionStack++; + } + + function testCollectionEnd(testCollection) { + collectionStack--; + if (collectionStack) + return; + + var Status = Core.Qtt.Status; + + var passed = 0; + var failed = 0; + var skipped = 0; + var errors = 0; + var i; + var test; + for (i = 0; i < tests.length; i++) { + test = tests[i]; + switch(test.state) { + case Status.Passed: + passed++; + break; + case Status.Failed: + failed++; + break; + default: + case Status.Skipped: + case Status:Untested: + skipped++; + break; + case Status.Error: + errors++; + break; + } + } + writer.writeStartTestSuite( + testCollection.name, + msecsMarker, + 'localhost', + passed + failed + skipped + errors, + failed, + errors, + skipped, + (+(new Date()) - msecsMarker.getTime())/1000); + for (i = 0; i < tests.length; i++) { + test = tests[i]; + writer.writeStartTestCase(test.classname, test.name, test.duration); + var message; + if (test.messages.length > 0) { + message = test.messages[test.messages.length-1]; + var messageWritten; + switch(message.type) { + case Status.Error: + writer.writeError(message.type, message.message); + break; + case Status.Failed: + writer.writeFailure(message.type, message.message); + break; + case Status.Skipped: + case Status.Untested: + writer.writeSkipped(message.type, message.message); + break; + default: + break; + } + } + + writer.writeEndTestCase(); + } + writer.writeEndTestSuite(); + } + + function testStart(test) { + currentTest = { + state: Core.Qtt.Status.Passed, + time: +(new Date()), + classname: lastCollection, + name: test.name, + messages: [] + }; + } + function testEnd(test) { + currentTest.duration = (+(new Date()) - currentTest.time)/1000; + currentTest.state = test.__status + if (test.__status === Core.Qtt.Status.Untested) { + currentTest.messages.push({type: test.__status, message: 'No verifiable steps performed'}); + + } + + tests.push(currentTest); + + } + + function cleanup() { } + + function log(type, msg) { + currentTest.messages.push({type: type, message: msg}); + } +} diff --git a/src/interpreter/imports/runner/qml/XmlLogger.qml b/src/interpreter/imports/runner/qml/XmlLogger.qml new file mode 100644 index 0000000..951eb59 --- /dev/null +++ b/src/interpreter/imports/runner/qml/XmlLogger.qml @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtSystemTest 1.0 +import QtSystemTest.Runner 1.0 + +Logger { + id: xmlLogger + property XmlWriter writer: XmlWriter {} + + property Js js : Js{} + function store(){} + + function aboutToStartExecution() { + store.timerStack = []; + writer.filePath = xmlLogger.path; + writer.writeStartDocument(); + writer.writeStartElement('systemtestrun'); + store.timerStack.push(+new Date); + } + + function finishedExecution() { + var duration = (+new Date) - store.timerStack.pop(); + + writer.writeStartElement('report'); + + var report = runner.report; + var totalTests = 0; + var keys = ['passed', 'skipped', 'untested', 'failed', 'error']; + keys.forEach(function(s) { + totalTests += report[s]; + writer.writeTextElement(s, report[s].toString()); + }); + writer.writeTextElement('total', totalTests.toString()); + writer.writeTextElement('duration', duration); + writer.writeEndElement(); // report + writer.writeEndElement(); // systemtestrun + writer.writeEndDocument(); + } + + function testCollectionStart(testCollection) { + var loc = locationOf(testCollection); + writer.writeStartElement('collection'); + writer.writeAttribute('name', testCollection.name); + writer.writeAttribute('file', loc.fileName); + writer.writeAttribute('line', loc.lineNumber); + writer.writeAttribute('timestamp', (new Date).toISOString()); + store.timerStack.push(+new Date); + } + + function testCollectionEnd(testCollection) { + var duration = (+new Date) - store.timerStack.pop(); + writer.writeStartElement('report'); + writer.writeTextElement('duration', duration); + writer.writeEndElement(); + writer.writeEndElement(); + } + + function testStart(test) { + var loc = locationOf(test); + writer.writeStartElement('test'); + writer.writeAttribute('name', test.name); + writer.writeAttribute('file', loc.fileName); + writer.writeAttribute('line', loc.lineNumber); + writer.writeAttribute('timestamp', (new Date).toISOString()); + store.timerStack.push(+new Date); + } + + function testEnd(test) { + var duration = (+new Date) - store.timerStack.pop(); + writer.writeStartElement('report'); + writer.writeTextElement('status', test.__status.toLowerCase()); + writer.writeTextElement('duration', duration); + writer.writeEndElement(); + writer.writeEndElement(); + } + + function methodStart(method) { + writer.writeStartElement('method'); + writer.writeAttribute('name', method); + } + + function methodEnd(method) { + writer.writeEndElement(); + } + + function writeFrame(callSite) { + var path = Qt.qst.relativeToCurrentPath(callSite.fileName); + writer.writeStartElement('frame'); + writer.writeAttribute('file', path); + writer.writeAttribute('line', callSite.lineNumber); + writer.writeCharacters(callSite.functionName); + writer.writeEndElement(); + } + + function writeEventContents(event) + { + var Core = js.core(); + var stringify = Core.stringify.nothrow(); + writer.writeTextElement('reason', event.message); + if (event.stack) { + writer.writeStartElement('stack'); + event.stack.forEach(writeFrame.bind(this)); + writer.writeEndElement(); + } + if (event.meta) { + writer.writeStartElement('meta') + for(var part in event.meta) { + var asString = stringify(event.meta[part]); + writer.writeStartElement('property'); + writer.writeAttribute('name', part); + writer.writeCharacters(stringify.failed ? 'opaque object' : asString); + writer.writeEndElement(); + } + writer.writeEndElement(); + } + } + + function log(type, event) { + var ltype = type.toLowerCase(); + switch(ltype) { + case 'passed': + case 'skipped': + case 'failed': + case 'error': + case 'untested': + writer.writeStartElement(ltype); + writeEventContents(event); + writer.writeEndElement(); + break; + default: + writer.writeStartElement('note'); + writer.writeAttribute('type', ltype); + writeEventContents(event); + writer.writeEndElement(); + break; + } + } + +} diff --git a/src/interpreter/imports/runner/qmldir b/src/interpreter/imports/runner/qmldir new file mode 100644 index 0000000..89362d2 --- /dev/null +++ b/src/interpreter/imports/runner/qmldir @@ -0,0 +1,7 @@ +plugin qtsystemtestrunner +Logger 1.0 qml/Logger.qml +PlainTextLogger 1.0 qml/PlainTextLogger.qml +XUnitLogger 1.0 qml/XUnitLogger.qml +XmlLogger 1.0 qml/XmlLogger.qml +Config 1.0 qml/Config.qml + diff --git a/src/interpreter/imports/runner/qtsystemtestrunner.json b/src/interpreter/imports/runner/qtsystemtestrunner.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/interpreter/imports/runner/qtsystemtestrunner.json @@ -0,0 +1 @@ +{} diff --git a/src/interpreter/imports/runner/runner.pro b/src/interpreter/imports/runner/runner.pro new file mode 100644 index 0000000..438c683 --- /dev/null +++ b/src/interpreter/imports/runner/runner.pro @@ -0,0 +1,70 @@ +TARGET = qtsystemtestrunner +TARGETPATH = QtSystemTest/Runner + +TEMPLATE = lib +CONFIG += no_clean qt plugin +QT += declarative declarative-private + + +SOURCES += src/imports.cpp \ + src/qstxunitwriter.cpp \ + src/qstlogwriter.cpp \ + +HEADERS += src/imports.h \ + src/qstxunitwriter.h \ + src/qstlogwriter.h \ + +OTHER_FILES += \ + qtsystemtest.json \ + +target.path += $$[QT_INSTALL_IMPORTS]/QtSystemTest/Runner + +# public api +QML_IMPORT_FILES = \ + qml/Config.qml \ + qml/Logger.qml \ + qml/PlainTextLogger.qml \ + qml/XmlLogger.qml \ + qml/XUnitLogger.qml + +qmlImportFiles.files += $$QML_IMPORT_FILES +qmlImportFiles.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH/qml + +# scripts +#SCRIPT_FILES = \ +# scripts/api.js \ +# scripts/Datatype.js \ +# scripts/Functional.js \ +# scripts/JsCore.js \ +# scripts/SourceBuilder.js \ +# scripts/Class.js \ +# scripts/QstCore.js \ +# scripts/Console.js \ +# scripts/Expect.js \ +# scripts/Exception.js \ +# scripts/ApplicationRegistry.js \ + +#scriptFiles.files += $$SCRIPT_FILES +#scriptFiles.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH/scripts + +# qmldir +QMLDIR_FILE = qmldir +qmldirFile.files += $$QMLDIR_FILE +qmldirFile.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH + +# show in QtCreator +OTHER_FILES += $$QML_IMPORT_FILES \ +# $$SCRIPT_FILES \ + qmldir \ + + +INSTALLS += qmlImportFiles qmldirFile target + + + + + + + + + diff --git a/src/interpreter/imports/runner/src/imports.cpp b/src/interpreter/imports/runner/src/imports.cpp new file mode 100644 index 0000000..a2852d9 --- /dev/null +++ b/src/interpreter/imports/runner/src/imports.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "imports.h" +#include "qstxunitwriter.h" +#include <QtDebug> +#include <QtDeclarative> + +void QtSystemTestRunnerModule::registerTypes(const char *uri) +{ + qDebug() << Q_FUNC_INFO << uri; + Q_ASSERT(QLatin1String(uri) == QLatin1String("QtSystemTest.Runner")); + qmlRegisterType<QstPlainTextWriter>(uri, 1, 0, "PlainTextWriter"); + qmlRegisterType<QstXmlStreamWriter>(uri, 1, 0, "XmlWriter"); + qmlRegisterType<QstXUnitWriter>(uri, 1, 0, "XUnitWriter"); +} + +void QtSystemTestRunnerModule::initializeEngine(QDeclarativeEngine *, const char *) +{ +} + +Q_EXPORT_PLUGIN2(qtsystemtestrunner, QtSystemTestRunnerModule); diff --git a/src/interpreter/imports/runner/src/imports.h b/src/interpreter/imports/runner/src/imports.h new file mode 100644 index 0000000..f424a95 --- /dev/null +++ b/src/interpreter/imports/runner/src/imports.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef IMPORTS_H +#define IMPORTS_H + +#include <QDeclarativeExtensionPlugin> + +class QDeclarativeEngine; + +class QtSystemTestRunnerModule : public QDeclarativeExtensionPlugin +{ + Q_OBJECT + +public: + virtual void registerTypes(const char *uri); + void initializeEngine(QDeclarativeEngine *, const char *); +}; + +#endif // IMPORTS_H diff --git a/src/interpreter/imports/runner/src/qstlogwriter.cpp b/src/interpreter/imports/runner/src/qstlogwriter.cpp new file mode 100644 index 0000000..8ef70de --- /dev/null +++ b/src/interpreter/imports/runner/src/qstlogwriter.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstlogwriter.h" + +#include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QList> + + +#include <QtCore/QDebug> + +static QIODevice *createDevice(const QString &path) +{ + QFile *file = new QFile; + if (path.isEmpty()) { + if (!file->open(stdout, QFile::WriteOnly)) { + qWarning("Error opening stdout: %s", qPrintable(file->errorString())); + delete file; + file = 0; + } + } else { + file->setFileName(path); + if (!file->open(QFile::WriteOnly)) { + qWarning("Error opening log file %s: %s", qPrintable(path), qPrintable(file->errorString())); + delete file; + file = 0; + } + } + return file; +} + + +void QstPlainTextWriter::setFilePath(const QString &path) +{ + QIODevice *dev = m_stream->device(); + m_stream->setDevice(0); + dev->deleteLater(); + + dev = createDevice(path); + if (dev) + m_stream->setDevice(dev); +} + +QString QstPlainTextWriter::filePath() const +{ + QFile *file = qobject_cast<QFile*>(m_stream->device()); + if (file) { + QFileInfo info(*file); + return info.absoluteFilePath(); + } + return QString(); +} + +void QstPlainTextWriter::writeLine(const QString &text) +{ + *m_stream << text << endl; + m_stream->flush(); +} + +static QList<int> color_codes(QstPlainTextWriter::Color color, bool foreground = true) +{ + QList<int> commands; + if (color == QstPlainTextWriter::DefaultColor) + return commands; + int distance = (int)color - (int)QstPlainTextWriter::Black; + commands.append(distance % 2); + commands.append((distance / 2) + (foreground ? 30 : 40)); + return commands; +} + +QString QstPlainTextWriter::colorize(const QString &text, Color foreground, Color background) +{ + if (m_colorSetting == NeverColor || (m_colorSetting == AutoColor && !isConsole())) + return text; + + QList<int> commands; + commands << color_codes(foreground, true) << color_codes(background, false); + if (commands .isEmpty()) + return text; + QString result = QString::fromLatin1("\033["); + QListIterator<int> it(commands); + while(it.hasNext()) { + result += QString::number(it.next()); + if (it.hasNext()) + result += QString::fromLatin1(";"); + } + result += "m"; + return result + text + "\033[0m"; +} + +bool QstPlainTextWriter::isConsole() const +{ + QFile *file = qobject_cast<QFile*>(m_stream->device()); + if (file) { + // not sure, but may need to use _isatty on win + return isatty(file->handle()); + } + return false; +} + +void QstXmlStreamWriter::setFilePath(const QString &path) +{ + QIODevice *dev = m_writer->device(); + m_writer->setDevice(0); + dev->deleteLater(); + + dev = createDevice(path); + if (dev) + m_writer->setDevice(dev); +} + +QString QstXmlStreamWriter::filePath() const +{ + QFile *file = qobject_cast<QFile*>(m_writer->device()); + if (file) { + QFileInfo info(*file); + return info.absoluteFilePath(); + } + return QString(); +} + +void QstXmlStreamWriter::flush() +{ + QFile *file = qobject_cast<QFile *>(m_writer->device()); + if (file) + file->flush(); +} diff --git a/src/interpreter/imports/runner/src/qstlogwriter.h b/src/interpreter/imports/runner/src/qstlogwriter.h new file mode 100644 index 0000000..8e87eac --- /dev/null +++ b/src/interpreter/imports/runner/src/qstlogwriter.h @@ -0,0 +1,212 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTLOGWRITER_H +#define QSTLOGWRITER_H + +#include <QtCore/QTextStream> +#include <QtCore/QXmlStreamWriter> + + +class QstPlainTextWriter : public QObject +{ + Q_OBJECT + Q_ENUMS(ColorSetting Color) + Q_PROPERTY(QString filePath READ filePath WRITE setFilePath) + Q_PROPERTY(ColorSetting colorSetting READ colorSetting WRITE setColorSetting) +public: + enum ColorSetting { + AutoColor, + AlwaysColor, + NeverColor + }; + + enum Color { + DefaultColor, + Black, // the order of these colors matters, see colorize + DarkGray, + Red, + LightRed, + Green, + LightGreen, + Brown, + Yellow, + Blue, + LightBlue, + Purple, + LightPurple, + Cyan, + LightCyan, + LightGray, + White + }; + + QstPlainTextWriter(QObject *parent = 0) + : QObject(parent), + m_colorSetting(AutoColor) + { + m_stream = new QTextStream; + m_stream->setCodec("UTF8"); + } + + ~QstPlainTextWriter() { + if (m_stream->device()) { + m_stream->device()->close(); + m_stream->device()->deleteLater(); + } + delete m_stream; + } + + void setColorSetting(ColorSetting setting) { m_colorSetting = setting; } + ColorSetting colorSetting() const { return m_colorSetting; } + + void setFilePath(const QString &); + QString filePath() const; + + Q_INVOKABLE void writeLine(const QString &); + + Q_INVOKABLE QString colorize(const QString &text, Color foreground = DefaultColor, Color background = DefaultColor); + +private: + Q_INVOKABLE bool isConsole() const; + QTextStream *m_stream; + ColorSetting m_colorSetting; +}; + +class QstXmlStreamWriter : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString filePath READ filePath WRITE setFilePath) + Q_PROPERTY(bool autoFormatting READ autoFormatting WRITE setAutoFormatting) + Q_PROPERTY(int autoFormattingIndent READ autoFormattingIndent WRITE setAutoFormattingIndent) + +public: + QstXmlStreamWriter(QObject *parent = 0) + : QObject(parent) + { + m_writer = new QXmlStreamWriter; + m_writer->setAutoFormatting(true); + } + + ~QstXmlStreamWriter() + { + flush(); + if (m_writer->device()) { + m_writer->device()->close(); + m_writer->device()->deleteLater(); + } + delete m_writer; + } + + void setFilePath(const QString &); + QString filePath() const; + + void setAutoFormatting(bool value) + { m_writer->setAutoFormatting(value); } + bool autoFormatting() const + { return m_writer->autoFormatting(); } + + void setAutoFormattingIndent(int spacesOrTabs) + { m_writer->setAutoFormattingIndent(spacesOrTabs); } + int autoFormattingIndent() const + { return m_writer->autoFormattingIndent(); } + + Q_INVOKABLE void writeAttribute(const QString &qualifiedName, const QString &value) + { m_writer->writeAttribute(qualifiedName, value); } + Q_INVOKABLE void writeAttribute(const QString &namespaceUri, const QString &name, const QString &value) + { m_writer->writeAttribute(namespaceUri, name, value); } + + Q_INVOKABLE void writeCDATA(const QString &text) + { m_writer->writeCDATA(text); } + Q_INVOKABLE void writeCharacters(const QString &text) + { m_writer->writeCharacters(text); } + Q_INVOKABLE void writeComment(const QString &text) + { m_writer->writeComment(text); } + + Q_INVOKABLE void writeDTD(const QString &dtd) + { m_writer->writeDTD(dtd); } + + Q_INVOKABLE void writeEmptyElement(const QString &qualifiedName) + { m_writer->writeEmptyElement(qualifiedName); } + Q_INVOKABLE void writeEmptyElement(const QString &namespaceUri, const QString &name) + { m_writer->writeEmptyElement(namespaceUri, name); } + + Q_INVOKABLE void writeTextElement(const QString &qualifiedName, const QString &text) + { m_writer->writeTextElement(qualifiedName, text); } + Q_INVOKABLE void writeTextElement(const QString &namespaceUri, const QString &name, const QString &text) + { m_writer->writeTextElement(namespaceUri, name, text); } + + Q_INVOKABLE void writeEndDocument() + { m_writer->writeEndDocument(); flush(); } + Q_INVOKABLE void writeEndElement() + { m_writer->writeEndElement(); } + + Q_INVOKABLE void writeEntityReference(const QString &name) + { m_writer->writeEntityReference(name); } + Q_INVOKABLE void writeNamespace(const QString &namespaceUri, const QString &prefix = QString()) + { m_writer->writeNamespace(namespaceUri, prefix); } + Q_INVOKABLE void writeDefaultNamespace(const QString &namespaceUri) + { m_writer->writeDefaultNamespace(namespaceUri); } + Q_INVOKABLE void writeProcessingInstruction(const QString &target, const QString &data = QString()) + { m_writer->writeProcessingInstruction(target, data); } + + Q_INVOKABLE void writeStartDocument() + { m_writer->writeStartDocument(); } + Q_INVOKABLE void writeStartDocument(const QString &version) + { m_writer->writeStartDocument(version); } + Q_INVOKABLE void writeStartDocument(const QString &version, bool standalone) + { m_writer->writeStartDocument(version, standalone); } + Q_INVOKABLE void writeStartElement(const QString &qualifiedName) + { m_writer->writeStartElement(qualifiedName); } + Q_INVOKABLE void writeStartElement(const QString &namespaceUri, const QString &name) + { m_writer->writeStartElement(namespaceUri, name); } + + Q_INVOKABLE bool hasError() const + { return m_writer->hasError(); } + + void flush(); +private: + + QXmlStreamWriter *m_writer; +}; + + +#endif // QSTLOGWRITER_H diff --git a/src/interpreter/imports/runner/src/qstxunitwriter.cpp b/src/interpreter/imports/runner/src/qstxunitwriter.cpp new file mode 100644 index 0000000..976d98e --- /dev/null +++ b/src/interpreter/imports/runner/src/qstxunitwriter.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstxunitwriter.h" +#include <QtCore/QDateTime> + + +QstXUnitWriter::QstXUnitWriter() + : QstXmlStreamWriter(), + m_state(Document), + m_suiteId(1) +{ +} + +QstXUnitWriter::~QstXUnitWriter() +{ +} + +bool QstXUnitWriter::checkState(State state, const QString &element, bool start) +{ + if (m_state != state) { + if (m_state != Error) { + if (start) + qWarning("unexpected state when starting '%s'", element.toLocal8Bit().constData()); + else + qWarning("unexpected state when ending '%s'", element.toLocal8Bit().constData()); + m_state = Error; + } + return false; + } + if (hasError()) { + if (m_state != Error) { + qWarning("unexpected error with device"); + m_state = Error; + } + return false; + } + return true; +} + +static const QString s_suiteSet(QString::fromLatin1("testsuites")); +static const QString s_suite(QString::fromLatin1("testsuite")); +static const QString s_case(QString::fromLatin1("testcase")); +static const QString s_error(QString::fromLatin1("error")); +static const QString s_failure(QString::fromLatin1("failure")); +static const QString s_skipped(QString::fromLatin1("skipped")); + +void QstXUnitWriter::writeStartTestSuiteSet() +{ + if (!checkState(Document, s_suiteSet, true)) + return; + m_state = SuiteSet; + + writeStartElement(s_suiteSet); +} + +void QstXUnitWriter::writeEndTestSuiteSet() +{ + if (!checkState(SuiteSet, s_suiteSet, false)) + return; + m_state = Document; + + writeEndElement(); + flush(); +} + +void QstXUnitWriter::writeStartTestSuite( + const QString &name, + const QDateTime ×tamp, + const QString &hostname, + int testTotal, int testFails, int testErrors, int testSkips, + int duration) +{ + if (!checkState(SuiteSet, s_suite, true)) + return; + m_state = Suite; + + writeStartElement(s_suite); + writeAttribute("name", name); + writeAttribute("package", QString::fromLatin1("none")); + writeAttribute("timestamp", timestamp.toLocalTime().toString("yyyy-MM-ddThh:mm:ss")); + writeAttribute("hostname", hostname.isEmpty() ? "localhost" : hostname); + writeAttribute("tests", QString::number(testTotal)); + writeAttribute("failures", QString::number(testFails)); + writeAttribute("errors", QString::number(testErrors)); + writeAttribute("skipped", QString::number(testSkips)); + writeAttribute("time", QString::number(duration)); + writeAttribute("id", QString::number(m_suiteId++)); +} + +void QstXUnitWriter::writeEndTestSuite() +{ + if (!checkState(Suite, s_suite, false)) + return; + m_state = SuiteSet; + + writeEndElement(); +} + + +void QstXUnitWriter::writeStartTestCase(const QString &classname, const QString &name, int duration) +{ + if (!checkState(Suite, s_case, true)) + return; + m_state = Case; + + writeStartElement(s_case); + writeAttribute("classname", classname); + writeAttribute("name", name); + writeAttribute("time", QString::number(duration)); +} + +void QstXUnitWriter::writeEndTestCase() +{ + if (!checkState(Case, s_case, false)) + return; + m_state = Suite; + + writeEndElement(); +} + +void QstXUnitWriter::writeError(const QString &type, const QString &message) +{ + if (!checkState(Case, s_error, true)) + return; + + writeStartElement(s_error); + writeAttribute("type", type); + writeCharacters(message); + writeEndElement(); +} +void QstXUnitWriter::writeFailure(const QString &type, const QString &message) +{ + if (!checkState(Case, s_failure, true)) + return; + + writeStartElement(s_failure); + writeAttribute("type", type); + writeCharacters(message); + writeEndElement(); +} +void QstXUnitWriter::writeSkipped(const QString &type, const QString &message) +{ + if (!checkState(Case, s_skipped, true)) + return; + + writeStartElement(s_skipped); + writeAttribute("type", type); + writeCharacters(message); + writeEndElement(); +} diff --git a/src/interpreter/imports/runner/src/qstxunitwriter.h b/src/interpreter/imports/runner/src/qstxunitwriter.h new file mode 100644 index 0000000..93904fc --- /dev/null +++ b/src/interpreter/imports/runner/src/qstxunitwriter.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTXUNITWRITER_H +#define QSTXUNITWRITER_H + +#include "qstlogwriter.h" + +class QstXUnitWriter : public QstXmlStreamWriter +{ + Q_OBJECT +public: + QstXUnitWriter(); + ~QstXUnitWriter(); + + Q_INVOKABLE void writeStartTestSuiteSet(); + Q_INVOKABLE void writeEndTestSuiteSet(); + + Q_INVOKABLE void writeStartTestSuite( + const QString &name, + const QDateTime ×tamp, + const QString &hostname, + int testTotal, + int testFails, + int testErrors, + int testSkips, + int duration); + + Q_INVOKABLE void writeEndTestSuite(); + + Q_INVOKABLE void writeStartTestCase(const QString &classname, const QString &name, int duration); + Q_INVOKABLE void writeEndTestCase(); + + Q_INVOKABLE void writeError(const QString &type, const QString &message); + Q_INVOKABLE void writeFailure(const QString &type, const QString &message); + Q_INVOKABLE void writeSkipped(const QString &type, const QString &message); + +private: + enum State { + Document, + SuiteSet, + Suite, + Case, + Error + }; + + bool checkState(State, const QString &element, bool start = true); + + State m_state; + + int m_suiteId; +}; + +#endif // QSTXUNITWRITER_H diff --git a/src/interpreter/interpreter.pro b/src/interpreter/interpreter.pro new file mode 100644 index 0000000..a89fbfb --- /dev/null +++ b/src/interpreter/interpreter.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS = imports runner diff --git a/src/interpreter/runner/main.cpp b/src/interpreter/runner/main.cpp new file mode 100644 index 0000000..f7f7ae1 --- /dev/null +++ b/src/interpreter/runner/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QApplication> +#include <qstrunnerbootstrap.h> + +int main(int argc, char *argv[]) +{ + QCoreApplication *app = 0; + + bool guiEnabled = false; + for (int i = 1; i < argc; ++i) { + if ( qstrcmp(argv[i], "--disable-manual-tests") == 0) { + guiEnabled = false; + break; + } + } + + if (guiEnabled) { + app = new QApplication(argc, argv); + } else { + app = new QCoreApplication(argc, argv); + } + + QstRunnerBootstrap runner(app); + int ret = runner.run(); + return ret; +} diff --git a/src/interpreter/runner/qstjsengine.cpp b/src/interpreter/runner/qstjsengine.cpp new file mode 100644 index 0000000..1e3b225 --- /dev/null +++ b/src/interpreter/runner/qstjsengine.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstjsengine.h" + + +QstJsEngine::QstJsEngine(QObject *parent) : + QObject(parent) +{ + +} diff --git a/src/interpreter/runner/qstjsengine.h b/src/interpreter/runner/qstjsengine.h new file mode 100644 index 0000000..14828a7 --- /dev/null +++ b/src/interpreter/runner/qstjsengine.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTJSENGINE_H +#define QSTJSENGINE_H + +#include <QObject> + +class QstJsEngine : public QObject +{ + Q_OBJECT +public: + explicit QstJsEngine(QObject *parent = 0); + +signals: + +public slots: + +}; + +#endif // QSTJSENGINE_H diff --git a/src/interpreter/runner/qstrunnerbootstrap.cpp b/src/interpreter/runner/qstrunnerbootstrap.cpp new file mode 100644 index 0000000..0c44c56 --- /dev/null +++ b/src/interpreter/runner/qstrunnerbootstrap.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstrunnerbootstrap.h" +#include "qstrunnercore.h" +#include <QtCore/QFileInfo> +#include <QtCore/QStringList> +#include <QtCore/QCoreApplication> +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtScript/QScriptEngine> +#include <QtScript/QScriptContext> +#include <QtScript/QScriptValue> +#include <QtScript/QScriptContextInfo> +#include <QDeclarativeEngine> +#include <QDeclarativeComponent> + +static const int InternalError = 1 << 6; + + +static QScriptValue isRelativePath(QScriptContext *ctx, QScriptEngine *) +{ + QUrl url = ctx->argument(0).toString(); + return url.isRelative(); +} + +static QScriptValue relativeToCurrentPath(QScriptContext *ctx, QScriptEngine *) +{ + QUrl url = ctx->argument(0).toString(); + if (url.isLocalFile()) + return QDir::current().relativeFilePath(url.toLocalFile()); + return url.toString(); +} + + +static QScriptValue qscriptengine_stack(QScriptContext *ctx, QScriptEngine *e) +{ + QVariantList stack; + + qint32 frame = 0; + bool framesSpecified = ctx->argumentCount() > 0; + if (framesSpecified) { + frame = ctx->argument(0).toInt32(); + } + + while (ctx) { + // count down if user has requested for certain number of frames + if ( framesSpecified && frame-- <= 0 ) + break; + ctx = ctx->parentContext(); + QScriptContextInfo info(ctx); + QVariantMap callsite; + callsite["fileName"] = info.fileName(); + callsite["lineNumber"] = info.lineNumber(); + callsite["functionName"] = info.functionName(); + stack << callsite; + } + return qScriptValueFromSequence(e, stack); +} + +// Copied from qdeclarativedebughelper_p.h in Qt +class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper +{ +public: + static QScriptEngine *getScriptEngine(QDeclarativeEngine *engine); +}; + +bool QstRunnerBootstrap::setupScriptEngine(QDeclarativeEngine *declarativeEngine) +{ + QScriptEngine *e = QDeclarativeDebugHelper::getScriptEngine(declarativeEngine); + QScriptValue qst = e->newObject(); + qst.setProperty(QLatin1String("stack"), e->newFunction(qscriptengine_stack)); + qst.setProperty(QLatin1String("isRelativePath"), e->newFunction(isRelativePath)); + qst.setProperty(QLatin1String("relativeToCurrentPath"), e->newFunction(relativeToCurrentPath)); + + QScriptValue qtObject = e->globalObject().property(QLatin1String("Qt")); + qtObject.setProperty(QLatin1String("qst"), qst); + return true; +} + +QstRunnerBootstrap::QstRunnerBootstrap(QCoreApplication *app) + : QObject(app) + , m_app(app) + , m_qmlRunner(0) +{ + QStringList args = app->arguments(); + // Skips executable + args.removeAt(0); + + if (args.count() == 0) { + qDebug() << "No arguments passed, failing back to qmlunit Test Suite (" << app->applicationDirPath() << ")\n"; + args = QStringList(app->applicationDirPath() + "/test"); + } + + foreach (const QString &arg, args) { + findTests(arg); + } +} + + +bool QstRunnerBootstrap::setup() +{ + qmlRegisterType<QstRunnerCore>("QstRunner", 1, 0, "Runner"); + QDeclarativeEngine *engine = new QDeclarativeEngine(this); + engine->setOfflineStoragePath(QDir::currentPath() + "/storage"); + setupScriptEngine(engine); + + qDebug()<< "Loading Runner"; + QUrl runnerPath = QUrl::fromLocalFile( + m_app->applicationDirPath() + "/scripts/QstRunner.qml"); + + QDeclarativeComponent runnerCom(engine, runnerPath); + if (!runnerCom.errors().isEmpty()) { + qDebug() << "Internal error in Qml runner" + << runnerCom.errors(); + return false; // may be exit 2 + } + m_qmlRunner = qobject_cast<QstRunnerCore *>(runnerCom.create()); + if (!m_qmlRunner) { + qDebug() << "Internal Error: qmlRunner creation failed" + << runnerCom.errors(); + return false; // may be exit 2 + } + + if ( !m_qmlRunner->setup(engine, qApp->arguments()) ) { + return false; + } + + qDebug()<< "Loading test file"; + QDeclarativeComponent com(engine, QUrl::fromLocalFile(m_testFile.first())); + if (!com.errors().isEmpty()) { + qDebug() << "Errors in testcase \n" + << com.errors(); + return false; // may be exit 1 + } + QObject *test = com.create(); + if (!test ) { + qDebug() << "Internal Error testcase object creation \n" + << com.errors(); + return false; // may be exit 1 + } + m_qmlRunner->setTest(test); + return true; +} + +int QstRunnerBootstrap::run() +{ + if (!setup()) { + return InternalError; + } + qDebug() << Q_FUNC_INFO << "---------------[setup is ok]-------------------"; + return m_qmlRunner->exec(); +} + +void QstRunnerBootstrap::findTests(const QString &path) +{ + if (isTest(path)) { + m_testFile << QDir(path).absolutePath(); + return; + } + + QStringList filters; filters << "*"; + QDir dir = QDir(QDir(path).absolutePath()); + + QListIterator<QFileInfo> files(dir.entryInfoList(filters, QDir::AllEntries | QDir::NoDotAndDotDot)); + while(files.hasNext()) { + QFileInfo file = files.next(); + if (file.fileName() == "." || file.fileName() == "..") continue; + + if (isTest(file)) + m_testFile << file.absoluteFilePath(); + else if (isDir(file)) + findTests(file.absoluteFilePath()); + } +} + +bool QstRunnerBootstrap::isTest(const QFileInfo &file) +{ + return isTest(file.fileName()); +} + +bool QstRunnerBootstrap::isTest(const QString &filePath) +{ + return filePath.endsWith("Test.qml") + || filePath.endsWith("Tests.qml"); +} + +bool QstRunnerBootstrap::isDir(const QFileInfo &file) +{ + return QDir(file.absoluteFilePath()).exists(); +} diff --git a/src/interpreter/runner/qstrunnerbootstrap.h b/src/interpreter/runner/qstrunnerbootstrap.h new file mode 100644 index 0000000..a294306 --- /dev/null +++ b/src/interpreter/runner/qstrunnerbootstrap.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTUITESTRUNNER_H +#define QTUITESTRUNNER_H + +#include <QtCore/QObject> +#include <QtCore/QStringList> + +class QDeclarativeEngine; +class QCoreApplication; +class QFileInfo; +class QStringList; +class QstRunnerCore; + +class QstRunnerBootstrap : public QObject +{ + Q_OBJECT + +public: + explicit QstRunnerBootstrap(QCoreApplication *app); + int run(); + +public slots: + +signals: + +private: + bool setup(); + void findTests(const QString &path); + bool isDir(const QFileInfo &file); + bool isTest(const QFileInfo &file); + bool isTest(const QString &filePath); + bool setupScriptEngine(QDeclarativeEngine *declarativeEngine); + + +private: + QCoreApplication *m_app; + QStringList m_testFile; + QstRunnerCore *m_qmlRunner; +}; + +#endif // QTUITESTRUNNER_H diff --git a/src/interpreter/runner/qstrunnercore.cpp b/src/interpreter/runner/qstrunnercore.cpp new file mode 100644 index 0000000..9116936 --- /dev/null +++ b/src/interpreter/runner/qstrunnercore.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstrunnercore.h" +#include <private/qdeclarativecontext_p.h> +#include <QDeclarativeEngine> +#include <QDeclarativeContext> +#include <QtDebug> + +QstRunnerCore::QstRunnerCore(QObject *parent) : + QObject(parent) +{ +} + + + +QVariant QstRunnerCore::locationOf(QObject *o) +{ + QVariantMap ret; + if (!o) { + return ret; + } + QDeclarativeData *d = QDeclarativeData::get(o, false); + if (d && d->outerContext && !d->outerContext->url.isEmpty()) { + ret["url"] = d->outerContext->url; + ret["lineNumber"] = d->lineNumber; + } + return ret; +} + + +void QstRunnerCore::setRootProperty(const QString &name, QObject *obj) +{ + m_engine->rootContext()->setContextProperty(name, obj); +} + +bool QstRunnerCore::setup(QDeclarativeEngine *engine, const QStringList &args) +{ + m_engine = engine; + qDebug()<< "setting __runner : " << this; + m_engine->rootContext()->setContextProperty("__runner", this); + + QVariant ret; + qDebug()<< "Invoking qml __setup"; + QMetaObject::invokeMethod(this, "__setup", + Q_RETURN_ARG(QVariant, ret), + Q_ARG(QVariant, args) ); + return ret.toBool(); +} + +void QstRunnerCore::setTest(QObject *test) +{ + setRootProperty("__testRoot", test); +} + + +int QstRunnerCore::exec() +{ + qDebug()<< "Validate test and exec"; + QVariant ret; + QMetaObject::invokeMethod(this, "__exec", + Q_RETURN_ARG(QVariant, ret) ); + return ret.toInt(); +} diff --git a/src/interpreter/runner/qstrunnercore.h b/src/interpreter/runner/qstrunnercore.h new file mode 100644 index 0000000..524260a --- /dev/null +++ b/src/interpreter/runner/qstrunnercore.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSYSTEMTESTRUNNERCORE_H +#define QSYSTEMTESTRUNNERCORE_H + +#include <QtCore/QObject> +#include <QtCore/QVariant> + +class QDeclarativeEngine; + +class QstRunnerCore : public QObject +{ + Q_OBJECT +public: + explicit QstRunnerCore(QObject *parent = 0); + + bool setup(QDeclarativeEngine *engine, const QStringList &args); + void setTest(QObject *test); + int exec(); + +signals: + +public slots: + QVariant locationOf(QObject *o); + void setRootProperty(const QString &name, QObject* obj); + +private: + QDeclarativeEngine *m_engine; + +}; + +#endif // QSYSTEMTESTRUNNERCORE_H diff --git a/src/interpreter/runner/runner.pro b/src/interpreter/runner/runner.pro new file mode 100644 index 0000000..f5205b2 --- /dev/null +++ b/src/interpreter/runner/runner.pro @@ -0,0 +1,30 @@ +CONFIG += qt +QT += declarative declarative-private script + +TARGET = qtsystemtestrunner +TEMPLATE = app + +macx:CONFIG-=app_bundle + +SOURCES += main.cpp\ + qstrunnercore.cpp \ + qstrunnerbootstrap.cpp \ + qstjsengine.cpp + +HEADERS += \ + qstrunnercore.h \ + qstrunnerbootstrap.h \ + qstjsengine.h + +SCRIPTS += \ + scripts/QstRunner.js \ + scripts/QstRunner.qml + +DESTDIR = ../../../bin +SCRIPTSDIR = $$OUT_PWD/../../../bin/scripts +scripts.target = dummytarget +scripts.commands = (mkdir -p $$SCRIPTSDIR && cd $$PWD && cp $$SCRIPTS $$SCRIPTSDIR/) + +QMAKE_EXTRA_TARGETS += scripts + +POST_TARGETDEPS += dummytarget diff --git a/src/interpreter/runner/scripts/QstRunner.js b/src/interpreter/runner/scripts/QstRunner.js new file mode 100644 index 0000000..da34bc6 --- /dev/null +++ b/src/interpreter/runner/scripts/QstRunner.js @@ -0,0 +1,358 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +var create = function(Core){ +// import to this namespace +var + InternalError = 1<<6, + Console = Core.Console, + Class = Core.Class, + Js = Core.Js, + Qtt = Core.Qtt, + runner, + Topic = Console.topic('Runner') +; + +function relevantStack(e){ + relevantStack.currentFile = relevantStack.currentFile + || Js.Engine.currentFile(); + + Topic.debug('Runner: file: ', relevantStack.currentFile); + var filtered = []; + e.stack.some(function(callSite) { + var hasReachedRunner = callSite.fileName === relevantStack.currentFile; + if (!hasReachedRunner) { + filtered.push(callSite); + } + return hasReachedRunner; + }); + return (e instanceof Qtt.Error) + ? filtered + : filtered.length > 0 ? filtered + : e.stack; +} + +var AbstractTestRunner = Class.create(function(item) { + var Topic = Console.topic('Runner').topic('AbstractTestRunner'); + + function validate(fnName, config){ + config = config || { } + config.mustExist = config.mustExist === undefined ? true : config.mustExist; + + if ( !(fnName in item) ) { + if (config.mustExist === true) { + throw new ReferenceError( 'Missing mandatory property or function "' + + fnName + '" in test item (Name:' + item.name + ')') + } + Topic.debug('Name: ', fnName, ' is missing, but ok to ignore' ); + return {ok: true, exists : false}; + } + + var m = item[fnName]; + if (typeof (m) !== 'function') { + throw new TypeError(fnName + ' not a function'); + } + return {ok: true, exists : true}; + } + + function exec() { + var Topic = Console.topic('Runner').topic('exec'); + Topic.debug( 'Running .............', item); + + // skip disabled items + var result = true; + if (item.enabled === false) { + Topic.debug(item, 'is disabled '); + return result; + } + + this.start(); + runner.currentTestItem = item; + try { + var ok = invokeSetup.call(this); + if (ok) { + this.run(); + } + } catch (e) { + /// FIXME: Qt5, remove this as e.stack *can be* enabled by default + e.__addStack(1); + this.setStatus(Qtt.Status.Failed); + console.log("Internal error: ", e.status || 'JsError', e.message); + ok = false; + e.stack.forEach( function(s) { + console.log(s.fileName, ': ', s.lineNumber, ' : ', s.functionName); }); + + var error = { + message: e.message, + stack: relevantStack(e), + formatted: e.formatted, + meta: e.meta + }; + runner.logEvent(e.status || 'JsError', error); + throw e; + } finally { + invokeCleanup.call(this); + this.end(); + } + } + + + function invokeSetup() { + var Topic = Console.topic('AbstractTestRunner').topic('invokeSetup'); + + Topic.debug( 'validating setup'); + var setup = 'setup'; + var result = validate(setup, {mustExist: false}); + if ( result.ok && result.exists === false ) { + return true; + } + + setup = item.setup; + var ok = true; + try { + runner.methodStart(setup.name); + runner.currentMethod = setup.name; + setup(); + runner.methodEnd(setup.name); + } catch (e) { + /// FIXME: Qt5, remove this as e.stack *can be* enabled by default + e.__addStack(1); + Topic.debug('Exception caught: ', e); + ok = false; + var status = (e instanceof Qtt.Error) + ? Qtt.Status.Untested + : Qtt.Status.Failed; + var error = { + message: e.message, + stack: relevantStack(e), + formatted: e.formatted, + meta: e.meta + }; + runner.logEvent(e.status || 'JsError', error); + runner.methodEnd(setup.name); + this.setStatus(status); + } + return ok; + } + + // don't throw any errors, just report them and end the cleanup + function invokeCleanup() { + var Topic = Console.topic('TestRunner').topic('runCleanup'); + + var cleanup = 'cleanup'; + var result = validate(cleanup, {mustExist: false}); + if ( result.ok && result.exists === false ) { + return; + } + + cleanup = item.cleanup; + runner.methodStart(cleanup.name); + runner.currentMethod = cleanup.name; + + try { + cleanup(); + } catch (e) { + /// FIXME: Qt5, remove this as e.stack *can be* enabled by default + e.__addStack(1); + Topic.debug('Exception in cleanup: ', e); + + var error = { + message: e.message, + stack: e.stack, + formatted: e.formatted, + meta: e.meta + }; + + runner.logEvent('WARNING', error); + } finally { + Topic.debug('run finally - finishing method : cleanup '); + runner.methodEnd(cleanup.name); + } + } + + return { + validate: validate, + item: function() { return item }, + exec: exec, + start: function() { throw new Error('Must override start')}, + run: function() { throw new Error('Must override run')}, + end: function() { throw new Error('Must override end')}, + setStatus: function() { throw new Error('Must override setStatus')}, + }; +}); + +var TestRunner = AbstractTestRunner.extend(function(item) { + this._super(item); + var Topic = Console.topic('TestRunner').topic('AbstractTestRunner'); + Topic.debug(' Creating a Test runner for ', item.name); + + function start() { runner.testStart(item); } + + function end() { runner.testEnd(item); } + + function setStatus(status) { + Topic.debug('Setting ... ', item.name , ' :', status) + item.__status = status; + /// FIXME Qt5: change report to var and runner.report[status]++ + var report = runner.report; + report[status]++; + runner.report = report; + } + + function run() { + var Topic = Console.topic('TestRunner').topic('runRun'); + + Topic.debug( 'validating run'); + var run = 'run'; + var status = Qtt.Status.Failed; + try { + this.validate(run); + + run = item.run; + runner.methodStart(run.name); + runner.currentMethod = run.name; + + Topic.debug('Going to run ... run'); + run(); + status = Qtt.Status.Passed; + } catch (e) { + /// FIXME: Qt5, remove this as e.stack *can be* enabled by default + e.__addStack(1); + status = (e instanceof Qtt.Error) + ? e.status + : Qtt.Status.Failed; + var error = { + message: e.message, + stack: relevantStack(e), + formatted: e.formatted, + meta: e.meta + }; + Topic.debug(status, Core.stringify(error)); + runner.logEvent(status, error); + } finally { + runner.methodEnd(run.name); + this.setStatus(status); + } + } + + return { + start: start, + end: end, + run: run, + setStatus: setStatus + }; +}); + +var TestCollectionRunner = AbstractTestRunner.extend(function(item) { + this._super(item); + + + function start() { runner.testCollectionStart(item); } + + function end() { runner.testCollectionEnd(item); } + + + function setStatus(status) { + // recurse and run the subsets ... + var subset = item.children; + for (var i = 0; i< subset.length; ++i) { + var testItem = subset[i]; + if ( !testItem.enabled ) { + continue; + } + var tr = runnerForItem(testItem); + tr.start(); + tr.setStatus(status); + tr.end(); + } + } + + function run() { + // recurse and run the subsets ... + var subset = item.__subset; + for (var i = 0; i< subset.length; ++i) { + var tr = runnerForItem(subset[i]); + tr.exec(); + } + } + + return { + start: start, + end: end, + run: run, + setStatus: setStatus + }; +}); + + +function runnerForItem(item) { + var Runner = item.__isTest ? TestRunner : TestCollectionRunner; + return new Runner(item); +} + +function exec(qmlRunner, item){ + runner = qmlRunner + try { + runner.aboutToStartExecution(); + var tr = runnerForItem(item); + tr.exec(); + runner.finishedExecution(); + + var report = runner.report; + var result = (report.failed > 0) + | (report.skipped > 0) << 1 + | (report.untested > 0) << 2 + | (report.error > 0) << 3; + } catch (e) { + /// FIXME: Qt5, remove this as e.stack *can be* enabled by default + e.__addStack(1); + result = InternalError; + } + return result; +} + + return { + exec: exec + } + +}; diff --git a/src/interpreter/runner/scripts/QstRunner.qml b/src/interpreter/runner/scripts/QstRunner.qml new file mode 100644 index 0000000..32aee06 --- /dev/null +++ b/src/interpreter/runner/scripts/QstRunner.qml @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 + +import QstRunner 1.0 +import QtSystemTest 1.0 +import QtSystemTest.Runner 1.0 +import "QstRunner.js" as JsRunner + +Runner { + id: runner + + property variant currentTestItem + property string currentMethod + + property variant report : ({ + 'passed': 0, + 'failed': 0, + 'skipped': 0, + 'untested': 0, + 'error': 0, + }); + + property variant __loggers + + signal aboutToStartExecution() + signal finishedExecution() + signal testCollectionStart(variant testCollection) + signal testCollectionEnd(variant testCollection) + + signal testStart(variant test) + signal testEnd(variant test) + + signal methodStart(string methodName) + signal methodEnd(string methodName) + + property variant component: Component { + id: configComponent + Config { } + } + + + + function __broadcast(fnName, args) { + for (var i =0; i < __loggers.length; ++i) { + var logger = __loggers[i]; + if ( ! (fnName in logger) ) { + throw new Error('function ' + fnName + ' not in ' + logger); + } + var f = logger[fnName]; + f.apply(logger, args); + }; + } + + function logEvent(type, error) { + __broadcast('log', [type, error]); + } + + + function log(messages) { + var str = js.core().stringify.apply(null, arguments); + __broadcast(arguments.callee.name, ['debug', { message: str }]); + } + + + function __setup(args) { + var x = configComponent.createObject(runner); + setRootProperty('config', x); + __loggers = x.loggers; + Array.prototype.forEach.call(__loggers, function(l) { + l.setup(); + }); + return true; + } + + property Js js: Js { } + + function __exec() { + var result = __testRoot.__validate(); + if (!result.valid) { + __broadcast('log', ['Error', result.error]); + return JsRunner.InternalError; + } + console.log('Test validation - okay?: ', result.valid); + + result = 1 << 6; + try { + var x = JsRunner.create(js.core()); + result = x.exec(runner, __testRoot); + } catch (e) { + console.log('Error: internal: ', e.toString()); + console.log('Details:') + for (var k in e) { + console.log(' ', k, ': ' , e[k]); + } + } + return result; + } +} diff --git a/src/objectBrowser/main.cpp b/src/objectBrowser/main.cpp new file mode 100644 index 0000000..b799927 --- /dev/null +++ b/src/objectBrowser/main.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtSystemTest/QstConnection> +#include "qtestbrowserdlg_p.h" +#include <QApplication> + +#define DEFAULT_HOST "localhost" +#define DEFAULT_PORT 5657 + +int main(int argc, char *argv[]) +{ + QApplication *app = new QApplication(argc, argv); + + const QStringList arguments = QCoreApplication::arguments(); + int args = arguments.size(); + QStringList deviceConfig; + + QString hostName(DEFAULT_HOST); + int port = DEFAULT_PORT; + for (int i=1; i<args; ++i) { + QString arg = arguments.at(i); + if (QString("-help").indexOf(arg) == 0) { + qWarning() << QString( + "%1 - Object Browser\n\n" + " -help : Display this help text and exit\n" + " -authost : Host name of system under test (default: %2)\n" + " -port port : Port qtuitestd is listening on (default: %3)\n" + ).arg(arguments[0]).arg(DEFAULT_HOST).arg(DEFAULT_PORT).toLatin1().data(); + exit(0); + } else if (QString("-authost").indexOf(arg) == 0) { + if (i == args-1) { + qWarning() << "Must provide host name"; + exit(1); + } else { + hostName = arguments.at(++i); + } + } else if (QString("-port").indexOf(arg) == 0) { + if (i == args-1) { + qWarning() << "Must provide port"; + exit(1); + } else { + port = arguments.at(++i).toInt(); + if (port == 0) { + qWarning() << "Invalid port"; + exit(1); + } + } + } + } + + //TODO: Parse command line args for host and port + QstConnection *connection = new QstConnection(hostName, port); + if (!connection->connectToRemote()) { + qWarning() << "Failed to connect to host" << hostName << "on port" << port; + exit(1); + } + QTestBrowserDlg *browser = new QTestBrowserDlg(connection); + browser->exec(); + + delete browser; + delete connection; + delete app; + return 0; +} diff --git a/src/objectBrowser/objectBrowser.pro b/src/objectBrowser/objectBrowser.pro new file mode 100644 index 0000000..4489579 --- /dev/null +++ b/src/objectBrowser/objectBrowser.pro @@ -0,0 +1,20 @@ +TEMPLATE = app +TARGET=qstobjectbrowser +DESTDIR=../../bin + +QT+=network + +contains(QT_MAJOR_VERSION, 5) { + QT+=widgets +} + +INCLUDEPATH += ../../include +LIBS += -L../../lib +LIBS += -lQstProtocol + +HEADERS +=\ + qtestbrowserdlg_p.h + +SOURCES +=\ + qtestbrowserdlg.cpp \ + main.cpp diff --git a/src/objectBrowser/qtestbrowserdlg.cpp b/src/objectBrowser/qtestbrowserdlg.cpp new file mode 100644 index 0000000..b0531ec --- /dev/null +++ b/src/objectBrowser/qtestbrowserdlg.cpp @@ -0,0 +1,1139 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qtestbrowserdlg_p.h" +#include <QtSystemTest/QstConnection> + +#include <QAction> +#include <QMenu> +#include <QPushButton> +#include <QDesktopWidget> +#include <QLineEdit> +#include <QComboBox> +#include <QSpinBox> +#include <QTreeWidget> +#include <QTableWidget> +#include <QHeaderView> +#include <QSplitter> +#include <QLayout> +#include <QPixmap> +#include <QMouseEvent> +#include <QPaintEvent> +#include <QPainter> +#include <QVariantMap> +#include <QMetaMethod> +#include <QApplication> +#include <QClipboard> +#include <QMessageBox> +#include <QCheckBox> +#include <QScrollArea> + +QString signature(const QVariantMap &map) +{ + return map[QstConnection::signatureProperty].toString(); +} + +TestImageViewer::TestImageViewer(QWidget *parent, Qt::WindowFlags f) + : QLabel(parent, f) +{ +} + +TestImageViewer::~TestImageViewer() +{ +} + +void TestImageViewer::setSelectedArea(const QRect& rect) +{ + m_selectedArea = rect; + update(); +} + +void TestImageViewer::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + emit clicked(event->pos()); + } +} + +void TestImageViewer::paintEvent(QPaintEvent *event) +{ + QLabel::paintEvent(event); + if (m_selectedArea.isNull()) { + return; + } + + QPainter painter(this); + painter.setPen(Qt::red); + painter.drawRect(m_selectedArea); +} + +QTestBrowserDlg::QTestBrowserDlg( QstConnection* test, const QVariantMap &item, const QVariantMap &imgItem ) + : QDialog(0, Qt::Window) + , m_test(0) + , m_image(0) + , m_appContext(0) + , m_tree(0) + , m_queryTab(0) + , m_propertyTab(0) + , m_itemPropertyTable(0) + , m_queryTable(0) + , m_resultsTable(0) + , m_contextTableItem(0) + , m_flagInvisible(0) + , m_flagDisabled(0) + , m_flagIgnoreScan(0) + , m_refreshAction(0) + , m_expandAction(0) + , m_collapseAction(0) + , m_methodsAction(0) + , m_propertyRefreshAction(0) + , m_propertyMethodsAction(0) + , m_propertyPropertiesAction(0) + , m_propertyQueryAction(0) + , m_propertyCopyAction(0) + , m_propertyCopyTableAction(0) + , m_queryClearAction(0) + , m_queryCopyAction(0) +{ + setSystemTest(test); + createActions(); + createWidgets(); + updateAppContext(); + setBaseItems(item, imgItem); +} + +QTestBrowserDlg::~QTestBrowserDlg() +{ +} + +void QTestBrowserDlg::createActions() +{ + m_refreshAction = new QAction(tr("Refresh"), this); + m_refreshAction->setShortcut(QKeySequence::Refresh); + connect(m_refreshAction, SIGNAL(triggered()), this, SLOT(refresh())); + addAction(m_refreshAction); + + m_expandAction = new QAction(tr("Expand Tree"), this); + m_expandAction->setShortcut(QKeySequence(tr("Alt+E"))); + connect(m_expandAction, SIGNAL(triggered()), this, SLOT(expandAll())); + addAction(m_expandAction); + + m_collapseAction = new QAction(tr("Collapse Tree"), this); + m_collapseAction->setShortcut(QKeySequence(tr("Alt+C"))); + connect(m_collapseAction, SIGNAL(triggered()), this, SLOT(collapseAll())); + addAction(m_collapseAction); + + m_methodsAction = new QAction(tr("View Methods"), this); + m_methodsAction->setShortcut(QKeySequence(tr("Alt+M"))); + connect(m_methodsAction, SIGNAL(triggered()), this, SLOT(viewMethods())); + addAction(m_methodsAction); + + m_propertyRefreshAction = new QAction(tr("Refresh Properties"), this); + connect(m_propertyRefreshAction, SIGNAL(triggered()), this, SLOT(refreshProperties())); + + m_propertyMethodsAction = new QAction(this); + connect(m_propertyMethodsAction, SIGNAL(triggered()), this, SLOT(viewPropertyMethods())); + + m_propertyPropertiesAction = new QAction(this); + connect(m_propertyPropertiesAction, SIGNAL(triggered()), this, SLOT(viewPropertyProperties())); + + m_propertyQueryAction = new QAction(tr("Add as Query Condition"), this); + connect(m_propertyQueryAction, SIGNAL(triggered()), this, SLOT(addPropertyAsQueryCondition())); + + m_propertyCopyAction = new QAction(tr("Copy"), this); + connect(m_propertyCopyAction, SIGNAL(triggered()), this, SLOT(copyTableItemValue())); + + m_propertyCopyTableAction = new QAction(tr("Copy Table"), this); + connect(m_propertyCopyTableAction, SIGNAL(triggered()), this, SLOT(copyTable())); + + m_queryClearAction = new QAction(tr("Clear Query"), this); + connect(m_queryClearAction, SIGNAL(triggered()), this, SLOT(clearQuery())); + + m_queryCopyAction = new QAction(tr("Copy Query"), this); + connect(m_queryCopyAction, SIGNAL(triggered()), this, SLOT(copyQuery())); + +} + +void QTestBrowserDlg::createWidgets() +{ + QHBoxLayout *mainLayout = new QHBoxLayout( this ); + QSplitter *mainSplitter = new QSplitter(Qt::Horizontal, this); + QSplitter *leftSplitter = new QSplitter(Qt::Vertical, this); + QSplitter *rightSplitter = new QSplitter(Qt::Vertical, this); + + mainLayout->addWidget(mainSplitter); + mainSplitter->addWidget(leftSplitter); + mainSplitter->addWidget(rightSplitter); + mainSplitter->setStretchFactor(0, 0); + mainSplitter->setStretchFactor(1, 1); + + m_image = new TestImageViewer(); + m_image->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + connect(m_image, SIGNAL(clicked(QPoint)), this, SLOT(onImageClicked(QPoint))); + + m_image->setAlignment( Qt::AlignCenter ); + m_image->setFrameShape( QLabel::NoFrame ); + m_image->setScaledContents( false ); + + QScrollArea *scrollArea = new QScrollArea; + scrollArea->setWidget(m_image); + leftSplitter->addWidget(scrollArea); + leftSplitter->setStretchFactor(0, 2); + + m_appContext = new QComboBox(this); + m_appContext->installEventFilter(this); + leftSplitter->addWidget(m_appContext); + + m_queryTab = createQueryTab(); + leftSplitter->addWidget(m_queryTab); + + m_tree = new QTreeWidget( this ); + connect(m_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(onItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); + m_tree->setColumnCount(6); + m_tree->setHeaderLabels(QStringList() << QLatin1String("Type") << QLatin1String("Signature") << QLatin1String("QML id") << QLatin1String("objectName") << QLatin1String("Geometry") << QLatin1String("text")); + + rightSplitter->addWidget(m_tree); + rightSplitter->setStretchFactor(0, 2); + m_propertyTab = new QTabWidget(this); + m_itemPropertyTable = new QTableWidget(this); + initPropertyTable(m_itemPropertyTable); + + m_propertyTab->addTab(m_itemPropertyTable, QLatin1String("Item Properties")); + m_propertyTab->setTabEnabled(0, false); + m_propertyTab->setTabPosition(QTabWidget::South); + m_propertyTab->setTabsClosable(true); + connect(m_propertyTab, SIGNAL(tabCloseRequested(int)), this, SLOT(onTabCloseRequested(int))); + + rightSplitter->addWidget(m_propertyTab); + + setWindowTitle( "Object Browser" ); + m_tabItemSignatures.append(""); +} + +QTabWidget * QTestBrowserDlg::createQueryTab() +{ + QTabWidget *tabWidget = new QTabWidget(this); + QFrame *queryFrame = new QFrame(this); + QFrame *flagsFrame = new QFrame(this); + QVBoxLayout *queryLayout = new QVBoxLayout(queryFrame); + QVBoxLayout *flagsLayout = new QVBoxLayout(flagsFrame); + + m_queryTable = new QTableWidget(this); + static QStringList labels(QStringList() << QString() << QLatin1String("Property") << QLatin1String("Value")); + m_queryTable->setColumnCount(labels.count()); + m_queryTable->verticalHeader()->hide(); + m_queryTable->horizontalHeader()->setStretchLastSection(true); + m_queryTable->setHorizontalHeaderLabels(labels); + m_queryTable->setContextMenuPolicy(Qt::CustomContextMenu); + m_queryTable->setEditTriggers(QAbstractItemView::AllEditTriggers); + m_queryTable->setRowCount(1); + addQueryRow(); + m_queryTable->resizeColumnsToContents(); + m_queryTable->setSpan(1, 0, 1, labels.count()); + QPushButton *addButton = new QPushButton(tr("Add New Condition")); + m_queryTable->setCellWidget(1, 0, addButton); + connect(addButton, SIGNAL(clicked()), this, SLOT(addQueryRow()) ); + connect(m_queryTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(onQueryItemChanged(QTableWidgetItem*))); + connect(m_queryTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onQueryContextMenu(QPoint))); + QPushButton *queryButton = new QPushButton("Query"); + connect( queryButton, SIGNAL(clicked()), this, SLOT(doQuery()) ); + queryLayout->addWidget(m_queryTable); + queryLayout->addWidget(queryButton); + + m_flagInvisible = new QCheckBox(QLatin1String("Scan Invisible Items"), this); + m_flagDisabled = new QCheckBox(QLatin1String("Scan Disabled Items"), this); + m_flagIgnoreScan = new QCheckBox(QLatin1String("Ignore Scanned"), this); + QLabel *flagsInfo = new QLabel(QLatin1String("Query Flags are used to control how the search is performed. Please refer to the QtUiTest documentation for details.")); + flagsInfo->setWordWrap(true); + flagsLayout->addWidget(m_flagInvisible); + flagsLayout->addWidget(m_flagDisabled); + flagsLayout->addWidget(m_flagIgnoreScan); + flagsLayout->addWidget(flagsInfo); + + m_resultsTable = new QTableWidget(this); + static QStringList resultLabels(QStringList() << QLatin1String("Signature") << QLatin1String("QML id")); + m_resultsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_resultsTable->setColumnCount(resultLabels.count()); + m_resultsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_resultsTable->setSelectionMode(QAbstractItemView::SingleSelection); + m_resultsTable->verticalHeader()->hide(); + m_resultsTable->horizontalHeader()->setStretchLastSection(true); + m_resultsTable->setHorizontalHeaderLabels(resultLabels); + connect(m_resultsTable, SIGNAL(itemSelectionChanged()), this, SLOT(onResultsItemSelected())); + + tabWidget->addTab(queryFrame, tr("Query")); + tabWidget->addTab(flagsFrame, tr("Query Flags")); + tabWidget->addTab(m_resultsTable, tr("Results")); + + return tabWidget; +} + +void QTestBrowserDlg::updateAppContext() +{ + disconnect(m_appContext, SIGNAL(currentIndexChanged(QString)), this, SLOT(onAppContextChanged(QString))); + m_appContext->clear(); + m_appContext->setCurrentIndex(-1); + QStringList appIds = m_test->getAppIds(); + int appIndex = appIds.indexOf(m_test->currentAppId()); + foreach (const QString &id, appIds) { + QString appName; + QVariantMap appData = m_test->applicationData(id); + appName = appData["appName"].toString(); + appName.append(QString("(%1)").arg(id)); + m_appContext->addItem(appName, id); + } + m_appContext->setCurrentIndex(appIndex); + connect(m_appContext, SIGNAL(currentIndexChanged(QString)), this, SLOT(onAppContextChanged(QString))); +} + +QSize QTestBrowserDlg::sizeHint() const +{ + return QSize(960, 960); +} + +void QTestBrowserDlg::contextMenuEvent(QContextMenuEvent *e) +{ + m_methodsAction->setText(QString("View Methods for %1").arg(currentTabSignature())); + + QMenu menu(this); + menu.addAction(m_refreshAction); + menu.addSeparator(); + menu.addAction(m_expandAction); + menu.addAction(m_collapseAction); + menu.addSeparator(); + menu.addAction(m_methodsAction); + menu.addSeparator(); + + QMenu *subMenu = menu.addMenu(tr("Add Query Condition")); + subMenu->addAction(QLatin1String("CHILD_OF")); + subMenu->addAction(QLatin1String("DESCENDANT_OF")); + subMenu->addAction(QLatin1String("PARENT_OF")); + subMenu->addAction(QLatin1String("ANCESTOR_OF")); + connect(subMenu, SIGNAL(triggered(QAction*)), this, SLOT(onMenuQueryCondition(QAction*))); + menu.exec(e->globalPos()); +} + +void QTestBrowserDlg::setSystemTest ( QstConnection *test ) +{ + m_test = test; + connect(m_test, SIGNAL(appFinished(QString)), this, SLOT(onAppFinished(QString))); + connect(m_test, SIGNAL(appStarted(QString)), this, SLOT(onAppStarted(QString))); +} + +void QTestBrowserDlg::setImage( const QPixmap &img ) +{ + if (!img.isNull()) { + m_image->setPixmap(img); + } else { + m_image->setText("No image available"); + } + + m_image->adjustSize(); + updateGeometry(); +} + +void QTestBrowserDlg::setBaseItems( const QVariantMap &item, const QVariantMap &imgItem ) +{ + if (item.isEmpty()) { + m_appId = m_test->currentAppId(); + qDebug() << "current app id" << m_appId; + m_appId = m_appContext->itemData(m_appContext->currentIndex()).toString(); + m_test->setAppId(m_appId); + QVariantMap appData = m_test->applicationData(m_appId); + m_baseItem = appData["appObject"].toMap(); + m_imgItem = m_baseItem; + } else { + m_baseItem = item; + m_imgItem = imgItem; + m_appId = item[QstConnection::appIdProperty].toString(); + } + refresh(); +} + +void QTestBrowserDlg::setObjectMap ( const QVariantMap &map ) +{ + m_tree->setCursor(Qt::WaitCursor); + m_map = map; + m_geometry = m_map["geometry"].toMap(); + m_children = m_map["children"].toMap(); + m_window = m_map["window"].toMap(); + QString sig = signature(m_baseItem); + + m_tree->clear(); + m_treeMap.clear(); + + addItemToTree(sig); + m_tree->expandAll(); + m_tree->resizeColumnToContents(0); + m_tree->setCursor(Qt::ArrowCursor); +} + +void QTestBrowserDlg::closeWindow() +{ + QDialog::accept(); + deleteLater(); +} + +void QTestBrowserDlg::onImageClicked( const QPoint& point ) +{ + QPoint p = point + m_origin; + QString selectedItem; + int selectedArea=-1; + + foreach (const QString &item, m_window.keys()) { + if (m_window[item] == m_currentWindowSignature) { + QRect rect = m_geometry[item].toRect(); + if (rect.contains(p) && m_map["visible"].toMap()[item].toBool()) { + if (selectedArea == -1 || selectedArea > abs(rect.width() * rect.height())) { + selectedItem = item; + selectedArea = abs(rect.width() * rect.height()); + } + } + } + } + selectItem(selectedItem); +} + +void QTestBrowserDlg::selectItem( const QString &item ) +{ + QTreeWidgetItem *treeItem = m_treeMap[item]; + if (treeItem && treeItem != m_tree->currentItem() && !treeItem->isDisabled()) { + m_tree->collapseAll(); + m_tree->setCurrentItem(treeItem); + } +} + +void QTestBrowserDlg::onItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *prev) +{ + Q_UNUSED(prev); + if (!item || !m_test) { + return; + } + + QString itemSignature = item->text(1); + QString windowSignature = m_window[itemSignature].toString(); + if (windowSignature != m_currentWindowSignature) { + m_currentWindowSignature = windowSignature; + m_imgItem = widgetSpec(windowSignature); + refreshImage(); + } + + QRect rect; + rect = m_geometry[item->text(1)].toRect(); + rect.moveTopLeft(rect.topLeft() - m_origin); + m_image->setSelectedArea(rect); + + QVariantMap propertyMap = + m_test->getProperties(widgetSpec(itemSignature)); + + updatePropertyTable(m_itemPropertyTable, propertyMap); + m_tabItemSignatures.replace(0, itemSignature); + m_propertyTab->setCurrentIndex(0); + m_propertyTab->setTabEnabled(0, true); + m_propertyTab->setTabToolTip(0, QString("Properties: %1").arg(itemSignature)); +} + +void QTestBrowserDlg::onAppContextChanged(const QString &context) +{ + Q_UNUSED(context); + setBaseItems(); +} + +void QTestBrowserDlg::initTable(QTableWidget *table, const QStringList &labels) +{ + table->setColumnCount(labels.count()); + table->verticalHeader()->hide(); + table->horizontalHeader()->setStretchLastSection(true); + table->setHorizontalHeaderLabels(labels); + table->setContextMenuPolicy(Qt::CustomContextMenu); +} + +void QTestBrowserDlg::initPropertyTable(QTableWidget *table) +{ + static QStringList propertyHeaders(QStringList() + << QLatin1String("Property") + << QLatin1String("Value") + ); + + initTable(table, propertyHeaders); + connect(table, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(onPropertyDoubleClicked(QTableWidgetItem*))); + connect(table, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onPropertyContextMenu(QPoint))); +} + +void QTestBrowserDlg::initMethodsTable(QTableWidget *table) +{ + static QStringList methodsHeaders(QStringList() + << QLatin1String("Method Type") + << QLatin1String("Return Type") + << QLatin1String("Method Signature") + ); + + initTable(table, methodsHeaders); + connect(table, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onMethodsContextMenu(QPoint))); +} + +void QTestBrowserDlg::updatePropertyTable(QTableWidget *table, const QVariantMap &propertyMap) +{ + QVariantMap previousValues = table->property("_qttPrevMap").toMap(); + + table->clearContents(); + table->setRowCount(propertyMap.size()); + table->clearSpans(); + + int row = 0; + foreach (const QString &propertyName, propertyMap.keys()) { + QTableWidgetItem *nameItem = new QTableWidgetItem(propertyName); + nameItem->setFlags(Qt::ItemIsEnabled); + table->setItem(row, 0, nameItem); + QVariant value = propertyMap[propertyName]; + + if (value.type() == QVariant::List) { + QVariantList list = value.toList(); + if (list.size() > 0) { + if (list.size() > 1) { + table->setRowCount(table->rowCount() + list.size() -1); + table->setSpan(row, 0, list.size(), 1); + } + foreach (const QVariant &item, list) { + QTableWidgetItem *valueItem = valueToTableItem(item); + valueItem->setFlags(Qt::ItemIsEnabled); + table->setItem(row++, 1, valueItem); + } + continue; + } + } + + QTableWidgetItem *valueItem = valueToTableItem(value, previousValues.value(propertyName)); + valueItem->setFlags(Qt::ItemIsEnabled); + table->setItem(row, 1, valueItem); + row++; + } + + table->resizeRowsToContents(); + int size = table->horizontalHeader()->sectionSize(0); + table->resizeColumnToContents(0); + if (size > table->horizontalHeader()->sectionSize(0)) { + table->horizontalHeader()->resizeSection(0, size); + } + table->setProperty("_qttPrevMap", propertyMap); +} + +void QTestBrowserDlg::updateMethodsTable(QTableWidget *table, const QVariantList &methods) +{ + table->clearContents(); + table->setRowCount(methods.size()); + table->clearSpans(); + + int row = 0; + foreach (const QVariant &method, methods) { + QVariantMap map = method.toMap(); + int methodType = map["methodType"].toInt(); + QString methodTypeName; + switch (methodType) { + case QMetaMethod::Method: + methodTypeName = QLatin1String("Method"); + break; + case QMetaMethod::Signal: + methodTypeName = QLatin1String("Signal"); + break; + case QMetaMethod::Slot: + methodTypeName = QLatin1String("Slot"); + break; + case QMetaMethod::Constructor: + methodTypeName = QLatin1String("Constructor"); + break; + } + QString returnType = map["returnType"].toString(); + QString signature = map["signature"].toString(); + + QTableWidgetItem *typeItem = new QTableWidgetItem(methodTypeName); + typeItem->setFlags(Qt::ItemIsEnabled); + table->setItem(row, 0, typeItem); + + QTableWidgetItem *retItem = new QTableWidgetItem(returnType); + retItem->setFlags(Qt::ItemIsEnabled); + table->setItem(row, 1, retItem); + + QTableWidgetItem *sigItem = new QTableWidgetItem(signature); + sigItem->setFlags(Qt::ItemIsEnabled); + table->setItem(row, 2, sigItem); + + row++; + } + + table->resizeRowsToContents(); + table->resizeColumnsToContents(); + table->sortItems(1); +} + +QTableWidgetItem *QTestBrowserDlg::valueToTableItem(const QVariant &value, const QVariant &previous) +{ + QString valueString = valueToString(value); + QTableWidgetItem *valueItem = new QTableWidgetItem(valueString); + if (previous.isValid() && valueToString(previous) != valueString) { + valueItem->setBackground(QBrush("#ffff80")); + } + if (value.type() == QVariant::Map) { + QString sig = signature(value.toMap()); + if (m_treeMap.contains(sig)) { + valueItem->setForeground(QBrush(Qt::blue)); + } else if (!sig.isEmpty()) { + valueItem->setForeground(QBrush(Qt::darkGreen)); + } + } else if (valueString.startsWith(QChar('<')) + && valueString.endsWith(QChar('>'))) { + valueItem->setForeground(QBrush(Qt::gray)); + return valueItem; + } + valueItem->setData(Qt::UserRole, value); + return valueItem; +} + +QString QTestBrowserDlg::valueToString(const QVariant &value) +{ + QString valueString; + if (value.canConvert(QVariant::String)) { + valueString = value.toString(); + } else if (value.type() == QVariant::List) { + QVariantList list = value.toList(); + if (list.length() == 0) { + valueString = QLatin1String("<Empty List>"); + } else { + QStringList itemStrings; + foreach (const QVariant& item, list) { + itemStrings << valueToString(item); + } + valueString = itemStrings.join(QLatin1String(", ")); + } + } else if (value.type() == QVariant::Map) { + QVariantMap map = value.toMap(); + valueString = signature(map); + if (valueString.isEmpty()) { + if (map.contains(QstConnection::enumProperty)) { + valueString = QString("%1 (%2)").arg(map[QstConnection::valueProperty].toInt()).arg(map[QstConnection::enumProperty].toString()); + } else { + valueString = QLatin1String("<QVariantMap>"); + } + } + } else if (value.type() == QVariant::PointF) { + QRectF rectf = value.toRectF(); + valueString = QString("QPointF (%1,%2)").arg(rectf.x()).arg(rectf.y()); + } else if (value.type() == QVariant::RectF) { + QRectF rectf = value.toRectF(); + valueString = QString("QRectF (%1,%2 %3x%4)").arg(rectf.x()).arg(rectf.y()).arg(rectf.width()).arg(rectf.height()); + } else if (value.type() == QVariant::Size) { + QSize size = value.toSize(); + valueString = QString("QSize (%1x%2)").arg(size.width()).arg(size.height()); + } else if (value.type() == QVariant::SizeF) { + QSizeF size = value.toSizeF(); + valueString = QString("QSizeF (%1x%2)").arg(size.width()).arg(size.height()); + } else { + valueString = QString("<%1>").arg(value.typeName()); + } + return valueString; +} + +void QTestBrowserDlg::addItemToTree(const QString &item, QTreeWidgetItem *parent) +{ + QString geoString; + if (m_geometry.contains(item)) { + QRect rect = m_geometry[item].toRect(); + geoString = QString("%1,%2 %3x%4").arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height()); + } + QTreeWidgetItem *treeItem = new QTreeWidgetItem(parent, QStringList() << + m_map["type"].toMap()[item].toString() << + item << + m_map["qmlid"].toMap()[item].toString() << + m_map["objectName"].toMap()[item].toString() << + geoString << + m_map["text"].toMap()[item].toString() + ); + if (!m_map["visible"].toMap()[item].toBool()) { + treeItem->setForeground(0, QBrush(Qt::gray)); + } + m_tree->addTopLevelItem(treeItem); + m_treeMap[item] = treeItem; + + foreach (const QString &child, m_children[item].toStringList()) { + addItemToTree(child, treeItem); + } +} + +void QTestBrowserDlg::addQueryRow(const QString &property, const QVariant &value) +{ + static QStringList relationshipProperties(QStringList() + << QLatin1String("ANCESTOR_OF") << QLatin1String("CHILD_OF") << QLatin1String("DESCENDANT_OF") << QLatin1String("PARENT_OF")); + + static QStringList qmlProperties(QStringList() + << QLatin1String("QMLID") << QLatin1String("QMLINHERITS") << QLatin1String("QMLTYPE")); + + static QStringList defaultProperties(QStringList() + << QLatin1String("CLASSNAME") << QLatin1String("INHERITS") << QLatin1String("LABEL") << QLatin1String("PROPERTY")); + + int row = m_queryTable->rowCount()-1; + m_queryTable->insertRow(row); + + QTableWidgetItem *checkItem = new QTableWidgetItem(QString()); + checkItem->setCheckState(Qt::Checked); + m_queryTable->setItem(row, 0, checkItem); + + QComboBox *propertyCombo = new QComboBox(); + propertyCombo->addItems(defaultProperties); + propertyCombo->insertSeparator(99); + propertyCombo->addItems(relationshipProperties); + propertyCombo->insertSeparator(99); + propertyCombo->addItems(qmlProperties); + propertyCombo->setEditable(true); + propertyCombo->lineEdit()->setText(property); + propertyCombo->setMaxVisibleItems(propertyCombo->count()+1); + m_queryTable->setCellWidget(row, 1, propertyCombo); + + QTableWidgetItem *valueItem = new QTableWidgetItem(); + if (value.canConvert(QVariant::String)) { + valueItem->setText(value.toString()); + valueItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable); + } else { + valueItem->setText(valueToString(value)); + valueItem->setData(Qt::UserRole, value); + valueItem->setFlags(Qt::NoItemFlags); + } + + m_queryTable->setItem(row, 2, valueItem); + m_queryTable->resizeRowsToContents(); + m_queryTable->scrollToItem(checkItem, QAbstractItemView::PositionAtTop); +} + +QVariantMap QTestBrowserDlg::queryMap() const +{ + QVariantMap map; + for (int i=0; i<m_queryTable->rowCount()-1;) { + QComboBox *propertyCombo = qobject_cast<QComboBox*>(m_queryTable->cellWidget(i, 1)); + QString property; + if (propertyCombo) { + property = propertyCombo->currentText(); + } + QTableWidgetItem *valueItem = m_queryTable->item(i, 2); + QVariant value = valueItem->data(Qt::UserRole); + if (!value.isValid()) { + value = valueItem->text(); + } + if (property.isEmpty() && value.isNull()) { + m_queryTable->removeRow(i); + continue; + } + + if (property.isEmpty()) { + QMessageBox::warning(const_cast<QTestBrowserDlg*>(this), tr("Invalid Query"), QLatin1String("An empty property is not permitted")); + return QVariantMap(); + } + + if (map.contains(property)) { + QMessageBox::warning(const_cast<QTestBrowserDlg*>(this), tr("Invalid Query"), QString("There are duplicate instances of property '%1'").arg(property)); + return QVariantMap(); + } + + map[property] = value; + i++; + } + + if (map.isEmpty()) { + QMessageBox::warning(const_cast<QTestBrowserDlg*>(this), tr("Invalid Query"), QLatin1String("No properties were specified !")); + } + + return map; +} + +void QTestBrowserDlg::doQuery() +{ + m_resultsTable->clearContents(); + m_resultsTable->setRowCount(0); + + QVariantMap map = queryMap(); + if (map.isEmpty()) { + return; + } + + int flags=0; + if (m_flagInvisible->isChecked()) flags |= QstConnection::ScanInvisible; + if (m_flagDisabled->isChecked()) flags |= QstConnection::ScanDisabledItems; + if (m_flagIgnoreScan->isChecked()) flags |= QstConnection::IgnoreScanned; + + QString currentAppId = m_test->currentAppId(); + if (currentAppId != m_appId) { + m_test->setAppId(m_appId); + } + m_matches = m_test->findByProperties(map, flags); + if (currentAppId != m_appId) { + m_test->setAppId(currentAppId); + } + + m_resultsTable->setRowCount(m_matches.count()); + int row=0; + QVariantMap idMap = m_map["qmlid"].toMap(); + foreach (const QString &match, m_matches) { + QTableWidgetItem *item = new QTableWidgetItem(match); + m_resultsTable->setItem(row, 0, item); + QTableWidgetItem *idItem = new QTableWidgetItem(idMap[match].toString()); + m_resultsTable->setItem(row, 1, idItem); + row++; + } + m_resultsTable->resizeRowsToContents(); + m_resultsTable->resizeColumnsToContents(); + m_queryTab->setTabText(2, QString("Results (%1)").arg(m_matches.count())); + m_queryTab->setCurrentIndex(2); +} + +void QTestBrowserDlg::clearQuery() +{ + for (int i=0; i<m_queryTable->rowCount()-1;) { + m_queryTable->removeRow(i); + } +} + +void QTestBrowserDlg::copyQuery() +{ + QVariantMap map = queryMap(); + if (map.isEmpty()) { + return; + } +// QApplication::clipboard()->setText(m_test->objectToString(map)); +} + +void QTestBrowserDlg::expandAll() +{ + m_tree->expandAll(); + m_tree->scrollToItem(m_tree->currentItem()); +} + +void QTestBrowserDlg::collapseAll() +{ + + m_tree->collapseAll(); + m_tree->scrollToItem(m_tree->currentItem()); +} + +void QTestBrowserDlg::refresh() +{ + setObjectMap(m_test->getObjects(m_baseItem)); + refreshImage(); +} + +void QTestBrowserDlg::refreshImage() +{ + m_tree->setEnabled(false); + QImage img(m_test->grabImage(m_imgItem)); + m_origin = m_geometry[m_imgItem["_signature_"].toString()].toRect().topLeft(); + setImage(QPixmap::fromImage(img)); + m_tree->setEnabled(true); +} + +void QTestBrowserDlg::showMatch(int index) +{ + selectItem(m_matches[index]); +} + +void QTestBrowserDlg::viewMethods() +{ + QString currentItem = currentTabSignature(); + QVariantList methods = + m_test->getMethods(widgetSpec(currentItem)); + + QTableWidget *methodsTable = new QTableWidget(); + initMethodsTable(methodsTable); + updateMethodsTable(methodsTable, methods); + int newTabIndex = m_propertyTab->addTab(methodsTable, QString("Methods: %1").arg(currentItem)); + m_tabItemSignatures.append(currentItem); + m_propertyTab->setCurrentIndex(newTabIndex); +} + +void QTestBrowserDlg::onPropertyDoubleClicked(QTableWidgetItem *item) +{ + QString itemText = item->text(); + if (m_treeMap.contains(itemText)) { + selectItem(itemText); + } else { + QVariant value = item->data(Qt::UserRole); + if (value.type() == QVariant::Map) { + QVariantMap map = value.toMap(); + if (map.contains(QstConnection::signatureProperty)) { + openPropertyTab(map[QstConnection::signatureProperty].toString()); + } + } + } +} + +void QTestBrowserDlg::openPropertyTab(const QString &signature) +{ + QVariantMap propertyMap = + m_test->getProperties(widgetSpec(signature)); + + QTableWidget *propertyTable = new QTableWidget(); + initPropertyTable(propertyTable); + updatePropertyTable(propertyTable, propertyMap); + int newTabIndex = m_propertyTab->addTab(propertyTable, QString("Properties: %1").arg(signature)); + m_tabItemSignatures.append(signature); + m_propertyTab->setCurrentIndex(newTabIndex); + +} + +void QTestBrowserDlg::onTabCloseRequested(int tabIndex) +{ + if (tabIndex > 0) { + QWidget *w = m_propertyTab->widget(tabIndex); + m_propertyTab->removeTab(tabIndex); + delete w; + m_tabItemSignatures.removeAt(tabIndex); + } +} + +QString QTestBrowserDlg::currentTabSignature() const +{ + return m_tabItemSignatures.at(m_propertyTab->currentIndex()); +} + +void QTestBrowserDlg::onPropertyContextMenu(const QPoint &pos) +{ + QTableWidget *propertyTable = qobject_cast<QTableWidget*>(m_propertyTab->currentWidget()); + if (propertyTable) { + m_contextTableItem = propertyTable->itemAt(pos); + QMenu menu(this); + + m_methodsAction->setText(QString("View Methods for %1").arg(currentTabSignature())); + menu.addAction(m_propertyRefreshAction); + menu.addSeparator(); + menu.addAction(m_methodsAction); + + if (tableItemIsWidgetIdentifier(m_contextTableItem)) { + m_propertyMethodsAction->setText(QString("View Methods for %1").arg(m_contextTableItem->text())); + m_propertyPropertiesAction->setText(QString("View Properties for %1").arg(m_contextTableItem->text())); + menu.addSeparator(); + menu.addAction(m_propertyMethodsAction); + menu.addAction(m_propertyPropertiesAction); + } + + // Add as Query Condition, only if item is not part of a list + // and the value is valid + if (m_contextTableItem + && propertyTable->rowSpan(m_contextTableItem->row(), 0) == 1 + && propertyTable->item(m_contextTableItem->row(), 1)->data(Qt::UserRole).isValid()) { + menu.addSeparator(); + menu.addAction(m_propertyQueryAction); + } + menu.addSeparator(); + menu.addAction(m_propertyCopyAction); + menu.addAction(m_propertyCopyTableAction); + menu.exec(propertyTable->mapToGlobal(pos)); + m_contextTableItem = 0; + } +} + +void QTestBrowserDlg::onMethodsContextMenu(const QPoint &pos) +{ + QTableWidget *propertyTable = qobject_cast<QTableWidget*>(m_propertyTab->currentWidget()); + if (propertyTable) { + m_contextTableItem = propertyTable->itemAt(pos); + QMenu menu(this); + menu.addAction(m_propertyCopyAction); + menu.addAction(m_propertyCopyTableAction); + menu.exec(propertyTable->mapToGlobal(pos)); + m_contextTableItem = 0; + } +} + +void QTestBrowserDlg::refreshProperties() +{ + QTableWidget *propertyTable = qobject_cast<QTableWidget*>(m_propertyTab->currentWidget()); + if (propertyTable) { + propertyTable->setCursor(Qt::WaitCursor); + QVariantMap propertyMap = + m_test->getProperties(widgetSpec(currentTabSignature())); + updatePropertyTable(propertyTable, propertyMap); + propertyTable->setCursor(Qt::ArrowCursor); + } +} + +void QTestBrowserDlg::viewPropertyMethods() +{ + if (m_contextTableItem) { + QString signature = m_contextTableItem->text(); + QVariantList methods = + m_test->getMethods(widgetSpec(signature)); + + QTableWidget *methodsTable = new QTableWidget(); + initMethodsTable(methodsTable); + updateMethodsTable(methodsTable, methods); + int newTabIndex = m_propertyTab->addTab(methodsTable, QString("Methods: %1").arg(signature)); + m_tabItemSignatures.append(signature); + m_propertyTab->setCurrentIndex(newTabIndex); + } +} + +void QTestBrowserDlg::viewPropertyProperties() +{ + if (m_contextTableItem) { + QString signature = m_contextTableItem->text(); + openPropertyTab(signature); + } +} + +void QTestBrowserDlg::addPropertyAsQueryCondition() +{ + if (m_contextTableItem) { + int row = m_contextTableItem->row(); + QTableWidget *table = m_contextTableItem->tableWidget(); + QTableWidgetItem *propertyItem = table->item(row, 0); + QTableWidgetItem *valueItem = table->item(row, 1); + QVariant value = valueItem->data(Qt::UserRole); + if (value.type() == QVariant::Map) { + QVariantMap map = value.toMap(); + if (map.contains("_enum_")) + value = map.value("_enum_"); + else if (map.contains("_signature_")) + value = map.value("_signature_"); + else + return; + } + addQueryRow(propertyItem->text(), value); + } + m_queryTab->setCurrentIndex(0); +} + +void QTestBrowserDlg::copyTableItemValue() +{ + if (m_contextTableItem) { + QApplication::clipboard()->setText(m_contextTableItem->text()); + } +} + +void QTestBrowserDlg::copyTable() +{ + QTableWidget *propertyTable = qobject_cast<QTableWidget*>(m_propertyTab->currentWidget()); + QString text; + for (int row = 0; row < propertyTable->rowCount(); ++row) { + for (int col = 0; col < propertyTable->columnCount(); ++col) { + QString cellText; + QTableWidgetItem *item = propertyTable->item(row, col); + if (item) { + cellText = propertyTable->item(row, col)->text(); + } + text += QString("%1%2").arg(col ? "\t" : "").arg(cellText); + } + text += QLatin1String("\n"); + } + QApplication::clipboard()->setText(text); +} + +bool QTestBrowserDlg::tableItemIsWidgetIdentifier(const QTableWidgetItem *item) +{ + if (!item) return false; + QVariant value = item->data(Qt::UserRole); + return value.type() == QVariant::Map + && value.toMap().contains(QstConnection::signatureProperty); +} + +QVariantMap QTestBrowserDlg::widgetSpec(const QString &signature) +{ + return m_test->widgetFromSignature(signature, m_appId); +} + +void QTestBrowserDlg::onConnectionClosed() +{ + QMessageBox::warning(this, tr("Connection Lost"), tr("Connection to the test system has been lost.")); +} + +void QTestBrowserDlg::onQueryItemChanged(QTableWidgetItem *item) +{ + if (item->column() == 0 && item->checkState() == Qt::Unchecked) { + m_queryTable->removeRow(item->row()); + } +} + +void QTestBrowserDlg::onQueryContextMenu(const QPoint &pos) +{ + QMenu menu(this); + + menu.addAction(m_queryClearAction); + menu.addAction(m_queryCopyAction); + + menu.exec(m_queryTable->mapToGlobal(pos)); +} + +void QTestBrowserDlg::onResultsItemSelected() +{ + selectItem(m_resultsTable->item(m_resultsTable->currentRow(), 0)->text()); +} + +void QTestBrowserDlg::onMenuQueryCondition(QAction *action) +{ + addQueryRow(action->text(), currentTabSignature()); + m_queryTab->setCurrentIndex(0); +} + +void QTestBrowserDlg::onAppFinished(const QString& appId) +{ + updateAppContext(); + if (appId == m_appId) { + QMessageBox::warning(this, tr("Application Closed"), tr("The application was closed.")); + setBaseItems(); + } +} + +void QTestBrowserDlg::onAppStarted(const QString& appId) +{ + Q_UNUSED(appId); + updateAppContext(); +} + +bool QTestBrowserDlg::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == m_appContext && event->type() == QEvent::MouseButtonPress) { + for (int i=0; i<m_appContext->count(); i++) { + if (m_appContext->itemText(i).isEmpty()) { + QVariantMap appData = m_test->applicationData(m_appContext->itemData(i).toString()); + m_appContext->setItemText(i, appData["appId"].toString()); + } + } + return false; + } else { + return QDialog::eventFilter(obj, event); + } +} diff --git a/src/objectBrowser/qtestbrowserdlg_p.h b/src/objectBrowser/qtestbrowserdlg_p.h new file mode 100644 index 0000000..ecdfa8e --- /dev/null +++ b/src/objectBrowser/qtestbrowserdlg_p.h @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTESTBROWSERDLG_P_H +#define QTESTBROWSERDLG_P_H + +#include <QDialog> +#include <QLabel> +#include <QVariant> +#include <QVariantMap> +#include <QtSystemTest/qstglobal.h> + +class QstConnection; + +QT_BEGIN_NAMESPACE +class QAction; +class QMenu; +class QPushButton; +class QMouseEvent; +class QPaintEvent; +class QTreeWidget; +class QTreeWidgetItem; +class QTableWidget; +class QTableWidgetItem; +class QComboBox; +class QLineEdit; +class QSpinBox; +class QTabWidget; +class QCheckBox; +QT_END_NAMESPACE + +class TestImageViewer : public QLabel +{ + Q_OBJECT + +public: + TestImageViewer( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~TestImageViewer(); + void setSelectedArea(const QRect& rect); + +protected: + void mouseReleaseEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event); + +signals: + void clicked(const QPoint&); + +private: + QRect m_selectedArea; +}; + +class QSYSTEMTEST_EXPORT QTestBrowserDlg : public QDialog +{ + Q_OBJECT + +public: + QTestBrowserDlg(QstConnection*, const QVariantMap& = QVariantMap(), const QVariantMap& = QVariantMap()); + ~QTestBrowserDlg(); + + virtual QSize sizeHint() const; + virtual void contextMenuEvent(QContextMenuEvent *e); + void setSystemTest ( QstConnection *test ); + void setImage( const QPixmap& ); + void setBaseItems( const QVariantMap& = QVariantMap(), const QVariantMap& = QVariantMap() ); + void setObjectMap ( const QVariantMap& ); + +public slots: + void closeWindow(); + void onImageClicked(const QPoint&); + void onItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *prev); + void onAppContextChanged(const QString& context); + void addQueryRow(const QString &property = QString(), const QVariant &value = QString()); + void doQuery(); + void clearQuery(); + void copyQuery(); + void expandAll(); + void collapseAll(); + void refresh(); + void refreshImage(); + void showMatch(int); + void viewMethods(); + void selectItem(const QString& item); + void onPropertyDoubleClicked(QTableWidgetItem *item); + void onTabCloseRequested(int); + void onPropertyContextMenu(const QPoint&); + void onMethodsContextMenu(const QPoint&); + void refreshProperties(); + void viewPropertyMethods(); + void viewPropertyProperties(); + void addPropertyAsQueryCondition(); + void copyTableItemValue(); + void copyTable(); + void onConnectionClosed(); + void onQueryItemChanged(QTableWidgetItem *item); + void onQueryContextMenu(const QPoint&); + void onResultsItemSelected(); + void onMenuQueryCondition(QAction *action); + void onAppFinished(const QString&); + void onAppStarted(const QString&); + +protected: + bool eventFilter( QObject *obj, QEvent *event); + +private: + void createActions(); + void createWidgets(); + QTabWidget *createQueryTab(); + void updateAppContext(); + + void addItemToTree(const QString &item, QTreeWidgetItem *parent = 0); + void initTable(QTableWidget *table, const QStringList&); + void initPropertyTable(QTableWidget *table); + void initMethodsTable(QTableWidget *table); + void updatePropertyTable(QTableWidget *table, const QVariantMap &propertyMap); + void updateMethodsTable(QTableWidget *table, const QVariantList &methods); + QTableWidgetItem *valueToTableItem(const QVariant &value, const QVariant &previous = QVariant()); + QString valueToString(const QVariant &value); + QString currentTabSignature() const; + bool tableItemIsWidgetIdentifier(const QTableWidgetItem *item); + QVariantMap widgetSpec(const QString &signature); + void openPropertyTab(const QString &signature); + QVariantMap queryMap() const; + + QVariantMap m_baseItem; + QVariantMap m_imgItem; + QString m_appId; + QString m_visibleTabItem; + QPoint m_origin; + QVariantMap m_map; + QVariantMap m_geometry; + QVariantMap m_children; + QVariantMap m_window; + QMap<QString,QTreeWidgetItem*> m_treeMap; + QStringList m_matches; + QStringList m_tabItemSignatures; + QString m_currentWindowSignature; + + QstConnection *m_test; + TestImageViewer *m_image; + QComboBox *m_appContext; + QTreeWidget *m_tree; + QTabWidget *m_queryTab; + QTabWidget *m_propertyTab; + QTableWidget *m_itemPropertyTable; + QTableWidget *m_queryTable; + QTableWidget *m_resultsTable; + QTableWidgetItem *m_contextTableItem; + + QCheckBox *m_flagInvisible; + QCheckBox *m_flagDisabled; + QCheckBox *m_flagIgnoreScan; + + QAction *m_refreshAction; + QAction *m_expandAction; + QAction *m_collapseAction; + QAction *m_methodsAction; + + // Table context menu actions + QAction *m_propertyRefreshAction; + QAction *m_propertyMethodsAction; + QAction *m_propertyPropertiesAction; + QAction *m_propertyQueryAction; + QAction *m_propertyCopyAction; + QAction *m_propertyCopyTableAction; + + // Query actions + QAction *m_queryClearAction; + QAction *m_queryCopyAction; +}; + +#endif diff --git a/src/protocol/QstConnection b/src/protocol/QstConnection new file mode 100644 index 0000000..6d2fbf2 --- /dev/null +++ b/src/protocol/QstConnection @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstconnection.h" diff --git a/src/protocol/QstConnectionManager b/src/protocol/QstConnectionManager new file mode 100644 index 0000000..dc9726b --- /dev/null +++ b/src/protocol/QstConnectionManager @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstconnectionmanager.h" diff --git a/src/protocol/QstDebug b/src/protocol/QstDebug new file mode 100644 index 0000000..aa3c4d3 --- /dev/null +++ b/src/protocol/QstDebug @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstdebug.h" diff --git a/src/protocol/QstProtocol b/src/protocol/QstProtocol new file mode 100644 index 0000000..8afe44f --- /dev/null +++ b/src/protocol/QstProtocol @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstprotocol.h" diff --git a/src/protocol/protocol.pro b/src/protocol/protocol.pro new file mode 100644 index 0000000..c9ad254 --- /dev/null +++ b/src/protocol/protocol.pro @@ -0,0 +1,45 @@ +TEMPLATE = lib + +TARGET = QstProtocol +TARGETPATH = QtSystemTest + +TEMPLATE = lib + +CONFIG += no_clean qt +QT += core + +SOURCES += \ + qstprotocol.cpp \ + qstconnection.cpp \ + qstconnectionmanager.cpp + +PUBLIC_HEADERS += \ + qstprotocol.h \ + qstconnection.h \ + qstconnectionmanager.h \ + qstglobal.h \ + qstdebug.h \ + QstProtocol \ + QstConnection \ + QstConnectionManager \ + QstDebug + +HEADERS = $$PUBLIC_HEADERS + +# Installing libs and headers into Qt lib +includes.files = $$PUBLIC_HEADERS +includes.path = $$[QT_INSTALL_HEADERS]/$$TARGETPATH + +target.path = $$[QT_INSTALL_LIBS] + +INSTALLS += includes target + +# Building so that other libs in project can access this lib +DESTDIR = ../../lib +INCLUDEDESTDIR = $$OUT_PWD/../../include/$$TARGETPATH +includedir.target = dummytarget +includedir.commands = (mkdir -p $$INCLUDEDESTDIR && cd $$PWD && cp $$PUBLIC_HEADERS $$INCLUDEDESTDIR/) + +QMAKE_EXTRA_TARGETS += includedir + +PRE_TARGETDEPS += dummytarget diff --git a/src/protocol/qstconnection.cpp b/src/protocol/qstconnection.cpp new file mode 100644 index 0000000..c57cae8 --- /dev/null +++ b/src/protocol/qstconnection.cpp @@ -0,0 +1,263 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstconnection.h" +#include "qstprotocol.h" + +#include <QtCore/QDebug> + +const QLatin1String QstConnection::appIdProperty("_appid_"); +const QLatin1String QstConnection::enumProperty("_enum_"); +const QLatin1String QstConnection::signatureProperty("_signature_"); +const QLatin1String QstConnection::valueProperty("_value_"); +const QLatin1String QstConnection::widgetSpecifierProperty("widgetSpecifier"); + +QstConnection::QstConnection(QObject *parent) + : QstProtocol(parent) +{ +} + +QstConnection::QstConnection(const QString &host, int port, QObject *parent) + : QstProtocol(parent) + , m_host(host) + , m_port(port) + , m_queryFailed(false) +{ +} + +void QstConnection::processMessage( QstMessage *msg ) +{ + if (!msg) return; + + if (msg->event() == QLatin1String("APP_STARTED")) { + emit appStarted(msg->context()); + } else if (msg->event() == QLatin1String("APP_FINISHED")) { + emit appFinished(msg->context()); + } else { + emit messageReceived(msg->event(), msg->context(), msg->toMap()); + } +} + +bool QstConnection::connectToRemote() +{ + if (isConnected()) { + qDebug() << Q_FUNC_INFO << "Already connected to "<< m_host; + return true; + } + + QTime t; + t.start(); + while (t.elapsed() < 10000 && !isConnected()) { + QstProtocol::connect(m_host, m_port); + waitForConnected(2000); + } + + if (!isConnected()) { + qDebug() << Q_FUNC_INFO << "Could not connect to " << m_host << ':' << m_port; +/// FIXME: is this needed? +// errorMsg = errorStr() ; + return false; + } + + return true; +} + +QVariantMap QstConnection::sendQuery(const QString &event, const QVariantMap ¶ms, const QVariantMap &widgetSpecifier) +{ + QstMessage message(event, params); +// qDebug() << "message " << event << message.toMap(); + message[widgetSpecifierProperty] = widgetSpecifier[signatureProperty].toString(); + if (widgetSpecifier.contains(appIdProperty)) { + qDebug() << " context set "; + message.setContext(widgetSpecifier[appIdProperty].toString()); + } + else if (params.contains(appIdProperty)) { + message.setContext(params[appIdProperty].toString()); + } + + m_queryFailed = false; + QstMessage reply; + if (!sendMessage( message, reply, 10000 )) { + // Unable to send - should fail test + qDebug() << "Failed to send message"; + m_queryFailed = true; + return reply.toMap(); + } + + return reply.toMap(); +} + +QVariantMap QstConnection::sendPositionQuery(const QString &event, const QVariantMap ¶ms, const QPointF &position) +{ +// qDebug() << event << position; + QVariantMap _params(params); + _params["pos"] = position; + return sendQuery(event, _params); +} + + +QVariantMap QstConnection::applicationData(const QString &appId) +{ + QstMessage message("applicationData"); + if (!appId.isEmpty()) { + message.setContext(appId); + } + + QVariantMap ret; + QstMessage reply; + if (!sendMessage(message, reply, 10000)) { + return ret; + } + ret = reply["applicationdata"].toMap(); + return ret; +} + +QImage QstConnection::grabImage(const QVariantMap &widgetSpecifier) +{ + QImage im; + QVariantMap reply = sendQuery("grabImage", QVariantMap(), widgetSpecifier); + if (!m_queryFailed) { + im = reply["grabimage"].value<QImage>(); + } + return im; +} + +QVariantMap QstConnection::getObjects( const QVariantMap &widgetSpecifier ) +{ + QVariantMap map; + QVariantMap reply = sendQuery("getObjects", QVariantMap(), widgetSpecifier); + if (!m_queryFailed) { + map = reply["getobjects"].toMap(); + } + return map; +} + +QVariantMap QstConnection::getProperties( const QVariantMap &widgetSpecifier ) +{ + QVariantMap ret; + QVariantMap reply = sendQuery("getProperties", QVariantMap(), widgetSpecifier); + if (!m_queryFailed) { + ret = reply["getproperties"].toMap(); + } + return ret; +} + +QVariantList QstConnection::getMethods( const QVariantMap &widgetSpecifier ) +{ + QVariantList ret; + QVariantMap reply = sendQuery("getMethods", QVariantMap(), widgetSpecifier); + if (!m_queryFailed) { + ret = reply["getmethods"].toList(); + } + return ret; +} + +QVariantMap QstConnection::widgetFromSignature( const QString &signature, const QString &appId ) +{ + QVariantMap ret; + ret[signatureProperty] = signature; + if (!appId.isEmpty()) + ret[appIdProperty] = appId; + + return ret; +} + +QStringList QstConnection::getAppIds(const QString &name) +{ + QVariantMap params; + if (!name.isEmpty()) { + params["name"] = name; + } + QStringList ret; + QVariantMap reply = sendQuery("getApplications", params); + if (!m_queryFailed) { + ret = reply["getapplications"].toStringList(); + } + return ret; +} + +QString QstConnection::currentAppId() +{ + QString ret; + QVariantMap reply = sendQuery("currentApplication", QVariantMap()); + if (!m_queryFailed) { + ret = reply["currentapplication"].toString(); + } + return ret; +} + +QString QstConnection::homeAppId() +{ + QString ret; + QVariantMap reply = sendQuery("homeApplication", QVariantMap()); + if (!m_queryFailed) { + ret = reply["homeapplication"].toString(); + } + return ret; +} + +void QstConnection::setAppId(const QString& appId) +{ + QstMessage message("setApplication"); + message.setContext(appId); + + QstMessage reply; + sendMessage(message, reply, 10000); +} + +QStringList QstConnection::findByProperties( const QVariantMap &searchValues, int flags ) +{ + QVariantMap params; + params["searchvalues"] = searchValues; + params["flags"] = flags; + + QStringList ret; + QVariantMap reply = sendQuery("queryProperties", params); + + if (!m_queryFailed) { + QVariantList matches = reply["queryproperties"].toList(); + foreach (const QVariant &item, matches) + { + ret << item.toMap()[signatureProperty].toString(); + } + } + return ret; +} diff --git a/src/protocol/qstconnection.h b/src/protocol/qstconnection.h new file mode 100644 index 0000000..f4107db --- /dev/null +++ b/src/protocol/qstconnection.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTCONNECTION_H +#define QSTCONNECTION_H + +#include "qstprotocol.h" +#include <QtCore/QVariantMap> +#include <QtCore/QPointF> +#include <QImage> +#include <QStringList> + +class QstConnection : public QstProtocol +{ + Q_OBJECT + +public: + + enum QueryFlag + { + NoSort = 0x01, + NoScan = 0x02, + ScanInvisible = 0x04, + ScanDisabledItems = 0x08, + IgnoreScanned = 0x10 + }; + Q_DECLARE_FLAGS(QueryFlags, QueryFlag) + + QstConnection(QObject *parent = 0); + explicit QstConnection(const QString & host, int port, QObject *parent = 0); + + static const QLatin1String appIdProperty; + static const QLatin1String enumProperty; + static const QLatin1String signatureProperty; + static const QLatin1String valueProperty; + static const QLatin1String widgetSpecifierProperty; + + + QVariantMap applicationData(const QString &appId); + QImage grabImage(const QVariantMap &widgetSpecifier); + QVariantMap getObjects( const QVariantMap &widgetSpecifier ); + QVariantMap getProperties( const QVariantMap &widgetSpecifier ); + QVariantList getMethods( const QVariantMap &widgetSpecifier ); + QVariantMap widgetFromSignature( const QString &signature, const QString &appId ); + QStringList getAppIds(const QString & = QString()); + QString currentAppId(); + QString homeAppId(); + void setAppId(const QString& appId); + QStringList findByProperties( const QVariantMap &searchValues, int flags ); + +signals: + void appStarted(const QString &context); + void appFinished(const QString &context); + void messageReceived(const QString &event, const QString &context, const QVariantMap &data); + +protected: + virtual void processMessage( QstMessage *msg ); + +public slots: + bool connectToRemote(); + QVariantMap sendQuery(const QString &event, const QVariantMap ¶ms, const QVariantMap &widgetSpecifier = QVariantMap()); + QVariantMap sendPositionQuery(const QString &event, const QVariantMap ¶ms, const QPointF &position); + +private: + QString m_host; + int m_port; + bool m_queryFailed; +}; + +#endif diff --git a/src/protocol/qstconnectionmanager.cpp b/src/protocol/qstconnectionmanager.cpp new file mode 100644 index 0000000..d3fc295 --- /dev/null +++ b/src/protocol/qstconnectionmanager.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstconnectionmanager.h" +#include "qstconnection.h" + +#include <QtDebug> + +QstConnectionManager::QstConnectionManager(QObject *parent) : + QObject(parent) +{ +} + +QstConnection* QstConnectionManager::connectionForHost(const QString &host, int port) +{ + if ( !m_connections.contains(host) ) { +// qDebug() << Q_FUNC_INFO << " Creating a new connection with (" << host << ":" << port << ")"; + m_connections[host] = new QstConnection(host, port); + } + return m_connections[host]; +} diff --git a/src/protocol/qstconnectionmanager.h b/src/protocol/qstconnectionmanager.h new file mode 100644 index 0000000..04b6daf --- /dev/null +++ b/src/protocol/qstconnectionmanager.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTCONNECTIONMANAGER_H +#define QSTCONNECTIONMANAGER_H + +#include <QtCore/QObject> +#include <QtCore/QMap> + +class QstConnection; + +class QstConnectionManager : public QObject +{ + Q_OBJECT +public: + explicit QstConnectionManager(QObject *parent = 0); + +signals: + +public slots: + QstConnection *connectionForHost(const QString &host, int port = 5656); + +private: + typedef QMap<QString, QstConnection*> Connections; + Connections m_connections; +}; + +#endif // QSTCONNECTIONMANAGER_H diff --git a/src/protocol/qstdebug.h b/src/protocol/qstdebug.h new file mode 100644 index 0000000..4afa3c0 --- /dev/null +++ b/src/protocol/qstdebug.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTT_DEBUG_H +#define QTT_DEBUG_H + +#include <QDebug> +#ifndef qttDebug +#define qttDebug qDebug +#endif + +#define QTT_TRACE_FUNCTION() + +#endif // QTT_DEBUG_H diff --git a/src/protocol/qstglobal.h b/src/protocol/qstglobal.h new file mode 100644 index 0000000..f25915a --- /dev/null +++ b/src/protocol/qstglobal.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QST_GLOBAL_H +#define QST_GLOBAL_H + +#include <QtGlobal> + +#if defined(Q_OS_WIN32) +# if defined(QTUITEST_TARGET) +# define QTUITEST_EXPORT Q_DECL_EXPORT +# else +# define QTUITEST_EXPORT Q_DECL_IMPORT +# endif +# if defined(QTSLAVE_TARGET) +# define QTSLAVE_EXPORT Q_DECL_EXPORT +# else +# define QTSLAVE_EXPORT Q_DECL_IMPORT +# endif +#else +# define QTUITEST_EXPORT Q_DECL_EXPORT +# define QTSLAVE_EXPORT Q_DECL_EXPORT +#endif + +#if defined(Q_OS_WIN32) || defined(Q_OS_SYMBIAN) +# if defined(QSYSTEMTEST_TARGET) +# define QSYSTEMTEST_EXPORT Q_DECL_EXPORT +# else +# define QSYSTEMTEST_EXPORT Q_DECL_IMPORT +# endif +# if defined(QTUITESTRUNNER_TARGET) +# define QTUITESTRUNNER_EXPORT Q_DECL_EXPORT +# else +# define QTUITESTRUNNER_EXPORT Q_DECL_IMPORT +# endif +#else +# define QSYSTEMTEST_EXPORT Q_DECL_EXPORT +# define QTUITESTRUNNER_EXPORT Q_DECL_EXPORT +#endif + +#define xstr(s) str(s) +#define str(s) #s +#define QTUITEST_VERSION_STR xstr(QTUITEST_VERSION) + +#endif diff --git a/src/protocol/qstprotocol.cpp b/src/protocol/qstprotocol.cpp new file mode 100644 index 0000000..c5a69b8 --- /dev/null +++ b/src/protocol/qstprotocol.cpp @@ -0,0 +1,1086 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +/* + This cpp file contains a number of socket related classes that are used heavily in QtUiTest. + The classes are documented later in the file. +*/ +#include "qstprotocol.h" + +#ifdef QTUITEST_TARGET +#include <qtuitestnamespace.h> +#endif + +#include <QCoreApplication> +#include <QString> +#include <QTimer> +#include <QUuid> +#include <QFileInfo> +#include <QDir> +#include <QtNetwork/QTcpSocket> +#include <QtNetwork/QTcpServer> +#include <QtNetwork/QHostAddress> +#include <QtNetwork/QHostInfo> +#include <QPointer> + +#include <QDebug> +#define qLog(A) if (1); else qDebug() + +#if defined(Q_OS_WIN32) && !defined(Q_OS_TEMP) +# include <io.h> +#endif + +static const int CONNECT_TIMEOUT = 20000; + +static const quint32 TEST_MSG_SIGNATURE = 0xEDBAEDBA; +static const quint32 TEST_MSG_END = 0xEDBAABDE; +static uint g_unique_id = 0; + +bool waitForSignal(QObject* object, const char* signal, int timeout) +{ +#ifdef QTUITEST_TARGET + return QtUiTest::waitForSignal(object, signal, timeout); +#else + QEventLoop loop; + QTimer dummy; + dummy.setInterval(1000); + if (!QObject::connect(object, signal, &dummy, SLOT(start()))) + return false; + if (!QObject::connect(object, signal, &loop, SLOT(quit()))) + return false; + QTimer::singleShot(timeout, &loop, SLOT(quit())); + loop.exec(); + return dummy.isActive(); +#endif +} + +void wait(int timeout) +{ +#ifdef QTUITEST_TARGET + QtUiTest::wait(timeout); +#else + QEventLoop loop; + QTimer::singleShot(timeout, &loop, SLOT(quit())); + loop.exec(); +#endif +} + + +/* + \class QstMessage qstprotocol.h + \inpublicgroup QtUiTestModule + + \brief The QstMessage class can be used for exchanging messages between separate + processes. The class is never used directly but instead is used by QstProtocol. + + The class basically wraps a number of strings (i.e. 'event' and 'message') and binary data + (i.e. a bytearray or a file) into a datastream that is sent to a peer using a socket + connection. On the receiving side a QstMessage instance is decoding the datastream + and performs a number of sanity checks to make it a bit more robost. + + A TCP connection 'should' be reliable but in exceptional cases bytes may be lost. This + would result in the connection becoming useless because all future data reception would + be out of sync. To solve this a 'resync' function is implemented that can re-sync the datastream + by throwing away bytes until the data seems in sync again. The obvious downside is that + at least one message will be lost. + + Message format is as follows: + + Field: Length: Remarks: + + Start signature 4 Fixed value - 0xEDBAEDBA + Message state 1 See MessageState enum + Message number 2 + Length 4 Length of event/context block + Event:Context Length QString value (event and context) + Data length 4 Length of following binary data + File data Data length Binary data + End signature 4 Fixed value - 0xEDBAABDE +*/ + +/* + \internal + + Constructs a default (empty) message. +*/ + +QstMessage::QstMessage(const QString &event, QVariantMap const &map) + : m_phase(0) + , m_msg_id(0) + , m_event(event) + , m_state(MessageEmpty) + , m_map(map) +{ +} + +/* + \internal + + Copy constructor. +*/ + +QstMessage::QstMessage(const QstMessage &other) + : m_phase(0) + , m_msg_id(other.m_msg_id) + , m_event(other.m_event) + , m_context(other.m_context) + , m_state(other.m_state) + , m_map(other.m_map) + , m_buffer(other.m_buffer) +{ +} + +/* + \internal + + Destroys the message. +*/ + +QstMessage::~QstMessage() +{ +} + +/* + \internal + + Assignment operator. +*/ + +QstMessage& QstMessage::operator=(const QstMessage &other) +{ + m_msg_id = other.m_msg_id; + m_event = other.m_event; + m_context = other.m_context; + m_state = other.m_state; + m_map = other.m_map; + m_buffer = other.m_buffer; + + return *this; +} + +QVariant &QstMessage::operator[](const QString &key) +{ + unpack(); + return m_map[key.toLower()]; +} + +const QVariant QstMessage::operator[](const QString &key) const +{ + unpack(); + return m_map[key.toLower()]; +} + +bool QstMessage::contains(const QString &key) const +{ + unpack(); + return m_map.contains(key.toLower()); +} + +QList<QString> QstMessage::keys() const +{ + unpack(); + return m_map.keys(); +} + +QString QstMessage::toString() const +{ + QString ret; + if (!isUnpacked()) { + ret = QLatin1String("(packed)\n"); + return ret; + } + + QVariantMap::const_iterator i = m_map.constBegin(); + while (i != m_map.constEnd()) { + if (!i.value().isValid()) { + i++; + continue; + } + ret += i.key() + QLatin1String(": "); + if (i.value().canConvert<QStringList>()) + ret += QLatin1String("'") + i.value().toStringList().join(QLatin1String("','")) + QLatin1String("'"); + else if (i.value().canConvert<QString>()) + ret += QLatin1String("'") + i.value().toString() + QLatin1String("'"); + else + ret += QLatin1String("(data)"); + ret += QLatin1Char('\n'); + ++i; + } + + if (ret.endsWith(QLatin1Char('\n'))) ret.chop(1); + return ret; +} + +QVariantMap QstMessage::toMap() const +{ + return m_map; +} + +/* + \internal + Returns the event that was received. +*/ + +QString QstMessage::event() const +{ + return m_event; +} + +void QstMessage::setEvent(const QString &event) +{ + m_event = event; +} + +/* + \internal + Returns the message number. +*/ + +quint16 QstMessage::msgId() const +{ + return m_msg_id; +} + +bool QstMessage::isNull() const +{ + return m_map.isEmpty(); +} + +bool QstMessage::isUnpacked() const +{ + return m_buffer.isEmpty(); +} + +void QstMessage::unpack() const +{ + if (isUnpacked()) return; + + QDataStream s(&m_buffer, QIODevice::ReadOnly); + s.setVersion(QDataStream::Qt_4_6); + s >> m_map; + m_buffer.clear(); +} + + +/* + \class QstProtocol qstprotocol.h + \inpublicgroup QtUiTestModule + + \brief The QstProtocol class can be used for exchanging messages between separate + processes. + + It is intended to be fast but at the same time ultra reliable and robust communication protocol. + + The main function that is used on the sending side is: + \code + myConnection.postMessage( "My-Event", "My-Message", ptr_to_my_data ); + \endcode + + On the receiving side the main function is a re-implemented 'processMessage': + \code + void MyTestConnection::processMessage( QstMessage *msg ) + { + if (msg->event() == "My-Event") { + print( msg->message() ); + } + } + \endcode +*/ + +#include <stdio.h> + +QstProtocol::QstProtocol(QObject *parent) + : QTcpSocket(parent) + , tx_msg_id(1) + , port(0) + , onData_busy(false) + , enable_reconnect(false) + , reconnect_interval(10000) + , last_data_received(false) + , connection_valid(false) + , debug_on(false) + , m_auto_unpack(true) +{ + static int id1 = qRegisterMetaType<QstMessage>(); Q_UNUSED(id1); + static int id2 = qRegisterMetaType<QstMessage*>(); Q_UNUSED(id2); + static int id3 = qRegisterMetaType<const QstMessage*>(); Q_UNUSED(id3); + + unique_id = QString::number(++g_unique_id); + if (debug_on) { + qDebug() << QString("%1 QstProtocol::QstProtocol()").arg(uniqueId()).toLatin1(); + } + cur_message = 0; + rx_busy = false; + + QObject::connect( &connect_timer, SIGNAL(timeout()), this, SLOT(connectTimeout()), Qt::DirectConnection ); + + QObject::connect( this,SIGNAL(connected()),this,SLOT(onSocketConnected()), Qt::DirectConnection ); + QObject::connect( this,SIGNAL(disconnected()),this,SLOT(onSocketClosed()), Qt::DirectConnection ); + QObject::connect( this,SIGNAL(readyRead()),this,SLOT(onData()), Qt::DirectConnection ); + + // initialize. Any time is better than no time. + rx_timer.start(); +} + +/*! + Destructs the instance of QstProtocol. +*/ + +QstProtocol::~QstProtocol() +{ + if (debug_on) { + qDebug() << QString("%1 QstProtocol::~QstProtocol()").arg(uniqueId()).toLatin1(); + } + enableReconnect( false, 0 ); + + // anything that is still in the tx buffer gets lost + abort(); + close(); + + while (send_msg_replies.count() > 0) + delete send_msg_replies.takeFirst(); + while (unhandled_msg.count() > 0) + delete unhandled_msg.takeFirst(); +} + +void QstProtocol::setSocket( int socket ) +{ + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::setSocket(socket=%2)"). + arg(uniqueId()). + arg(socket).toLatin1()); + } + setSocketDescriptor( socket ); + + rx_timer.start(); + testConnection(); +} + +void QstProtocol::enableReconnect( bool enable, uint reconnectInterval ) +{ + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::enableReconnect( enable=%2, interval=%3)"). + arg(uniqueId()). + arg(enable). + arg(reconnectInterval).toLatin1()); + } + enable_reconnect = enable; + reconnect_interval = reconnectInterval; +} + +/*! + Opens a socket connection to the specified \a hostname and \a port. + + After a connection is successfully opened the instance will listen for and process + incoming commands received from the remote host. +*/ +void QstProtocol::connect( const QString& hostname, int port ) +{ + if (state() == ConnectedState) { + if (hostname == this->host && port == this->port) + return; + disconnect(); + } + + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::connect(%2:%3)"). + arg(uniqueId()). + arg(hostname). + arg(port).toLatin1()); + } + + rx_timer.start(); + + this->host = hostname; + this->port = port; + + reconnect(); +} + +void QstProtocol::disconnect( bool disableReconnect ) +{ + if (state() == ConnectedState) { + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::disconnect(disableReconnect=%2)"). + arg(uniqueId()). + arg(disableReconnect).toLatin1()); + } + // be polite and tell the other side we are closing + postMessage( QstMessage("QTEST_CLOSING_CONNECTION") ); + + // we are closing ourselves, so we don't want to reconnect + if (disableReconnect) enable_reconnect = false; + + onSocketClosed(); + } +} + +bool QstProtocol::isConnected() +{ + return ((state() == ConnectedState) && connection_valid); +} + +bool QstProtocol::waitForConnected( int timeout ) +{ + QTime t; + t.start(); + bool ok = false; + QTime t2; + t2.start(); + while (t.elapsed() < timeout && !ok) { + ok = QTcpSocket::waitForConnected(timeout); + if (!ok) { + wait(100); + if (t2.elapsed() > 1000) { + t2.start(); + reconnect(); + } + } + } + + if (ok) { + if (debug_on) { + qDebug() << QString("%1 QstProtocol::waitForConnected(%2, %3) ...") + .arg(uniqueId()).arg(timeout).arg(stateStr()).toLatin1(); + } + t2.start(); + while (t.elapsed() < timeout && !isConnected()) { + wait(10); + if (!isConnected() && t2.elapsed() > 500) { + postMessage( QstMessage(QLatin1String("QTEST_NEW_CONNECTION")) ); + t2.start(); + } + } + ok = isConnected(); + } + + if (debug_on) { + qDebug() << QString("%1 QstProtocol::waitForConnected() ... %2 (%3 ms)").arg(uniqueId()).arg(ok ? "OK" : "FAILED" ).arg(t.elapsed()).toLatin1(); + if (!ok) qDebug() << errorStr(); + } + return ok; +} + +/*! + \internal + Posts (e.g. non blocking) an \a event, \a message and contents of \a fileName to the remote host. +*/ + +uint QstProtocol::postMessage(const QstMessage &message ) +{ + if (debug_on && message.event() != QLatin1String("PING") && message.event() != QLatin1String("PONG")) { + qDebug() << ( QString("%1 QstProtocol::postMessage(%2)"). + arg(uniqueId()). + arg(message.event()).toLatin1()); + } + if (state() != ConnectedState) + return 0; + QstMessage msg(message); + msg.m_msg_id = tx_msg_id++; + send( msg ); + return msg.m_msg_id; +} + +void QstProtocol::onReplyReceived( QstMessage* /*reply*/ ) +{ +} + +/*! + \internal + Sends an \a event, \a message and \a data to the remote host and waits for up to + \a timeout milliseconds for a reply. If a reply is received, the reply's message + string is placed in \a reply. +*/ +bool QstProtocol::sendMessage( const QstMessage &message, QstMessage &reply, int timeout ) +{ + QstMessage msg(message); + QPointer<QstProtocol> safeThis(this); + bool safeDebugOn(debug_on); + QString safeUniqueId(uniqueId()); + + last_send_cmd = message.event(); + + if (state() == ConnectingState) { + wait(4000); + } + + if (state() == ConnectedState) { + msg.m_msg_id = tx_msg_id++; + + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::sendMessage(%2) msgid=%3)"). + arg(uniqueId()). + arg(msg.event()). + arg(msg.msgId()). + toLatin1()); + } + + send( msg ); + + QTime t1; + t1.start(); + QTime t2; + t2.start(); + bool first_time = true; + while ( (state() == ConnectedState) && + (timeout < 0 || t1.elapsed() < timeout) ) { + + if (debug_on) { + if (first_time || t2.elapsed() > 1000) { + qDebug() << ( QString("%1 QstProtocol::sendMessage(%2) ... waiting for reply"). + arg(uniqueId()). + arg(message.event()).toLatin1()); + t2.start(); + first_time = false; + } + } + + waitForSignal(this, SIGNAL(replyReceived()), 500); + + if (!safeThis) { + if (safeDebugOn) { + qDebug() << ( QString("%1 QstProtocol::sendMessage(%2) ... object deleted unexpectedly"). + arg(safeUniqueId). + arg(message.event()).toLatin1()); + } + reply[QLatin1String("status")] = "ERROR: Connection was terminated unexpectedly. This may be caused by an application crash."; + reply[QLatin1String("_q_inResponseTo")] = QString("%1\n%2").arg(message.event()).arg(message.toString()); + return false; + } else { + if (send_msg_replies.count() > 0) { + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::sendMessage(%2) ... check replies"). + arg(uniqueId()). + arg(message.event()).toLatin1()); + } + for (int i=0; i<send_msg_replies.size(); i++) { + QstMessage * possible_reply = send_msg_replies.at(i); + if (possible_reply && possible_reply->m_msg_id == msg.m_msg_id) { + reply = *possible_reply; + delete send_msg_replies.takeAt( i ); + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::sendMessage(%2) ... reply received"). + arg(uniqueId()). + arg(message.event()).toLatin1()); + } + + onReplyReceived(&reply); + return true; + } + } + } + } + } + if (state() != ConnectedState) { + reply[QLatin1String("status")] = "ERROR: Connection lost. This is likely caused by a crash in the Application Under Test."; + reply[QLatin1String("_q_inResponseTo")] = QString("%1\n%2").arg(message.event()).arg(message.toString()); + } else { + qDebug() << "ERROR-REPLY-TIMEOUT: " << t1.elapsed() << t2.elapsed(); + reply[QLatin1String("status")] = QLatin1String("ERROR_REPLY_TIMEOUT"); + reply[QLatin1String("_q_inResponseTo")] = QString("%1\n%2").arg(message.event()).arg(message.toString()); + } + reply[QLatin1String("location")] = QString("%1:%2").arg(__FILE__).arg(__LINE__); + } else { + reply[QLatin1String("status")] = QLatin1String("ERROR_NO_CONNECTION"); + reply[QLatin1String("_q_inResponseTo")] = QString("%1\n%2").arg(message.event()).arg(message.toString()); + reply[QLatin1String("location")] = QString("%1:%2").arg(__FILE__).arg(__LINE__); + } + + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::sendMessage(%2) ... done. Status: %3"). + arg(uniqueId()). + arg(message.event()).arg(reply[QLatin1String("status")].toString()).toLatin1()); + } + + return false; +} + +/*! + Send the string \a result as a reply to \a originalMsg. +*/ + +void QstProtocol::replyMessage( const QstMessage *originalMsg, const QstMessage &message ) +{ + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::replyMessage(%2)"). + arg(uniqueId()). + arg(originalMsg->event()).toLatin1()); + } + + QstMessage msg(message); + msg.m_msg_id = originalMsg->msgId(); + msg.m_event = QLatin1String("@REPLY@"); + if (originalMsg->state() == QstMessage::MessageOldVersion) { + msg["status"] = QLatin1String( + "\n**********************************************" + "\nThe version of qtuitestrunner you are using is" + "\nincompatible with this version of QtUiTest!" + "\n**********************************************\n"); + } + send( msg ); +} + +bool QstProtocol::lastDataReceived() +{ + return last_data_received; +} + +QString QstProtocol::errorStr() +{ + QString S = QLatin1String("Connection error: "); + switch (error()) { + case ConnectionRefusedError: S += QString("Connection attempt to %1:%2 failed").arg(host).arg(port).toLatin1(); break; + case HostNotFoundError: S += QString("Host %1:%2 not found").arg(host).arg(port).toLatin1(); break; + case RemoteHostClosedError: S += QLatin1String("RemoteHostClosedError"); break; + case SocketAccessError: S += QLatin1String("SocketAccessError"); break; + case SocketResourceError: S += QLatin1String("SocketResourceError"); break; + case SocketTimeoutError: S += QLatin1String("SocketTimeoutError"); break; + case DatagramTooLargeError: S += QLatin1String("DatagramTooLargeError"); break; + case NetworkError: S += QLatin1String("NetworkError"); break; + case AddressInUseError: S += QLatin1String("AddressInUseError"); break; + case SocketAddressNotAvailableError: S += QLatin1String("SocketAddressNotAvailableError"); break; + case UnsupportedSocketOperationError: S += QLatin1String("UnsupportedSocketOperationError"); break; + case UnknownSocketError: S += QLatin1String("UnknownSocketError"); break; + default: S += QLatin1String("Unknown error"); + } + + return S; +} + +QString QstProtocol::stateStr() +{ + switch (state()) { + case QAbstractSocket::UnconnectedState: return QLatin1String("UnconnectedState"); + case QAbstractSocket::HostLookupState: return QLatin1String("HostLookupState"); + case QAbstractSocket::ConnectingState: return QLatin1String("ConnectingState"); + case QAbstractSocket::ConnectedState: return QLatin1String("ConnectedState"); + case QAbstractSocket::BoundState: return QLatin1String("BoundState"); + case QAbstractSocket::ClosingState: return QLatin1String("ClosingState"); + case QAbstractSocket::ListeningState: return QLatin1String("ListeningState"); + } + return QLatin1String("Unknown state"); +} + +void QstProtocol::onConnectionFailed( const QString &reason ) +{ + emit connectionFailed( this, reason ); +} + +void QstProtocol::testConnection() +{ + if (debug_on) { + qDebug() << QString("%1 QstProtocol::testConnection()").arg(uniqueId()).toLatin1(); + } + + while (send_msg_replies.count() > 0) + delete send_msg_replies.takeFirst(); + + postMessage( QstMessage(QLatin1String("QTEST_NEW_CONNECTION")) ); +} + +void QstProtocol::send( const QstMessage &message ) +{ + QByteArray data; + + if (!message.isUnpacked()) { + data = message.m_buffer; + } else if (!message.m_map.isEmpty()) { + QDataStream s(&data, QIODevice::WriteOnly); + s.setVersion(QDataStream::Qt_4_6); + s << message.m_map; + } + + QDataStream tmp(this); + tmp.setVersion(QDataStream::Qt_4_6); + sendPreamble(&tmp, message); + + // phase 2 + quint32 len = data.count(); + tmp << len; + if (len > 0) { + // phase 3 + tmp.writeRawData( data.data(), (int)len ); + } + + // phase 4 + tmp << TEST_MSG_END; + + flush(); // Force socket to send data now +} + +void QstProtocol::sendPreamble( QDataStream *ds, const QstMessage &message) +{ + // phase 0 + *ds << TEST_MSG_SIGNATURE; + *ds << static_cast<quint8>(message.state()); + *ds << message.msgId(); + + // phase 1 + QString event; + if (message.context().isEmpty()) { + event = message.event(); + } else { + event = message.event() + QChar(':') + message.context(); + } + + quint32 len = (event.length() *2) + 4; + *ds << len; + *ds << event; +} + +bool QstProtocol::receive( QstMessage *msg, bool &syncError ) +{ + syncError = false; + + QDataStream stream(this); + stream.setVersion(QDataStream::Qt_4_6); + + quint8 msgState; + if (msg->m_phase == uint(0)) { + msg->m_len = 0; + quint32 sig; + if (bytesAvailable() >= sizeof( sig ) + sizeof( msgState ) + sizeof( msg->m_msg_id ) + sizeof( msg->m_len )) { + stream >> sig; + if (sig != TEST_MSG_SIGNATURE) { + qWarning() << QString("QstMessage::receive(), Invalid start signature (0x%1)").arg(sig,8,16).toLatin1(); + syncError = true; + return false; + } else { + stream >> msgState; + msg->m_state = static_cast<QstMessage::MessageState>(msgState); + stream >> msg->m_msg_id; + stream >> msg->m_len; + msg->m_phase++; + } + } + } + + if (msg->m_phase == uint(1)) { + if (bytesAvailable() >= msg->m_len) { + QString event; + stream >> event; + int i = event.indexOf(QLatin1Char(':')); + if (i == -1) { + msg->m_event = event; + } else { + msg->m_event = event.left(i); + msg->m_context = event.mid(i+1); + } + msg->m_phase++; + } + } + + if (msg->m_phase == uint(2)) { + if (bytesAvailable() >= sizeof( msg->m_len )) { + stream >> msg->m_len; + msg->m_phase++; + } + } + + if (msg->m_phase == uint(3)) { + if (msg->m_len > 0) { + QByteArray buf; + quint32 len = msg->m_len; + uint bytes_available = bytesAvailable(); + if (bytes_available < len) + len = bytes_available; + buf.resize( len ); + stream.readRawData( buf.data(), len ); + msg->m_buffer.append(buf); + msg->m_len -= len; + + if (msg->m_len == 0) { + // received OK + msg->m_phase++; + } else { + // waiting for more data + return false; + } + + } else { + msg->m_phase++; + } + } + + if (msg->m_phase == uint(4)) { + quint32 id2; + if (bytesAvailable() >= sizeof( id2 )) { + stream >> id2; + msg->m_phase = 0; + if (id2 != TEST_MSG_END) { + qWarning() << QString("QstMessage::receive(), Invalid end signature (0x%2)").arg(id2,8,16).toLatin1(); + syncError = true; + return false; + } else { + return true; + } + } + } + return false; +} + +bool QstProtocol::rxBusy() +{ + return rx_busy; +} + +/*! + Reads the remote control connection and responds to received commands. +*/ + +void QstProtocol::onData() +{ + if (onData_busy) return; + onData_busy = true; + + int sync_error_count = 0; + bool msg_received = true; + while (msg_received && bytesAvailable() > 0) { + msg_received = false; + // set the time to now :-) + rx_timer.start(); + + bool sync_error; + if (cur_message == 0) + cur_message = new QstMessage(); + + if (receive( cur_message, sync_error )) { + + msg_received = true; + QString last_event = cur_message->event(); + + if (m_auto_unpack) { + cur_message->unpack(); + } + + if (debug_on) { + qDebug() << ( QString("%1 QstProtocol::onData(%2) msgid = %3"). + arg(uniqueId()). + arg(last_event). + arg(cur_message->m_msg_id). + toLatin1()); + } + + // We received a full message + if (last_event == QLatin1String("@REPLY@")) { + // add the reply to a list + send_msg_replies.append( cur_message ); + int id = cur_message->m_msg_id; + QstMessage *received_message(cur_message); + // and make sure we create a new one + cur_message = 0; + emit replyReceived( id, received_message ); + } else if (last_event == QLatin1String("QTEST_NEW_CONNECTION")) { + // Acknowledge the other side we can receive data + postMessage( QstMessage(QLatin1String("QTEST_ACK_CONNECTION")) ); + } else if (last_event == QLatin1String("QTEST_ACK_CONNECTION")) { + // we don't assume we have a connection until both sides + // have actually received data from the other side + connection_valid = true; + onConnected(); + connect_timer.stop(); + } else if (last_event == QLatin1String("QTEST_CLOSING_CONNECTION")) { + last_data_received = true; + QTimer::singleShot( 0, this, SLOT(onSocketClosed())); + } else if (last_event == QLatin1String("PONG")) { + // Do nothing + } else if (last_event == QLatin1String("TEST")) { + if (!debug_on) { + // don't show the same information twice + qDebug() << QString("%1 Test message received").arg(uniqueId()).toLatin1(); + } + } else if (last_event == QLatin1String("PING")) { + postMessage( QstMessage(QLatin1String("PONG")) ); + } else { + // add the msg to a list + unhandled_msg.append( cur_message ); + cur_message = 0; + QTimer::singleShot(0, this, SLOT(processMessages())); + } + + delete cur_message; + cur_message = 0; + } else { + // We didn't receive a full message + if (sync_error) { + sync_error_count++; + if (sync_error_count > 10) + return; + // receiving garbage messages - nothing can be done but closing the connection and try again. + delete cur_message; + cur_message = 0; + disconnect(!enable_reconnect); + reconnect(); + } + // else we are waiting on more fragments to arrive + } + } + onData_busy = false; +} + +void QstProtocol::processMessages() +{ + while (!rx_busy && unhandled_msg.count() > 0) { + QstMessage *tmp = unhandled_msg.takeFirst(); + if (tmp) { + rx_busy = true; + processMessage( tmp ); + delete tmp; + rx_busy = false; + } + } +} + +/*! + Signals the instance that the other side has closed the connection. +*/ +void QstProtocol::onSocketClosed() +{ + if (debug_on) { + qDebug() << QString("%1 QstProtocol::onSocketClosed()").arg(uniqueId()).toLatin1(); + } + + // anything that is still in the tx buffer gets lost + abort(); + + close(); + + connection_valid = false; + + // if the close was spontaneous and we want to keep the connection alive, we try to reconnect + if (enable_reconnect) { + if (debug_on) { + qDebug() << + QString("%1 QstProtocol::onSocketClosed() singleshot reconnect in .5 seconds").arg(uniqueId()).toLatin1(); + } + QTimer::singleShot(500,this,SLOT(reconnect())); + } + + // tell the world we are closed + QTimer::singleShot(0, this, SLOT(emitConnectionClosed())); +} + +/*! + Signals the instance that a connection is established with a remote control host. +*/ +void QstProtocol::onSocketConnected() +{ + connect_timer.stop(); + if (debug_on) { + qDebug() << QString("%1 QstProtocol::onSocketConnected()").arg(uniqueId()).toLatin1(); + } + testConnection(); +} + +void QstProtocol::reconnect() +{ + if (!host.isEmpty() && state() != ConnectedState) { + if (debug_on) { + qDebug() << QString("%1 QstProtocol::reconnect(%2)").arg(uniqueId()).arg(stateStr()).toLatin1(); + } + + connect_timer.stop(); + connect_timer.start( CONNECT_TIMEOUT ); + + // if we are trying to connect to the local machine, always use 127.0.0.1 + // (and avoid the need for dns) + QString hostname = QHostInfo::localHostName().toUpper(); + if (hostname == host.toUpper() || hostname.startsWith( host.toUpper() + "." )) + host = QLatin1String("127.0.0.1"); + + close(); + wait(100); + if (state() == ConnectingState) { + // Will just get a warning, retry later + return; + } + connectToHost( host, port ); + } else { + if (host.isEmpty()) { + qWarning( "QstProtocol::reconnect() FAILED, no host specified" ); + enable_reconnect = false; + } + } +} + +void QstProtocol::connectTimeout() +{ + if (debug_on) { + qDebug() << QString("%1 QstProtocol::connectTimeout()").arg(uniqueId()).toLatin1(); + } + + connect_timer.stop(); + if (enable_reconnect) { + reconnect(); + } else { + onConnectionFailed( errorStr() ); + } +} + +void QstProtocol::emitConnectionClosed() +{ + if (debug_on) { + qDebug() << QString("%1 QstProtocol::emitConnectionClosed()").arg(uniqueId()).toLatin1(); + } + + // force sendMessage to quit + emit replyReceived(); + emit connectionClosed( this ); +} + + +QString QstProtocol::uniqueId() const +{ + return QString("%1 %2").arg(unique_id).arg(qApp->applicationName()); +} + +void QstProtocol::enableDebug( bool debugOn ) +{ + debug_on = debugOn; + qDebug() << QString("Debugging is switched %1 for Test Protocol %2").arg(debugOn ? "ON" : "OFF").arg(uniqueId()).toLatin1() ; +} + +void QstProtocol::disableDebug() +{ + debug_on = false; + qDebug() << QString("Debugging is switched %1 for Test Protocol %2").arg(debug_on ? "ON" : "OFF").arg(uniqueId()).toLatin1() ; +} diff --git a/src/protocol/qstprotocol.h b/src/protocol/qstprotocol.h new file mode 100644 index 0000000..502c114 --- /dev/null +++ b/src/protocol/qstprotocol.h @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTESTPROTOCOL_P_H +#define QTESTPROTOCOL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtUiTest API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QTimer> +#include <QTime> +#include <QObject> +#include <QString> +#include <QFile> +#include <QVariant> +#include <QMap> +#include <QtNetwork/QTcpSocket> +#include <QtNetwork/QTcpServer> + +#include "qstglobal.h" + +#define REMOTE_CONNECT_ERROR 99 + +#define MESSAGE_ERROR(message, str) (\ + message.setState(QstMessage::MessageError),\ + message["status"] = str,\ + message) + +class QstMessage +{ +public: + enum MessageState { + MessageEmpty = 0, + MessageSuccess = 1, + MessageError = 2, + MessageOldVersion = 3 + }; + + QstMessage(const QString &event = QString(), QVariantMap const &map = QVariantMap() ); + QstMessage(const QstMessage &other); + virtual ~QstMessage(); + + QstMessage& operator=(const QstMessage &other); + + QString event() const; + void setEvent(const QString &event); + quint16 msgId() const; + + const QVariant operator[](const QString &key) const; + QVariant &operator[](const QString &key); + bool contains(const QString &key) const; + QList<QString> keys() const; + + QString toString() const; + QVariantMap toMap() const; + + bool isNull() const; + bool isUnpacked() const; + void unpack() const; + MessageState state() const { return m_state; } + void setState(MessageState state) { m_state = state; } + + QString context() const { return m_context; } + void setContext(const QString &context) { m_context = context; } + +protected: + uint m_phase; + quint32 m_len; + + quint16 m_msg_id; + QString m_event; + QString m_context; + MessageState m_state; + + mutable QVariantMap m_map; + mutable QByteArray m_buffer; + + friend class QstProtocol; +}; +Q_DECLARE_METATYPE( QstMessage ) +Q_DECLARE_METATYPE( QstMessage* ) +Q_DECLARE_METATYPE( const QstMessage* ) + +class QstProtocol : public QTcpSocket +{ + Q_OBJECT + +public: + QstProtocol(QObject *parent = 0); + virtual ~QstProtocol(); + + virtual void setSocket( int socket ); + + void enableReconnect( bool enable, uint reconnectInterval = 5000 ); + + void connect( const QString& hostname, int port ); + void disconnect( bool disableReconnect = true ); + bool isConnected(); + virtual bool waitForConnected( int timeout = 10000 ); + + virtual uint postMessage( const QstMessage &message ); + + virtual bool sendMessage( const QstMessage &message, QstMessage &reply, int timeout ); + virtual void replyMessage( const QstMessage *originalMsg, const QstMessage &message ); + + bool lastDataReceived(); + bool rxBusy(); + virtual void onReplyReceived( QstMessage *reply ); + + QString errorStr(); + QString stateStr(); + + virtual void onConnectionFailed( const QString &reason ); + virtual void onConnected() {}; // re-implement in derived class + + QString uniqueId() const; + void enableDebug( bool debugOn ); + void setAutoUnpack( bool autoUnpack ) { m_auto_unpack = autoUnpack; } + +public slots: + void reconnect(); + void disableDebug(); + +protected: + virtual void processMessage( QstMessage *msg ) = 0; + + void send( const QstMessage &message ); + void sendPreamble( QDataStream *ds, const QstMessage &message ); + bool receive( QstMessage *msg, bool &syncError ); + +signals: + void connectionClosed( QstProtocol *socket ); + void connectionFailed( QstProtocol *socket, const QString &reason ); + void replyReceived(int id = -1, const QstMessage *message = 0); + void replyConfirmed(); + +protected slots: + void onData(); + void onSocketConnected(); + void onSocketClosed(); + void connectTimeout(); + void emitConnectionClosed(); + void processMessages(); + void testConnection(); + +private: + quint16 tx_msg_id; + QString host; + int port; + bool onData_busy; + bool enable_reconnect; + uint reconnect_interval; + QTimer connect_timer; + QTime rx_timer; + bool last_data_received; + bool rx_busy; + bool connection_valid; + + QList<QstMessage*> send_msg_replies; + QList<QstMessage*> unhandled_msg; + QstMessage *cur_message; + + QString last_send_cmd; + QString unique_id; + bool debug_on; + bool m_auto_unpack; +}; + +#endif diff --git a/src/remote/daemon/appmanager.cpp b/src/remote/daemon/appmanager.cpp new file mode 100644 index 0000000..46b23fd --- /dev/null +++ b/src/remote/daemon/appmanager.cpp @@ -0,0 +1,429 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "appmanager.h" +#include "qtuitestmaster_p.h" +#include "qtuitestdsettings.h" +#include "qtuitest_debug.h" + +#include <qtuitestslave.h> +#include <QLocalServer> +#include <QLocalSocket> + +TestApplication::TestApplication(const QString &appId, AppManager *appManager) + : m_appId(appId) + , m_port(0) + , m_env() + , m_connection(0) + , m_appManager(appManager) + , m_state(NotStarted) +{ +} + +TestApplication::~TestApplication() +{ + m_connection->deleteLater(); +} + +void TestApplication::onConnectionClosed() +{ + if (m_state == Disconnected) + return; + + qLog() << "Connection to application closed" << this << m_state; + if (m_state == ProcessingMessage) { + qLog() << "Still processing message"; + m_state = Disconnected; + return; + } + m_state = Disconnected; + emit finished(); +} + +void TestApplication::onSignalReceived(const QVariantMap &sender, const QString &signal, const QVariantList &args) +{ + QstMessage msg("SIGNAL_RECEIVED"); + msg.setContext(m_appId); + msg["sender"] = sender; + msg["signal"] = signal; + msg["args"] = args; + m_appManager->postMessage( msg ); +} + +bool TestApplication::forwardMessage( QstMessage *msg, QtUiTestSlave *slave ) +{ + qLog() << "TestApplication::forwardMessage" << msg->event() << "to" << m_appId << "on port" << m_port; + + if (m_connection) { + QstMessage reply; + m_state = ProcessingMessage; + m_connection->sendMessage(*msg, reply, 20000); + reply.setContext(m_appId); + slave->replyMessage(msg, reply); + if (m_state == Disconnected) { + qLog() << "Connection closed while processing message"; + emit finished(); + return false; + } + m_state = Connected; + return true; + } + return false; +} + +bool TestApplication::connectToAut(int timeout) +{ + if (!m_connection) { + m_connection = new QtUiTestMaster(); + connect(m_connection, SIGNAL(signalReceived(QVariantMap,QString,QVariantList)), this, SLOT(onSignalReceived(QVariantMap,QString,QVariantList))); + } + + QTime t; + t.start(); + while (t.elapsed() < timeout && !m_connection->isConnected()) { + m_connection->connect( QString("127.0.0.1"), m_port ); + m_connection->waitForConnected(2000); + } + + if (!m_connection->isConnected()) { + qLog() << "Failed to connect to" << m_appId << "on port" << m_port; + qLog() << "Connection state" << m_connection->state(); + if (m_connection->state() == QAbstractSocket::ConnectedState) { + // Connected, but no response! + qLog() << "Connected but did not receive reply"; + m_connection->disconnect(); + emit finished(false); + } else { + emit finished(); + } + return false; + } + qLog() << "Connected to" << m_appId << "on port" << m_port; + m_state = Connected; + + // Don't try to reconnect if connection is lost ... it's pointless + m_connection->enableReconnect(false, 0); + connect(static_cast<QstProtocol*>(m_connection), SIGNAL(connectionClosed(QstProtocol*)), this, SLOT(onConnectionClosed())); + + QstMessage msg("appName"); + QstMessage response; + m_connection->sendMessage( msg, response, 2000 ); + response.unpack(); + m_appName = response["appName"].toString(); + qLog() << "Application name is" << m_appName; + if (!m_appName.isEmpty() && m_appName == QtUiTestDSettings::instance()->homeApp()) { + qLog() << "This is the home application"; + m_appManager->setDefaultApplication(this); + } + + return true; +} + +bool TestApplication::isConnected() const +{ + if (m_connection) { + return m_connection->isConnected(); + } + return false; +} + +void TestApplication::cleanup() +{ + QstMessage msg("cleanup"); + m_connection->postMessage(msg); +} + +AppManager::AppManager() + : m_currentApplication(0) + , m_defaultApplication(0) + , m_server(0) +{ + QLocalServer::removeServer(QString::fromLocal8Bit(QTUITEST_PORT_PATH)); + m_server = new QLocalServer(this); + m_server->listen(QString::fromLocal8Bit(QTUITEST_PORT_PATH)); + connect(m_server, SIGNAL(newConnection()), this, SLOT(onNewConnection())); + + if (int port = QtUiTestDSettings::instance()->prestartPort()) { + qLog() << "Trying to connect to existing application on port" << port; + m_defaultApplication = new TestApplication(QtUiTestDSettings::instance()->prestartApp(), this); + if (!m_defaultApplication || !connectApplication(port, m_defaultApplication)) { + qWarning() << "Failed to connect to existing application on port" << port; + exit(1); + } + } +} + +AppManager::~AppManager() +{ +} + +AppManager* AppManager::instance() { + static AppManager appManager; + return &appManager; +} + +bool AppManager::connectApplication(int port, TestApplication *app, int timeout) +{ + connect(app, SIGNAL(finished(bool)), this, SLOT(onFinished(bool))); + + app->setPort(port); + if (!app->connectToAut(timeout)) + return false; + + m_portMap.insert(port, app); + m_appMap.insert(app->appId(), app); + m_pendingPorts.removeAll(port); + + if (app == m_defaultApplication || QtUiTestDSettings::instance()->homeApp().isEmpty()) { + setApplication(app); + } + + return true; +} + +void AppManager::purgeApplications() +{ + foreach (const QString &appId, m_appMap.keys()) { + m_appMap[appId]->deleteLater(); + } + + m_appMap.clear(); +} + +bool AppManager::forwardMessage( QstMessage *msg, QtUiTestSlave *slave ) +{ + QString appId = msg->context(); + TestApplication *app; + + if (appId.isEmpty()) { + app = m_currentApplication; + } else { + app = m_appMap[appId]; + if (app) { + qLog() << "Forwarding message to application id" << appId; + } else { + qLog() << "Cannot forward to application id" << appId; + } + } + + if (app) { + return app->forwardMessage(msg, slave); + } + return false; +} + +void AppManager::onNewConnection() +{ + qLog() << "New application requesting connection"; + int port = getFreePort(); + m_pendingPorts.append(port); + QString portString = QString::number(port).toLatin1() + QLatin1Char('\n'); + qLog() << "Assigning port:" << port; + QLocalSocket *socket = m_server->nextPendingConnection(); + socket->write(portString.toLatin1()); + socket->disconnect(); + socket->deleteLater(); + + //FIXME what identifier to use? + static int counter=0; + QString application = QString("app_%1:%2").arg(counter++, 5, 10, QLatin1Char('0')).arg(port); + TestApplication *app = new TestApplication(application, this); + if (!connectApplication(port, app)) { + qWarning() << "Failed to connect to application on port" << port; + return; + } + + // Send message to notify test runner of new application + QstMessage msg("APP_STARTED"); + msg.setContext(application); + postMessage( msg ); +} + +void AppManager::onFinished(bool reusePort) +{ + TestApplication *app = qobject_cast<TestApplication*>(sender()); + + if (app) { + qLog() << "Finished" << app->appId(); + + // Send message to notify test runner that app has closed + QstMessage msg("APP_FINISHED"); + msg.setContext(app->appId()); + if (app == m_defaultApplication) { + msg["homeapp"] = QtUiTestDSettings::instance()->homeApp(); + } + postMessage( msg ); + + if (m_defaultApplication && app == m_currentApplication) + setApplication(m_defaultApplication); + + if (reusePort) { + m_portMap.remove(app->port()); + } + + m_appMap.remove(app->appId()); + qLog() << "Apps now: " << m_appMap.keys(); + + app->deleteLater(); + + if (app == m_defaultApplication) { + // The home application has died! + qLog() << "The home application has terminated!"; + m_defaultApplication = 0; + purgeApplications(); + return; + } + + } +} + +int AppManager::getFreePort() const +{ + int port = QtUiTestDSettings::instance()->appPortMin(); + + //Find first unused port in range + foreach (int usedPort, m_portMap.keys()) { + if ((port != usedPort) + && !(m_pendingPorts.contains(port))) { + break; + } + port++; + } + if (m_pendingPorts.contains(port)) { + port++; + } + + if (port > QtUiTestDSettings::instance()->appPortMax()) { + qWarning("Exceeded maximum port number"); + } + + return port; +} + +bool AppManager::isConnected() const +{ + if (m_currentApplication) { + return m_currentApplication->isConnected(); + } + return false; +} + +void AppManager::setDefaultApplication(TestApplication *app) +{ + m_defaultApplication = app; +} + +QString AppManager::currentApplication() const +{ + QString ret; + if (m_currentApplication) { + ret = m_currentApplication->appId(); + } + return ret; +} + +QString AppManager::homeApplication() const +{ + QString ret; + if (m_defaultApplication) { + ret = m_defaultApplication->appId(); + } + return ret; +} + +QStringList AppManager::getApplications(const QString &name) +{ + QStringList result; + foreach (const QString &appId, m_appMap.keys()) { + if (!m_appMap[appId]) + m_appMap.remove(appId); + if (name.isEmpty() || m_appMap[appId]->appName() == name) + result.append(appId); + } + return result; +} + +bool AppManager::setApplication(const QString &appId) +{ + TestApplication *app = m_appMap[appId]; + if (!app) { + return false; + } + + setApplication(app); + return true; +} + +void AppManager::setApplication(TestApplication *app) +{ + qLog() << "Setting current application to" << app << app->appId(); + m_currentApplication = app; +} + +void AppManager::postMessage(const QstMessage &msg) +{ + //FIXME - should inform all runners + foreach (QtUiTestSlave *slave, m_slaves) { + slave->postMessage( msg ); + } +} + +void AppManager::testrunnerConnected(QtUiTestSlave *slave) +{ + if (!m_slaves.contains(slave)) { + m_slaves << slave; + } +} + +void AppManager::testrunnerDisconnected(QtUiTestSlave *slave) +{ + if (m_slaves.contains(slave)) { + m_slaves.removeAll(slave); + } + + if (m_slaves.isEmpty()) { + foreach (QPointer<TestApplication> app, m_appMap.values()) { + if (app) + app->cleanup(); + } + } +} diff --git a/src/remote/daemon/appmanager.h b/src/remote/daemon/appmanager.h new file mode 100644 index 0000000..acbc79f --- /dev/null +++ b/src/remote/daemon/appmanager.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef APPMANAGER_H +#define APPMANAGER_H + +#include <QStringList> +#include <QPointer> +#include <QVariantMap> +#include <QMap> + +class AppManager; +class QtUiTestMaster; +class QLocalServer; +class QstMessage; +class QtUiTestSlave; + +class TestApplication : public QObject +{ + Q_OBJECT + +public: + + enum State { NotStarted=0, Connected=1, ProcessingMessage=2, Disconnected=3 }; + explicit TestApplication( const QString &appId, AppManager *appManager = 0 ); + virtual ~TestApplication(); + bool connectToAut( int timeout ); + + bool forwardMessage( QstMessage *msg, QtUiTestSlave *slave ); + void setPort(int port) { m_port = port; } + int port() const { return m_port; } + QString appId() const { return m_appId; } + QString appName() const { return m_appName; } + bool isConnected() const; + State state() { return m_state; } + void cleanup(); + +private slots: + void onConnectionClosed(); + void onSignalReceived(const QVariantMap &sender, const QString &signal, const QVariantList &args); + +signals: + void finished(bool reusePort=true); + +private: + QString m_appId; + QString m_appName; + int m_port; + QStringList m_env; + QtUiTestMaster *m_connection; + AppManager *m_appManager; + State m_state; +}; + +class AppManager : public QObject +{ + Q_OBJECT + +public: + AppManager(); + virtual ~AppManager(); + + void init(QtUiTestSlave *slave); + bool forwardMessage( QstMessage *msg, QtUiTestSlave *slave ); + bool isConnected() const; + int getFreePort() const; + void setDefaultApplication(TestApplication*); + QString currentApplication() const; + QString homeApplication() const; + QStringList getApplications(const QString & = QString()); + bool setApplication(const QString&); + void purgeApplications(); + + void appStandardOutput( TestApplication *app, QByteArray text ); + void appStandardError( TestApplication *app, QByteArray text ); + void postMessage( const QstMessage &msg ); + void testrunnerConnected( QtUiTestSlave *slave ); + void testrunnerDisconnected( QtUiTestSlave *slave ); + + static AppManager* instance(); + +protected: + bool connectApplication( int port, TestApplication *app, int timeout=30000 ); + void setApplication(TestApplication *app); + +private slots: + void onNewConnection(); + void onFinished(bool reusePort); + +private: + QList<QtUiTestSlave*> m_slaves; + QPointer<TestApplication> m_currentApplication; + + // Default application is the system application, pre-started outside qtuitestd + QPointer<TestApplication> m_defaultApplication; + QMap<int, QPointer<TestApplication> > m_portMap; + QList<int> m_pendingPorts; + QMap<QString, QPointer<TestApplication> > m_appMap; + QLocalServer *m_server; +}; + +#endif diff --git a/src/remote/daemon/daemon.pro b/src/remote/daemon/daemon.pro new file mode 100644 index 0000000..71d8cac --- /dev/null +++ b/src/remote/daemon/daemon.pro @@ -0,0 +1,29 @@ +!include (../remote.pri) + +TEMPLATE = app +TARGET = qstdaemon +DESTDIR = ../../../bin + +QT += network +QT -= gui + +INCLUDEPATH += ../../../include +LIBS += -L../../../lib +LIBS += -lQstProtocol + +HEADERS += \ + appmanager.h \ + qtuitest_debug.h \ + qtuitestdsettings.h \ + qtuitestmaster_p.h \ + qtuitestserver.h \ + qtuitestslave.h + +SOURCES += \ + main.cpp \ + appmanager.cpp \ + qtuitestdsettings.cpp \ + qtuitestmaster.cpp \ + qtuitestserver.cpp \ + qtuitestslave.cpp + diff --git a/src/remote/daemon/main.cpp b/src/remote/daemon/main.cpp new file mode 100644 index 0000000..d783d10 --- /dev/null +++ b/src/remote/daemon/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qtuitestserver.h> +#include <qtuitestdsettings.h> +#include <QCoreApplication> + +bool qtuitest_debug = false; + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + qtuitest_debug = QtUiTestDSettings::instance()->debug(); + qtuitestServer()->startService(); + return app.exec(); +} diff --git a/src/remote/daemon/qtuitest_debug.h b/src/remote/daemon/qtuitest_debug.h new file mode 100644 index 0000000..b7efa21 --- /dev/null +++ b/src/remote/daemon/qtuitest_debug.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QDebug> + +extern bool qtuitest_debug; + +#define qLog() if (!qtuitest_debug); else qDebug() << QString("[%1]").arg(QTime::currentTime().toString(QLatin1String("hh:mm:ss:zzz"))).toLatin1().data() diff --git a/src/remote/daemon/qtuitestd.pro b/src/remote/daemon/qtuitestd.pro new file mode 100644 index 0000000..bee9005 --- /dev/null +++ b/src/remote/daemon/qtuitestd.pro @@ -0,0 +1,51 @@ +!include(../../../global.pri): error(global.pri not found) +!include($$SRCROOT/src/common/common.pri): error(common.pri not found) + +SOURCES += main.cpp \ + qtuitestslave.cpp \ + qtuitestserver.cpp \ + qtuitestmaster.cpp \ + appmanager.cpp \ + qtuitestdsettings.cpp + +HEADERS += qtuitestslave.h \ + appmanager.h \ + qtuitestmaster_p.h \ + qtuitest_debug.h \ + qtuitestdsettings.h + +TEMPLATE=app +VPATH+=$$PWD +INCLUDEPATH+=$$PWD + +DEFINES += QTT_NO_DEBUG_AND_TRACEBACKS +!include(../../common/libs/QttDebug/qttdebug.pri): error(qttdebug.pri not found) + +QT+=network +QT-=gui +TARGET=qtuitestd + +unix { + # install the script to start qtuitestd in the required + # two places avoiding the need for symbolic links + initscripts.path = /etc/init/test + initscripts.files = initscripts/qtuitestd.conf + # TODO: Disabled for now + INSTALLS += initscripts +} + +!symbian { + MOC_DIR=$$OUT_PWD/.moc + OBJECTS_DIR=$$OUT_PWD/.obj + DESTDIR=$$BUILDROOT/bin + target.path=$$QTT_INSTALL_BIN_DIR + INSTALLS+=target +} + +win32 { + CONFIG+=console +} + +mac { + CONFIG-=app_bundle +} diff --git a/src/remote/daemon/qtuitestdsettings.cpp b/src/remote/daemon/qtuitestdsettings.cpp new file mode 100644 index 0000000..27126a2 --- /dev/null +++ b/src/remote/daemon/qtuitestdsettings.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qtuitestdsettings.h> +#include <QCoreApplication> +#include <QStringList> +#include <QDebug> + +#define DEFAULT_PORT 5656 +#define DEFAULT_APPPORTMIN 5658 +#define DEFAULT_APPPORTMAX 5699 + +QtUiTestDSettings::QtUiTestDSettings() : + m_debug(false), + m_port(DEFAULT_PORT), + m_portMax(DEFAULT_PORT), + m_appPortMin(DEFAULT_APPPORTMIN), + m_appPortMax(DEFAULT_APPPORTMAX), + m_prestartPort(0) +{ + const QStringList arguments = QCoreApplication::arguments(); + int args = arguments.size(); + QStringList deviceConfig; + + for (int i=1; i<args; ++i) { + QString arg = arguments.at(i); + if (QString("-help").indexOf(arg) == 0) { + qWarning() << QString( + "%1 - QtUITest daemon\n\n" + " -help : Display this help text and exit\n" + " -debug : Display debugging information\n\n" + " -port port : Specify port to listen on (default: %2)\n" + " -port start,end : Specify port range to listen on\n\n" + " -appport start,end : Specify port range for launched applications (default: %3,%4)\n" + " -homeapp : Specify home application name\n\n" + "The following are optional, but both must be specified to connect to an existing\n" + "application instance (which must have QtUITest plugin loaded) :\n\n" + " -prestartapp : Specify application name of existing application\n" + " -prestartport : Specify port of existing application\n\n" + ).arg(arguments[0]).arg(DEFAULT_PORT).arg(DEFAULT_APPPORTMIN).arg(DEFAULT_APPPORTMAX) + .toLatin1().data(); + exit(0); + } else if (QString("-debug").indexOf(arg) == 0) { + m_debug = true; + } else if (QString("-port").indexOf(arg) == 0) { + if (i == args-1) { + qWarning() << "Must provide port"; + exit(1); + } else { + QString portRange = arguments.at(++i); + int commaPos = portRange.indexOf(QChar(',')); + if (commaPos == -1) { + m_port = portRange.toInt(); + m_portMax = m_port; + } else { + m_port = portRange.left(commaPos).toInt(); + m_portMax = portRange.mid(commaPos+1).toInt(); + } + if (!m_port || !m_portMax) { + qWarning() << "Invalid port specified"; + exit(1); + } + } + } else if (QString("-appport").indexOf(arg) == 0) { + if (i == args-1) { + qWarning() << "Must provide port range"; + exit(1); + } else { + QString appPortRange = arguments.at(++i); + int commaPos = appPortRange.indexOf(QChar(',')); + if (commaPos == -1) { + qWarning() << "Must specify port range start,end"; + exit(1); + } + m_appPortMin = appPortRange.left(commaPos).toInt(); + m_appPortMax = appPortRange.mid(commaPos+1).toInt(); + if (!m_appPortMin || !m_appPortMax) { + qWarning() << "Invalid port specified"; + exit(1); + } + } + } else if (QString("-prestartport").indexOf(arg) == 0) { + if (i == args-1) { + qWarning() << "Must provide port"; + exit(1); + } else { + m_prestartPort = arguments.at(++i).toInt(); + if (!m_prestartPort) { + qWarning() << "Invalid port specified"; + exit(1); + } + } + } else if (QString("-prestartapp").indexOf(arg) == 0) { + if (i == args-1) { + qWarning() << "Must provide prestarted application name"; + exit(1); + } else { + m_prestartApp = arguments.at(++i); + } + } else if (QString("-homeapp").indexOf(arg) == 0) { + if (i == args-1) { + qWarning() << "Must provide home application name"; + exit(1); + } else { + m_homeApp = arguments.at(++i); + } + } else if (QString("-config").indexOf(arg) == 0) { + if (i == args-1) { + qWarning() << "Must provide config value"; + exit(1); + } else { + QString conf = arguments.at(++i); + if (!conf.contains(QLatin1Char('='))) { + qWarning() << "Config argument must be of format key=value"; + exit(1); + } + deviceConfig << conf; + } + } + } + + if ( (m_prestartPort && m_prestartApp.isNull()) || + (!m_prestartPort && !m_prestartApp.isNull()) ) { + qWarning() << "Must specify both prestart port and application name"; + exit(1); + } + + foreach (const QString& conf, deviceConfig) { + int equals = conf.indexOf(QLatin1Char('=')); + QString key = conf.left(equals); + QString value = conf.mid(equals+1); + m_deviceConfig[key] = value; + } +} + +QtUiTestDSettings::~QtUiTestDSettings() +{ +} + +QtUiTestDSettings *QtUiTestDSettings::instance() +{ + static QtUiTestDSettings instance; + return &instance; +}
\ No newline at end of file diff --git a/src/remote/daemon/qtuitestdsettings.h b/src/remote/daemon/qtuitestdsettings.h new file mode 100644 index 0000000..c046c1f --- /dev/null +++ b/src/remote/daemon/qtuitestdsettings.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITESTDSETTINGS_H +#define QTUITESTDSETTINGS_H + +#include <QString> +#include <QVariantMap> + +class QtUiTestDSettings +{ + +public: + QtUiTestDSettings(); + ~QtUiTestDSettings(); + + inline bool debug() const { return m_debug; } + inline int port() const { return m_port; } + inline int portMax() const { return m_portMax; } + inline int appPortMin() const { return m_appPortMin; } + inline int appPortMax() const { return m_appPortMax; } + inline int prestartPort() const { return m_prestartPort; } + inline QString prestartApp() const { return m_prestartApp; } + inline QString homeApp() const { return m_homeApp; } + inline QVariantMap deviceConfig() const { return m_deviceConfig; } + + static QtUiTestDSettings* instance(); + +private: + bool m_debug; + int m_port; + int m_portMax; + int m_appPortMin; + int m_appPortMax; + int m_prestartPort; + QString m_prestartApp; + QString m_homeApp; + QVariantMap m_deviceConfig; +}; + +#endif diff --git a/src/remote/daemon/qtuitestmaster.cpp b/src/remote/daemon/qtuitestmaster.cpp new file mode 100644 index 0000000..fcded65 --- /dev/null +++ b/src/remote/daemon/qtuitestmaster.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qtuitestmaster_p.h" + +#include <QFile> +#include <QDir> +#include <QTextStream> +#include <QIODevice> + +QtUiTestMaster::QtUiTestMaster() + : QstProtocol() +{ + setAutoUnpack(false); +} + +QtUiTestMaster::~QtUiTestMaster() +{ +} + +void QtUiTestMaster::processMessage( QstMessage *msg ) +{ + msg->unpack(); + if (msg->event() == QLatin1String("APP_NAME")) { + m_appName = (*msg)["appName"].toString(); + m_appVersion = (*msg)["appVersion"].toString(); + m_qtVersion = (*msg)["qtVersion"].toString(); + } else if (msg->event() == QLatin1String("SIGNAL_RECEIVED")) { + emit signalReceived( (*msg)["sender"].toMap(), (*msg)["signal"].toString(), (*msg)["args"].toList() ); + } +} + +bool QtUiTestMaster::forwardMessage( const QstMessage &msg ) +{ + QstMessage reply; + // FIXME: This timeout should really be configurable + return sendMessage(msg, reply, 20000); +} + +QString QtUiTestMaster::appName() const +{ + return m_appName; +} + +QString QtUiTestMaster::appVersion() const +{ + return m_appVersion; +} + +QString QtUiTestMaster::qtVersion() const +{ + return m_qtVersion; +} + +void QtUiTestMaster::onReplyReceived( QstMessage *reply ) +{ + // TODO - should emit signal +// emit newMessage(reply); +} diff --git a/src/remote/daemon/qtuitestmaster_p.h b/src/remote/daemon/qtuitestmaster_p.h new file mode 100644 index 0000000..29fb958 --- /dev/null +++ b/src/remote/daemon/qtuitestmaster_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITESTMASTER_P_H +#define QTUITESTMASTER_P_H + +#include <QtSystemTest/QstProtocol> +#include <QObject> +#include <QtSystemTest/qstglobal.h> + +class QtUiTestMaster : public QstProtocol +{ + Q_OBJECT + +public: + QtUiTestMaster(); + virtual ~QtUiTestMaster(); + + QString appName() const; + QString appVersion() const; + QString qtVersion() const; + bool forwardMessage( const QstMessage &msg ); + + virtual void onReplyReceived( QstMessage *reply ); + +signals: + void signalReceived( const QVariantMap &sender, const QString &signal, const QVariantList &args); + +protected: + virtual void processMessage( QstMessage *msg ); + +private: + QString m_appName; + QString m_appVersion; + QString m_qtVersion; +}; + +#endif + diff --git a/src/remote/daemon/qtuitestserver.cpp b/src/remote/daemon/qtuitestserver.cpp new file mode 100644 index 0000000..d6f67c9 --- /dev/null +++ b/src/remote/daemon/qtuitestserver.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qtuitestserver.h" +#include "qtuitest_debug.h" +#include "qtuitestdsettings.h" + +#include <qtuitestslave.h> +#include <QCoreApplication> +#include <QStringList> +#include <QtSystemTest/QstDebug> + +QtUiTestServer::QtUiTestServer(int port) + : QTcpServer(), showDebug(false) +{ + QTT_TRACE_FUNCTION(); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + if (!listen(QHostAddress::AnyIPv4, port)) { +#else + if (!listen(QHostAddress::Any, port)) { +#endif + qWarning() << "QtUiTestServer: couldn't listen for connections on " << port; + exit(-1); + } + qLog() << "QtUiTestServer: listening for connections on" << port; +} + +QtUiTestServer::~QtUiTestServer() +{ + QTT_TRACE_FUNCTION(); + close(); +} + +void QtUiTestServer::incomingConnection(int sd) +{ + QTT_TRACE_FUNCTION(); + qLog() << "New connection to qtuitestrunner on port" << sd; + slave.setSocket(sd); +} + +void QtUiTestServerManager::startService() +{ + QTT_TRACE_FUNCTION(); + qLog() << "QtUiTestServer: Starting service"; + + int port = QtUiTestDSettings::instance()->port(); + int portMax = QtUiTestDSettings::instance()->portMax(); + + for (int i=port; i<=portMax; ++i) { + QtUiTestServer *server = new QtUiTestServer(i); + m_servers << server; + } +} + +void QtUiTestServerManager::stopService() +{ + QTT_TRACE_FUNCTION(); + qLog() << "QtUiTestServer : Stoping service"; + + foreach (QtUiTestServer *server, m_servers) { + delete server; + } +} diff --git a/src/remote/daemon/qtuitestserver.h b/src/remote/daemon/qtuitestserver.h new file mode 100644 index 0000000..a8c7d86 --- /dev/null +++ b/src/remote/daemon/qtuitestserver.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITESTSERVER_H +#define QTUITESTSERVER_H + +#include <QTcpServer> +#include <qtuitestslave.h> + +struct QtUiTestServer : public QTcpServer +{ + QtUiTestServer(int port); + ~QtUiTestServer(); + void incomingConnection(int); + void startService(); + void stopService(); + + QtUiTestSlave slave; + bool showDebug; +}; + +class QtUiTestServerManager +{ +public: + void startService(); + void stopService(); + +private: + QList<QtUiTestServer*> m_servers; +}; + +Q_GLOBAL_STATIC(QtUiTestServerManager, qtuitestServer); + +#endif
\ No newline at end of file diff --git a/src/remote/daemon/qtuitestslave.cpp b/src/remote/daemon/qtuitestslave.cpp new file mode 100644 index 0000000..653b003 --- /dev/null +++ b/src/remote/daemon/qtuitestslave.cpp @@ -0,0 +1,600 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "appmanager.h" +#include "qtuitestslave.h" +#include "qtuitestmaster_p.h" +#include "qtuitest_debug.h" +#include "qtuitestdsettings.h" + +#include <QDir> +#include <QVariant> +#include <QMetaProperty> +#include <QMetaObject> +#include <QMetaType> +#include <QProcess> +#include <QCoreApplication> +#include <QSettings> +#include <QPointer> + +class QtUiTestSlavePrivate : public QObject +{ +Q_OBJECT +public: + QtUiTestSlavePrivate(QtUiTestSlave *parent) + : p(parent) + { + AppManager::instance(); + } + + QString recursiveDelete(const QString&) const; + + QtUiTestSlave *p; + AppManager *appManager() + { + return AppManager::instance(); + } + +public slots: + + QstMessage currentApplication (const QstMessage&); + QstMessage homeApplication (const QstMessage&); + QstMessage setApplication (const QstMessage&); + QstMessage isValidApplication (const QstMessage&); + QstMessage getApplications (const QstMessage&); + + QstMessage runProcess (const QstMessage&); + QstMessage getSetting (const QstMessage&); + QstMessage setSetting (const QstMessage&); + QstMessage putFile (const QstMessage&); + QstMessage getFile (const QstMessage&); + QstMessage deletePath (const QstMessage&); + QstMessage getDirectoryEntries(const QstMessage&); + QstMessage checkOS (const QstMessage&); + QstMessage deviceConfig (const QstMessage&); + QstMessage systemTime (const QstMessage&); +}; + +#include "qtuitestslave.moc" + +QtUiTestSlave::QtUiTestSlave() + : QstProtocol() + , d(new QtUiTestSlavePrivate(this)) +{ + setAutoUnpack(false); + QObject::connect(static_cast<QstProtocol*>(this), SIGNAL(connectionClosed(QstProtocol*)), this, SLOT(onConnectionClosed())); +} + +QtUiTestSlave::~QtUiTestSlave() +{ + delete d; + disconnect(); +} + +void QtUiTestSlave::onConnected() +{ + QstProtocol::onConnected(); + QstMessage msg("AUT_CONNECT"); + msg["qtVersion"] = QT_VERSION_STR; + msg["autVersion"] = QTUITEST_VERSION_STR; + msg["autTime"] = QTime::currentTime(); + d->appManager()->testrunnerConnected(this); + postMessage( msg ); +} + +void QtUiTestSlave::onConnectionClosed() +{ + qLog() << "Connection to qtuitestrunner has closed"; + d->appManager()->testrunnerDisconnected(this); +} + +QstMessage QtUiTestSlavePrivate::currentApplication(const QstMessage &message) +{ + Q_UNUSED(message); + QstMessage reply; + + reply[QLatin1String("currentApplication")] = appManager()->currentApplication(); + return reply; +} + +QstMessage QtUiTestSlavePrivate::homeApplication(const QstMessage &message) +{ + Q_UNUSED(message); + QstMessage reply; + + reply[QLatin1String("homeApplication")] = appManager()->homeApplication(); + return reply; +} + +QstMessage QtUiTestSlavePrivate::setApplication(const QstMessage &message) +{ + QstMessage reply; + QString appId = message.context(); + + if (appId.isEmpty()) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + } + + bool ok = appManager()->setApplication(appId); + if (!ok) { + return MESSAGE_ERROR(reply, QLatin1String("Unable to set application")); + } + return reply; +} + +QstMessage QtUiTestSlavePrivate::isValidApplication(const QstMessage &message) +{ + QstMessage reply; + QString appId = message.context(); + + if (appId.isEmpty()) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + } + + bool ok = appManager()->getApplications().contains(appId); + reply[QLatin1String("isValidApplication")] = ok; + return reply; +} + +QstMessage QtUiTestSlavePrivate::getApplications(const QstMessage &message) +{ + Q_UNUSED(message); + QstMessage reply; + QString appName = message["name"].toString(); + + reply[QLatin1String("getApplications")] = appManager()->getApplications(appName); + return reply; +} + +QstMessage QtUiTestSlavePrivate::runProcess(const QstMessage &message) +{ + QstMessage reply; + + QVariantMap cmd = message["cmd"].toMap(); + if (cmd.isEmpty()) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + } + + QString program = cmd["program"].toString(); + QStringList arguments = cmd["arguments"].toStringList(); + int timeout = cmd["timeout"].toInt(); + QString directory = cmd["directory"].toString(); + QVariantMap environment = cmd["environment"].toMap(); + QVariantMap appendEnvironment = cmd["appendEnvironment"].toMap(); + bool detached = cmd["detached"].toBool(); + + QProcessEnvironment env; + if (!environment.isEmpty()) { + foreach (const QString &key, environment.keys()) { + env.insert(key, environment[key].toString()); + } + } + if (!appendEnvironment.isEmpty()) { + if (env.isEmpty()) { + env = QProcessEnvironment::systemEnvironment(); + } + foreach (const QString &key, appendEnvironment.keys()) { + env.insert(key, appendEnvironment[key].toString()); + } + } + + bool ok = true; + QString status; + + if (detached) { + // Run command in background + qint64 pid = 0; + if (QProcess::startDetached(program, arguments, directory, &pid)) { + status = QLatin1String("Started"); + reply["pid"] = pid; + } else { + status = QLatin1String("FailedToStart"); + ok = false; + } + } else { + // Run command and wait for completion + QString stdout; + QString stderr; + int exitCode = 0; + QProcess *process = new QProcess(this); + + if (!env.isEmpty()) { + process->setProcessEnvironment(env); + } + if (!directory.isEmpty()) { + process->setWorkingDirectory(directory); + } + + process->start(program, arguments); + while (process->state() == QProcess::Starting) { + QCoreApplication::processEvents(); + } + + if (process->error() == QProcess::FailedToStart) { + status = QLatin1String("FailedToStart"); + ok = false; + } else { + QTime t; + t.start(); + while (process->state() == QProcess::Running && t.elapsed() < timeout) { + QCoreApplication::processEvents(); + } + + stdout += process->readAllStandardOutput(); + stderr += process->readAllStandardError(); + if (process->state() == QProcess::Running) { + status = QLatin1String("TimedOut"); + } else if (process->exitStatus() != QProcess::NormalExit) { + status = QLatin1String("Crashed"); + ok = false; + } else { + status = QLatin1String("Finished"); + } + } + + exitCode = process->exitCode(); + delete process; + + reply["stdout"] = stdout; + reply["stderr"] = stderr; + reply["exitCode"] = exitCode; + } + qLog() << "Command status:" << status; + reply["cmdStatus"] = status; + + if (!ok) { + return MESSAGE_ERROR(reply, QString("Error: Command failed to run (%1)").arg(status)); + } + return reply; +} + +QstMessage QtUiTestSlavePrivate::getSetting(const QstMessage &message) +{ + QstMessage reply; + QString org = message[QLatin1String("org")].toString(); + QString app = message[QLatin1String("app")].toString(); + QString path = message[QLatin1String("path")].toString(); + QString group = message[QLatin1String("group")].toString(); + QString key = message[QLatin1String("key")].toString(); + path = p->processEnvironment(path); + if (group.isEmpty() || key.isEmpty()) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + } + if (!path.isEmpty() && (!org.isEmpty() || !app.isEmpty())) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_BAD_PARAMETERS")); + } else if (path.isEmpty() && org.isEmpty()) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + } + + QSettings *settings = 0; + if (!path.isEmpty()) settings = new QSettings(path, QSettings::NativeFormat); + else settings = new QSettings(org, app); + + settings->beginGroup(group); + reply[QLatin1String("getSetting")] = settings->value(key); + delete settings; + + return reply; +} + +QstMessage QtUiTestSlavePrivate::setSetting(const QstMessage &message) +{ + QstMessage reply; + QString org = message[QLatin1String("org")].toString(); + QString app = message[QLatin1String("app")].toString(); + QString path = message[QLatin1String("path")].toString(); + QString group = message[QLatin1String("group")].toString(); + QString key = message[QLatin1String("key")].toString(); + path = p->processEnvironment(path); + if (key.isEmpty()) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + } + if (!path.isEmpty() && (!org.isEmpty() || !app.isEmpty())) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_BAD_PARAMETERS")); + } else if (path.isEmpty() && org.isEmpty()) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + } + + QSettings *settings = 0; + if (!path.isEmpty()) settings = new QSettings(path, QSettings::NativeFormat); + else settings = new QSettings(org, app); + + if (!group.isEmpty()) + settings->beginGroup(group); + settings->setValue(key, message[QLatin1String("value")]); + delete settings; + + return reply; +} + +QstMessage QtUiTestSlavePrivate::putFile(const QstMessage &message) +{ + QstMessage reply; + QString path = message[QLatin1String("path")].toString(); + path = p->processEnvironment(path); + QByteArray data = message[QLatin1String("data")].toByteArray(); + + if (path.isEmpty()) + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + + { + QFileInfo info = QFileInfo(path); + QDir dir = info.dir(); + if (info.exists()) { + dir.remove(info.fileName()); + } else if (!dir.exists() && !QDir(QLatin1String("/")).mkpath(dir.absolutePath())) { + return MESSAGE_ERROR(reply, QLatin1String("Could not create path '") + dir.absolutePath() + QLatin1String("'")); + } + } + + QFile f(path); + if (f.open(QIODevice::WriteOnly)) { + if (message[QLatin1String("permissions")].isValid() && !f.setPermissions(static_cast<QFile::Permissions>(message[QLatin1String("permissions")].toInt()))) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_FILE_PERMISSIONS")); + } + QDataStream ds(&f); + if (data.constData()) { + quint64 bytesWritten = ds.writeRawData(data.constData(), data.size()); + if ((qint64)bytesWritten == data.size()) + return reply; + else { + reply[QLatin1String("warning")] = QString("Wrote %1 byte(s), expected %2").arg(bytesWritten).arg(data.size()); + return MESSAGE_ERROR(reply, QLatin1String("ERROR_TRUNCATED")); + } + } + // It's OK for data to be empty, then we create an empty file. + return reply; + } + + return MESSAGE_ERROR(reply, QLatin1String("ERROR_FILE_OPEN")); +} + +QstMessage QtUiTestSlavePrivate::getFile(const QstMessage &message) +{ + QstMessage reply; + QString path = message[QLatin1String("path")].toString(); + path = p->processEnvironment(path); + + if (path.isEmpty()) + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + + QFile f(path); + if (!f.exists()) return MESSAGE_ERROR(reply, QLatin1String("ERROR_FILE_NOT_EXIST")); + if (f.open(QIODevice::ReadOnly)) { + QByteArray data; + QDataStream ds(&f); + data.resize(f.size()); + quint64 bytesRead = ds.readRawData(data.data(), f.size()); + reply[QLatin1String("getFile")] = data; + if ((qint64)bytesRead == f.size()) + return reply; + else { + reply[QLatin1String("warning")] = QString("Read %1 byte(s), expected %2").arg(bytesRead).arg(data.size()); + return MESSAGE_ERROR(reply, QLatin1String("ERROR_TRUNCATED")); + } + } + return MESSAGE_ERROR(reply, QLatin1String("ERROR_FILE_OPEN")); +} + +QstMessage QtUiTestSlavePrivate::getDirectoryEntries(const QstMessage &message) +{ + QstMessage reply; + QString path = message[QLatin1String("path")].toString(); + path = p->processEnvironment(path); + + if (path.isEmpty()) { + return MESSAGE_ERROR(reply, QLatin1String("ERROR_MISSING_PARAMETERS")); + } + + QDir d(path); + if (!d.exists()) { + reply[QLatin1String("getDirectoryEntries")] = QStringList(); + return reply; + } + + QDir::Filters filters; + { + int filters_int = message[QLatin1String("filters")].toInt(); + filters = QFlag(filters_int); + } + + QStringList list = d.entryList(filters); + reply[QLatin1String("getDirectoryEntries")] = list; + return reply; +} + +QstMessage QtUiTestSlavePrivate::deletePath(const QstMessage &message) +{ + QstMessage reply; + QString path = message[QLatin1String("path")].toString(); + path = p->processEnvironment(path); + QString deleteResult = recursiveDelete(path); + if (deleteResult != QLatin1String("OK")) { + return MESSAGE_ERROR(reply, deleteResult); + } + return reply; +} + +void QtUiTestSlave::processMessage( QstMessage *msg ) +{ + qLog() << "QtUiTestSlave::processMessage" << msg->event(); + + QstMessage reply; + QString methodSignature = msg->event() + QLatin1String("(QstMessage)"); + + if (d->metaObject()->indexOfMethod(methodSignature.toLatin1().constData()) == -1) { + if (!d->appManager()->isConnected()) { + (void)MESSAGE_ERROR(reply, QLatin1String("ERROR: Not connected to test application")); + } else if (!d->appManager()->forwardMessage(msg, this)) { + (void)MESSAGE_ERROR(reply, QLatin1String("ERROR: Could not forward message '") + msg->event() + QLatin1String("'")); + } + + } else { + msg->unpack(); + if (!QMetaObject::invokeMethod(d, msg->event().toLatin1().constData(), Qt::DirectConnection, + Q_RETURN_ARG(QstMessage, reply), + Q_ARG(QstMessage, *msg))) { + (void)MESSAGE_ERROR(reply, QLatin1String("ERROR: Failed to invoke method '") + msg->event() + QLatin1String("'")); + } + if (reply.state() != QstMessage::MessageError) { + reply.setState(QstMessage::MessageSuccess); + } + } + + replyMessage(msg, reply); +} + +QString QtUiTestSlave::processEnvironment( const QString& in ) const +{ + struct SystemEnvironment { + static QMap<QString,QString> get() { + QMap<QString,QString> ret; + QStringList env = QProcess::systemEnvironment(); + foreach (const QString &str, env) { + if (str.contains(QLatin1Char('='))) { + ret[str.left(str.indexOf(QLatin1Char('='))).toUpper()] = str.mid(str.indexOf(QLatin1Char('=')) + 1); + } + } + return ret; + } + }; + static const QMap<QString,QString> environment( SystemEnvironment::get() ); + + QString out; + static QRegExp re("\\$[{(]?([A-Za-z0-9_]+)[})]?"); + int offset = 0; + while (true) { + int index = re.indexIn(in, offset); + if (-1 == index) { + out += in.mid(offset); + break; + } + out += in.mid(offset, index - offset); + out += environment.value(re.cap(1).toUpper()); + offset += re.matchedLength(); + } + + return out; +} + +QString QtUiTestSlavePrivate::recursiveDelete( const QString &path ) const +{ + if (path.isEmpty()) return QLatin1String("ERROR_CANT_DELETE_EMPTY_PATH"); + + QFileInfo i(path); + if (!i.exists()) return QLatin1String("OK"); + if (!i.isDir() || i.isSymLink()) { + if (!i.dir().remove(i.fileName())) { + return QLatin1String("ERROR_CANT_DELETE_FILE_") + path; + } else { + return QLatin1String("OK"); + } + } + + QDir dir(path); + + QStringList children = dir.entryList( QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot ); + + QString res; + foreach (QString child, children) { + res = recursiveDelete( dir.absolutePath() + QLatin1String("/") + child ); + if (res != QLatin1String("OK") ) return res; + } + + QString dirName = dir.dirName(); + dir.cdUp(); + + if (!dir.rmdir(dirName)) { + return QLatin1String("ERROR_CANT_DELETE_DIRECTORY_") + path; + } + return QLatin1String("OK"); +} + +QstMessage QtUiTestSlavePrivate::checkOS( const QstMessage &message ) +{ + QstMessage reply; + QString os = message[QLatin1String("os")].toString().toUpper(); + + bool result = false; + +#ifdef Q_OS_UNIX + if (os == QLatin1String("UNIX")) result = true; +#endif +#ifdef Q_OS_LINUX + if (os == QLatin1String("LINUX")) result = true; +#endif +#ifdef Q_OS_MAEMO + if (os == QLatin1String("MAEMO")) result = true; +#endif +#ifdef Q_OS_MAC + if (os == QLatin1String("MAC")) result = true; +#endif +#ifdef Q_OS_WIN32 + if (os == QLatin1String("WIN32")) result = true; +#endif +#ifdef Q_OS_WINCE + if (os == QLatin1String("WINCE")) result = true; +#endif +#ifdef Q_OS_SYMBIAN + if (os == QLatin1String("SYMBIAN")) result = true; +#endif + + reply[QLatin1String("checkOS")] = result; + return reply; +} + +QstMessage QtUiTestSlavePrivate::deviceConfig( const QstMessage &message ) +{ + Q_UNUSED(message); + QstMessage reply; + reply[QLatin1String("deviceConfig")] = QtUiTestDSettings::instance()->deviceConfig(); + return reply; +} + +QstMessage QtUiTestSlavePrivate::systemTime(const QstMessage &message) +{ + Q_UNUSED(message); + QstMessage reply; + + reply["systemTime"] = QDateTime::currentDateTime().toString(Qt::ISODate); + return reply; +} diff --git a/src/remote/daemon/qtuitestslave.h b/src/remote/daemon/qtuitestslave.h new file mode 100644 index 0000000..dbd81aa --- /dev/null +++ b/src/remote/daemon/qtuitestslave.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITESTSLAVE_H +#define QTUITESTSLAVE_H + +#include <QtSystemTest/QstProtocol> + +class QtUiTestSlavePrivate; + +class QtUiTestSlave : public QstProtocol +{ + Q_OBJECT + +public: + QtUiTestSlave(); + virtual ~QtUiTestSlave(); + virtual void processMessage(QstMessage*); + +public slots: + virtual void onConnected(); + virtual void onConnectionClosed(); + +protected: + QString processEnvironment(const QString&) const; + +private: + friend class QtUiTestSlavePrivate; + QtUiTestSlavePrivate *d; +}; + +#endif diff --git a/src/remote/remote.pri b/src/remote/remote.pri new file mode 100644 index 0000000..bbdfb74 --- /dev/null +++ b/src/remote/remote.pri @@ -0,0 +1,15 @@ +!contains(DEFINES, DEFAULT_AUT_PORT) { + DEFINES += DEFAULT_AUT_PORT=6565 +} + +!contains(DEFINES, DEFAULT_AUTSSH_PORT) { + DEFINES += DEFAULT_AUT_AUTPORT=22 +} + +!contains(DEFINES, DEFAULT_AUT_HOST) { + DEFINES += DEFAULT_AUT_HOST="127.0.0.1" +} + +!contains(DEFINES, QTUITEST_PORT_PATH) { + DEFINES += 'QTUITEST_PORT_PATH=\\"/tmp/qtuitest_port\\"' +} diff --git a/src/remote/remote.pro b/src/remote/remote.pro new file mode 100644 index 0000000..317a146 --- /dev/null +++ b/src/remote/remote.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = daemon slave diff --git a/src/remote/slave/lib/lib.pro b/src/remote/slave/lib/lib.pro new file mode 100644 index 0000000..ca73a91 --- /dev/null +++ b/src/remote/slave/lib/lib.pro @@ -0,0 +1,93 @@ +!include (../../remote.pri) + +TEMPLATE = lib + +TARGET = QstSlave +TARGETPATH = QtSystemTest + +TEMPLATE = lib + +CONFIG += no_clean qt +QT += core network widgets declarative quick + +INCLUDEPATH += ../../../../include +LIBS += -L../../../../lib +LIBS += -lQstProtocol + +contains(QT_MAJOR_VERSION, 5) { + SOURCES += \ + qinputgenerator_qwindow.cpp \ + testquickobject.cpp \ + testquickitem.cpp \ + testquickview.cpp \ + testwindow.cpp + + PUBLIC_HEADERS += \ + testquickobject.h \ + testquickitem.h \ + testquickview.h \ + testwindow.h \ + + HEADERS += \ + qinputgenerator_qwindow_p.h + + QT += qml qml-private quick gui-private core-private widgets +} else { + INCLUDEPATH += $$QT_DECLARATIVE_PRIVATE_HEADERS_DIR +} + +SOURCES += \ + qinputgenerator_generic.cpp \ + testquickfactory.cpp \ + testobject.cpp \ + testwidget.cpp \ + qasciikey.cpp \ + qtuitestconnectionmanager.cpp \ + qtuitestwidgetinterface.cpp \ + qeventwatcher.cpp \ + qtestslave.cpp \ + testapplication.cpp \ + testslaveserver.cpp \ + qtuitestwidgets.cpp \ + qinputgenerator.cpp \ + qtestwidgets.cpp \ + qtuitestnamespace.cpp + +PUBLIC_HEADERS += \ + qtestwidgets.h \ + qtuitestnamespace.h \ + testquickfactory.h \ + testobject.h \ + testwidget.h \ + testapplication.h \ + qtuitestwidgetinterface.h \ + qtestslave.h \ + qtuitestmessagehandler.h \ + testslaveserver.h + +HEADERS = \ + qinputgenerator_p.h \ + qtuitestconnectionmanager_p.h \ + qeventwatcher_p.h \ + qtuitestwidgets_p.h \ + qinputgenerator_generic_p.h \ + $$PUBLIC_HEADERS + +# Installing libs and headers into Qt lib +includes.files = $$PUBLIC_HEADERS +includes.path = $$[QT_INSTALL_HEADERS]/$$TARGETPATH + +target.path = $$[QT_INSTALL_LIBS] + +INSTALLS += includes target + +# Building so that other libs in project can access this lib +DESTDIR = ../../../../lib +INCLUDEDESTDIR = $$OUT_PWD/../../../../include/$$TARGETPATH +includedir.target = dummytarget +includedir.commands = (mkdir -p $$INCLUDEDESTDIR && cd $$PWD && cp $$PUBLIC_HEADERS $$INCLUDEDESTDIR/) + +QMAKE_EXTRA_TARGETS += includedir + +PRE_TARGETDEPS += dummytarget + diff --git a/src/remote/slave/lib/qasciikey.cpp b/src/remote/slave/lib/qasciikey.cpp new file mode 100644 index 0000000..0e682c1 --- /dev/null +++ b/src/remote/slave/lib/qasciikey.cpp @@ -0,0 +1,526 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qtuitestnamespace.h" + +/*! \internal + Convert an ascii char key value to a Qt Key value. + If the key is unknown a 0 is returned. + + Note: this may happen more than you like since not all known + ascii keys _are_ converted already. So feel free to add all the keys you need. + */ +Qt::Key QtUiTest::asciiToKey(char ascii) +{ + switch ((unsigned char)ascii) { + case 0x08: return Qt::Key_Backspace; + case 0x09: return Qt::Key_Tab; + case 0x0b: return Qt::Key_Backtab; + case 0x0d: return Qt::Key_Return; + case 0x1b: return Qt::Key_Escape; + case 0x13: return Qt::Key_Up; + case 0x15: return Qt::Key_Down; + case 0x20: return Qt::Key_Space; + case 0x21: return Qt::Key_Exclam; + case 0x22: return Qt::Key_QuoteDbl; + case 0x23: return Qt::Key_NumberSign; + case 0x24: return Qt::Key_Dollar; + case 0x25: return Qt::Key_Percent; + case 0x26: return Qt::Key_Ampersand; + case 0x27: return Qt::Key_Apostrophe; + case 0x28: return Qt::Key_ParenLeft; + case 0x29: return Qt::Key_ParenRight; + case 0x2a: return Qt::Key_Asterisk; + case 0x2b: return Qt::Key_Plus; + case 0x2c: return Qt::Key_Comma; + case 0x2d: return Qt::Key_Minus; + case 0x2e: return Qt::Key_Period; + case 0x2f: return Qt::Key_Slash; + case 0x30: return Qt::Key_0; + case 0x31: return Qt::Key_1; + case 0x32: return Qt::Key_2; + case 0x33: return Qt::Key_3; + case 0x34: return Qt::Key_4; + case 0x35: return Qt::Key_5; + case 0x36: return Qt::Key_6; + case 0x37: return Qt::Key_7; + case 0x38: return Qt::Key_8; + case 0x39: return Qt::Key_9; + case 0x3a: return Qt::Key_Colon; + case 0x3b: return Qt::Key_Semicolon; + case 0x3c: return Qt::Key_Less; + case 0x3d: return Qt::Key_Equal; + case 0x3e: return Qt::Key_Greater; + case 0x3f: return Qt::Key_Question; + case 0x40: return Qt::Key_At; + case 0x41: return Qt::Key_A; + case 0x42: return Qt::Key_B; + case 0x43: return Qt::Key_C; + case 0x44: return Qt::Key_D; + case 0x45: return Qt::Key_E; + case 0x46: return Qt::Key_F; + case 0x47: return Qt::Key_G; + case 0x48: return Qt::Key_H; + case 0x49: return Qt::Key_I; + case 0x4a: return Qt::Key_J; + case 0x4b: return Qt::Key_K; + case 0x4c: return Qt::Key_L; + case 0x4d: return Qt::Key_M; + case 0x4e: return Qt::Key_N; + case 0x4f: return Qt::Key_O; + case 0x50: return Qt::Key_P; + case 0x51: return Qt::Key_Q; + case 0x52: return Qt::Key_R; + case 0x53: return Qt::Key_S; + case 0x54: return Qt::Key_T; + case 0x55: return Qt::Key_U; + case 0x56: return Qt::Key_V; + case 0x57: return Qt::Key_W; + case 0x58: return Qt::Key_X; + case 0x59: return Qt::Key_Y; + case 0x5a: return Qt::Key_Z; + case 0x5b: return Qt::Key_BracketLeft; + case 0x5c: return Qt::Key_Backslash; + case 0x5d: return Qt::Key_BracketRight; + case 0x5e: return Qt::Key_AsciiCircum; + case 0x5f: return Qt::Key_Underscore; + case 0x60: return Qt::Key_QuoteLeft; + case 0x61: return Qt::Key_A; + case 0x62: return Qt::Key_B; + case 0x63: return Qt::Key_C; + case 0x64: return Qt::Key_D; + case 0x65: return Qt::Key_E; + case 0x66: return Qt::Key_F; + case 0x67: return Qt::Key_G; + case 0x68: return Qt::Key_H; + case 0x69: return Qt::Key_I; + case 0x6a: return Qt::Key_J; + case 0x6b: return Qt::Key_K; + case 0x6c: return Qt::Key_L; + case 0x6d: return Qt::Key_M; + case 0x6e: return Qt::Key_N; + case 0x6f: return Qt::Key_O; + case 0x70: return Qt::Key_P; + case 0x71: return Qt::Key_Q; + case 0x72: return Qt::Key_R; + case 0x73: return Qt::Key_S; + case 0x74: return Qt::Key_T; + case 0x75: return Qt::Key_U; + case 0x76: return Qt::Key_V; + case 0x77: return Qt::Key_W; + case 0x78: return Qt::Key_X; + case 0x79: return Qt::Key_Y; + case 0x7a: return Qt::Key_Z; + case 0x7b: return Qt::Key_BraceLeft; + case 0x7c: return Qt::Key_Bar; + case 0x7d: return Qt::Key_BraceRight; + case 0x7e: return Qt::Key_AsciiTilde; + + // Latin 1 codes adapted from X: keysymdef.h,v 1.21 94/08/28 16:17:06 + case 0xa0: return Qt::Key_nobreakspace; + case 0xa1: return Qt::Key_exclamdown; + case 0xa2: return Qt::Key_cent; + case 0xa3: return Qt::Key_sterling; + case 0xa4: return Qt::Key_currency; + case 0xa5: return Qt::Key_yen; + case 0xa6: return Qt::Key_brokenbar; + case 0xa7: return Qt::Key_section; + case 0xa8: return Qt::Key_diaeresis; + case 0xa9: return Qt::Key_copyright; + case 0xaa: return Qt::Key_ordfeminine; + case 0xab: return Qt::Key_guillemotleft; + case 0xac: return Qt::Key_notsign; + case 0xad: return Qt::Key_hyphen; + case 0xae: return Qt::Key_registered; + case 0xaf: return Qt::Key_macron; + case 0xb0: return Qt::Key_degree; + case 0xb1: return Qt::Key_plusminus; + case 0xb2: return Qt::Key_twosuperior; + case 0xb3: return Qt::Key_threesuperior; + case 0xb4: return Qt::Key_acute; + case 0xb5: return Qt::Key_mu; + case 0xb6: return Qt::Key_paragraph; + case 0xb7: return Qt::Key_periodcentered; + case 0xb8: return Qt::Key_cedilla; + case 0xb9: return Qt::Key_onesuperior; + case 0xba: return Qt::Key_masculine; + case 0xbb: return Qt::Key_guillemotright; + case 0xbc: return Qt::Key_onequarter; + case 0xbd: return Qt::Key_onehalf; + case 0xbe: return Qt::Key_threequarters; + case 0xbf: return Qt::Key_questiondown; + case 0xc0: return Qt::Key_Agrave; + case 0xc1: return Qt::Key_Aacute; + case 0xc2: return Qt::Key_Acircumflex; + case 0xc3: return Qt::Key_Atilde; + case 0xc4: return Qt::Key_Adiaeresis; + case 0xc5: return Qt::Key_Aring; + case 0xc6: return Qt::Key_AE; + case 0xc7: return Qt::Key_Ccedilla; + case 0xc8: return Qt::Key_Egrave; + case 0xc9: return Qt::Key_Eacute; + case 0xca: return Qt::Key_Ecircumflex; + case 0xcb: return Qt::Key_Ediaeresis; + case 0xcc: return Qt::Key_Igrave; + case 0xcd: return Qt::Key_Iacute; + case 0xce: return Qt::Key_Icircumflex; + case 0xcf: return Qt::Key_Idiaeresis; + case 0xd0: return Qt::Key_ETH; + case 0xd1: return Qt::Key_Ntilde; + case 0xd2: return Qt::Key_Ograve; + case 0xd3: return Qt::Key_Oacute; + case 0xd4: return Qt::Key_Ocircumflex; + case 0xd5: return Qt::Key_Otilde; + case 0xd6: return Qt::Key_Odiaeresis; + case 0xd7: return Qt::Key_multiply; + case 0xd8: return Qt::Key_Ooblique; + case 0xd9: return Qt::Key_Ugrave; + case 0xda: return Qt::Key_Uacute; + case 0xdb: return Qt::Key_Ucircumflex; + case 0xdc: return Qt::Key_Udiaeresis; + case 0xdd: return Qt::Key_Yacute; + case 0xde: return Qt::Key_THORN; + case 0xdf: return Qt::Key_ssharp; + case 0xe5: return Qt::Key_Aring; + case 0xe6: return Qt::Key_AE; + case 0xf7: return Qt::Key_division; + case 0xf8: return Qt::Key_Ooblique; + case 0xff: return Qt::Key_ydiaeresis; + default: return Qt::Key(0); + } +} + +/*! \internal + Convert a Qt Key to an ascii char value. + If the Qt key is unknown a 0 is returned. + + Note: this may happen more than you like since not all known + Qt keys _are_ converted already. So feel free to add all the keys you need. +*/ +char QtUiTest::keyToAscii(Qt::Key key) +{ + switch (key) { + case Qt::Key_Backspace: return 0x8; //BS + case Qt::Key_Tab: return 0x09; // HT + case Qt::Key_Backtab: return 0x0b; // VT + case Qt::Key_Enter: + case Qt::Key_Return: return 0x0d; // CR + case Qt::Key_Escape: return 0x1b; // ESC + case Qt::Key_Space: return 0x20; // 7 bit printable ASCII + case Qt::Key_Exclam: return 0x21; + case Qt::Key_QuoteDbl: return 0x22; + case Qt::Key_NumberSign: return 0x23; + case Qt::Key_Dollar: return 0x24; + case Qt::Key_Percent: return 0x25; + case Qt::Key_Ampersand: return 0x26; + case Qt::Key_Apostrophe: return 0x27; + case Qt::Key_ParenLeft: return 0x28; + case Qt::Key_ParenRight: return 0x29; + case Qt::Key_Asterisk: return 0x2a; + case Qt::Key_Plus: return 0x2b; + case Qt::Key_Comma: return 0x2c; + case Qt::Key_Minus: return 0x2d; + case Qt::Key_Period: return 0x2e; + case Qt::Key_Slash: return 0x2f; + case Qt::Key_0: return 0x30; + case Qt::Key_1: return 0x31; + case Qt::Key_2: return 0x32; + case Qt::Key_3: return 0x33; + case Qt::Key_4: return 0x34; + case Qt::Key_5: return 0x35; + case Qt::Key_6: return 0x36; + case Qt::Key_7: return 0x37; + case Qt::Key_8: return 0x38; + case Qt::Key_9: return 0x39; + case Qt::Key_Colon: return 0x3a; + case Qt::Key_Semicolon: return 0x3b; + case Qt::Key_Less: return 0x3c; + case Qt::Key_Equal: return 0x3d; + case Qt::Key_Greater: return 0x3e; + case Qt::Key_Question: return 0x3f; + case Qt::Key_At: return 0x40; + case Qt::Key_A: return 0x61; // 0x41 == 'A', 0x61 == 'a' + case Qt::Key_B: return 0x62; + case Qt::Key_C: return 0x63; + case Qt::Key_D: return 0x64; + case Qt::Key_E: return 0x65; + case Qt::Key_F: return 0x66; + case Qt::Key_G: return 0x67; + case Qt::Key_H: return 0x68; + case Qt::Key_I: return 0x69; + case Qt::Key_J: return 0x6a; + case Qt::Key_K: return 0x6b; + case Qt::Key_L: return 0x6c; + case Qt::Key_M: return 0x6d; + case Qt::Key_N: return 0x6e; + case Qt::Key_O: return 0x6f; + case Qt::Key_P: return 0x70; + case Qt::Key_Q: return 0x71; + case Qt::Key_R: return 0x72; + case Qt::Key_S: return 0x73; + case Qt::Key_T: return 0x74; + case Qt::Key_U: return 0x75; + case Qt::Key_V: return 0x76; + case Qt::Key_W: return 0x77; + case Qt::Key_X: return 0x78; + case Qt::Key_Y: return 0x79; + case Qt::Key_Z: return 0x7a; + case Qt::Key_BracketLeft: return 0x5b; + case Qt::Key_Backslash: return 0x5c; + case Qt::Key_BracketRight: return 0x5d; + case Qt::Key_AsciiCircum: return 0x5e; + case Qt::Key_Underscore: return 0x5f; + case Qt::Key_QuoteLeft: return 0x60; + + case Qt::Key_BraceLeft: return 0x7b; + case Qt::Key_Bar: return 0x7c; + case Qt::Key_BraceRight: return 0x7d; + case Qt::Key_AsciiTilde: return 0x7e; + + case Qt::Key_Delete: return 0; + case Qt::Key_Insert: return 0; // = 0x1006, + case Qt::Key_Pause: return 0; // = 0x1008, + case Qt::Key_Print: return 0; // = 0x1009, + case Qt::Key_SysReq: return 0; // = 0x100a, + + case Qt::Key_Clear: return 0; // = 0x100b, + + case Qt::Key_Home: return 0; // = 0x1010, // cursor movement + case Qt::Key_End: return 0; // = 0x1011, + case Qt::Key_Left: return 0; // = 0x1012, + case Qt::Key_Up: return 0; // = 0x1013, + case Qt::Key_Right: return 0; // = 0x1014, + case Qt::Key_Down: return 0; // = 0x1015, + case Qt::Key_PageUp: return 0; // = 0x1016, + case Qt::Key_PageDown: return 0; // = 0x1017, + case Qt::Key_Shift: return 0; // = 0x1020, // modifiers + case Qt::Key_Control: return 0; // = 0x1021, + case Qt::Key_Meta: return 0; // = 0x1022, + case Qt::Key_Alt: return 0; // = 0x1023, + case Qt::Key_CapsLock: return 0; // = 0x1024, + case Qt::Key_NumLock: return 0; // = 0x1025, + case Qt::Key_ScrollLock: return 0; // = 0x1026, + case Qt::Key_F1: return 0; // = 0x1030, // function keys + case Qt::Key_F2: return 0; // = 0x1031, + case Qt::Key_F3: return 0; // = 0x1032, + case Qt::Key_F4: return 0; // = 0x1033, + case Qt::Key_F5: return 0; // = 0x1034, + case Qt::Key_F6: return 0; // = 0x1035, + case Qt::Key_F7: return 0; // = 0x1036, + case Qt::Key_F8: return 0; // = 0x1037, + case Qt::Key_F9: return 0; // = 0x1038, + case Qt::Key_F10: return 0; // = 0x1039, + case Qt::Key_F11: return 0; // = 0x103a, + case Qt::Key_F12: return 0; // = 0x103b, + case Qt::Key_F13: return 0; // = 0x103c, + case Qt::Key_F14: return 0; // = 0x103d, + case Qt::Key_F15: return 0; // = 0x103e, + case Qt::Key_F16: return 0; // = 0x103f, + case Qt::Key_F17: return 0; // = 0x1040, + case Qt::Key_F18: return 0; // = 0x1041, + case Qt::Key_F19: return 0; // = 0x1042, + case Qt::Key_F20: return 0; // = 0x1043, + case Qt::Key_F21: return 0; // = 0x1044, + case Qt::Key_F22: return 0; // = 0x1045, + case Qt::Key_F23: return 0; // = 0x1046, + case Qt::Key_F24: return 0; // = 0x1047, + case Qt::Key_F25: return 0; // = 0x1048, // F25 .. F35 only on X11 + case Qt::Key_F26: return 0; // = 0x1049, + case Qt::Key_F27: return 0; // = 0x104a, + case Qt::Key_F28: return 0; // = 0x104b, + case Qt::Key_F29: return 0; // = 0x104c, + case Qt::Key_F30: return 0; // = 0x104d, + case Qt::Key_F31: return 0; // = 0x104e, + case Qt::Key_F32: return 0; // = 0x104f, + case Qt::Key_F33: return 0; // = 0x1050, + case Qt::Key_F34: return 0; // = 0x1051, + case Qt::Key_F35: return 0; // = 0x1052, + case Qt::Key_Super_L: return 0; // = 0x1053, // extra keys + case Qt::Key_Super_R: return 0; // = 0x1054, + case Qt::Key_Menu: return 0; // = 0x1055, + case Qt::Key_Hyper_L: return 0; // = 0x1056, + case Qt::Key_Hyper_R: return 0; // = 0x1057, + case Qt::Key_Help: return 0; // = 0x1058, + case Qt::Key_Direction_L: return 0; // = 0x1059, + case Qt::Key_Direction_R: return 0; // = 0x1060, + + // Latin 1 codes adapted from X: keysymdef.h,v 1.21 94/08/28 16:17:06 + case Qt::Key_nobreakspace: return char(0xa0); + case Qt::Key_exclamdown: return char(0xa1); + case Qt::Key_cent: return char(0xa2); + case Qt::Key_sterling: return char(0xa3); + case Qt::Key_currency: return char(0xa4); + case Qt::Key_yen: return char(0xa5); + case Qt::Key_brokenbar: return char(0xa6); + case Qt::Key_section: return char(0xa7); + case Qt::Key_diaeresis: return char(0xa8); + case Qt::Key_copyright: return char(0xa9); + case Qt::Key_ordfeminine: return char(0xaa); + case Qt::Key_guillemotleft: return char(0xab); // left angle quotation mar + case Qt::Key_notsign: return char(0xac); + case Qt::Key_hyphen: return char(0xad); + case Qt::Key_registered: return char(0xae); + case Qt::Key_macron: return char(0xaf); + case Qt::Key_degree: return char(0xb0); + case Qt::Key_plusminus: return char(0xb1); + case Qt::Key_twosuperior: return char(0xb2); + case Qt::Key_threesuperior: return char(0xb3); + case Qt::Key_acute: return char(0xb4); + case Qt::Key_mu: return char(0xb5); + case Qt::Key_paragraph: return char(0xb6); + case Qt::Key_periodcentered: return char(0xb7); + case Qt::Key_cedilla: return char(0xb8); + case Qt::Key_onesuperior: return char(0xb9); + case Qt::Key_masculine: return char(0xba); + case Qt::Key_guillemotright: return char(0xbb); // right angle quotation mar + case Qt::Key_onequarter: return char(0xbc); + case Qt::Key_onehalf: return char(0xbd); + case Qt::Key_threequarters: return char(0xbe); + case Qt::Key_questiondown: return char(0xbf); + case Qt::Key_Agrave: return char(0xc0); + case Qt::Key_Aacute: return char(0xc1); + case Qt::Key_Acircumflex: return char(0xc2); + case Qt::Key_Atilde: return char(0xc3); + case Qt::Key_Adiaeresis: return char(0xc4); + case Qt::Key_Aring: return char(0xe5); + case Qt::Key_AE: return char(0xe6); + case Qt::Key_Ccedilla: return char(0xc7); + case Qt::Key_Egrave: return char(0xc8); + case Qt::Key_Eacute: return char(0xc9); + case Qt::Key_Ecircumflex: return char(0xca); + case Qt::Key_Ediaeresis: return char(0xcb); + case Qt::Key_Igrave: return char(0xcc); + case Qt::Key_Iacute: return char(0xcd); + case Qt::Key_Icircumflex: return char(0xce); + case Qt::Key_Idiaeresis: return char(0xcf); + case Qt::Key_ETH: return char(0xd0); + case Qt::Key_Ntilde: return char(0xd1); + case Qt::Key_Ograve: return char(0xd2); + case Qt::Key_Oacute: return char(0xd3); + case Qt::Key_Ocircumflex: return char(0xd4); + case Qt::Key_Otilde: return char(0xd5); + case Qt::Key_Odiaeresis: return char(0xd6); + case Qt::Key_multiply: return char(0xd7); + case Qt::Key_Ooblique: return char(0xf8); + case Qt::Key_Ugrave: return char(0xd9); + case Qt::Key_Uacute: return char(0xda); + case Qt::Key_Ucircumflex: return char(0xdb); + case Qt::Key_Udiaeresis: return char(0xdc); + case Qt::Key_Yacute: return char(0xdd); + case Qt::Key_THORN: return char(0xde); + case Qt::Key_ssharp: return char(0xdf); + case Qt::Key_division: return char(0xf7); + case Qt::Key_ydiaeresis: return char(0xff); + + // multimedia/internet keys - ignored by default - see QKeyEvent c'tor + + case Qt::Key_Back : return 0; // = 0x1061, + case Qt::Key_Forward : return 0; // = 0x1062, + case Qt::Key_Stop : return 0; // = 0x1063, + case Qt::Key_Refresh : return 0; // = 0x1064, + + case Qt::Key_VolumeDown: return 0; // = 0x1070, + case Qt::Key_VolumeMute : return 0; // = 0x1071, + case Qt::Key_VolumeUp: return 0; // = 0x1072, + case Qt::Key_BassBoost: return 0; // = 0x1073, + case Qt::Key_BassUp: return 0; // = 0x1074, + case Qt::Key_BassDown: return 0; // = 0x1075, + case Qt::Key_TrebleUp: return 0; // = 0x1076, + case Qt::Key_TrebleDown: return 0; // = 0x1077, + + case Qt::Key_MediaPlay : return 0; // = 0x1080, + case Qt::Key_MediaStop : return 0; // = 0x1081, + case Qt::Key_MediaPrevious : return 0; // = 0x1082, + case Qt::Key_MediaNext : return 0; // = 0x1083, + case Qt::Key_MediaRecord: return 0; // = 0x1084, + + case Qt::Key_HomePage : return 0; // = 0x1090, + case Qt::Key_Favorites : return 0; // = 0x1091, + case Qt::Key_Search : return 0; // = 0x1092, + case Qt::Key_Standby: return 0; // = 0x1093, + case Qt::Key_OpenUrl: return 0; // = 0x1094, + + case Qt::Key_LaunchMail : return 0; // = 0x10a0, + case Qt::Key_LaunchMedia: return 0; // = 0x10a1, + case Qt::Key_Launch0 : return 0; // = 0x10a2, + case Qt::Key_Launch1 : return 0; // = 0x10a3, + case Qt::Key_Launch2 : return 0; // = 0x10a4, + case Qt::Key_Launch3 : return 0; // = 0x10a5, + case Qt::Key_Launch4 : return 0; // = 0x10a6, + case Qt::Key_Launch5 : return 0; // = 0x10a7, + case Qt::Key_Launch6 : return 0; // = 0x10a8, + case Qt::Key_Launch7 : return 0; // = 0x10a9, + case Qt::Key_Launch8 : return 0; // = 0x10aa, + case Qt::Key_Launch9 : return 0; // = 0x10ab, + case Qt::Key_LaunchA : return 0; // = 0x10ac, + case Qt::Key_LaunchB : return 0; // = 0x10ad, + case Qt::Key_LaunchC : return 0; // = 0x10ae, + case Qt::Key_LaunchD : return 0; // = 0x10af, + case Qt::Key_LaunchE : return 0; // = 0x10b0, + case Qt::Key_LaunchF : return 0; // = 0x10b1, + + default: return 0; + } +} + +/*! \internal + Convert an variant value to a Qt Key value. + If the key is unknown a 0 is returned. + */ + +Qt::Key QtUiTest::variantToKey(const QVariant &keyValue) +{ + Qt::Key key = (Qt::Key)0; + switch(keyValue.type()) { + default: + key = (Qt::Key)keyValue.toInt(); + break; + case QVariant::Char: + key = QtUiTest::asciiToKey(keyValue.toChar().toAscii()); + break; + case QVariant::String: + if (keyValue.toString().length() == 1) + key = QtUiTest::asciiToKey(keyValue.toString()[0].toAscii()); + break; + } + return key; +} diff --git a/src/remote/slave/lib/qeventwatcher.cpp b/src/remote/slave/lib/qeventwatcher.cpp new file mode 100644 index 0000000..4092a07 --- /dev/null +++ b/src/remote/slave/lib/qeventwatcher.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qeventwatcher_p.h" + +#include <QSet> +#include <QPointer> +#include <QCoreApplication> +#include <QtSystemTest/QstDebug> + +struct QEventWatcherPrivate +{ + QSet<QObject*> objects; + QList<QEventWatcherFilter*> filters; + int count; +}; + +QEventWatcher::QEventWatcher(QObject* parent) + : QObject(parent), + d(new QEventWatcherPrivate) +{ + QTT_TRACE_FUNCTION(); + d->count = 0; +} + +QEventWatcher::~QEventWatcher() +{ + QTT_TRACE_FUNCTION(); + qDeleteAll(d->filters); + delete d; + d = 0; +} + +void QEventWatcher::addObject(QObject* obj) +{ + QTT_TRACE_FUNCTION(); + d->objects << obj; + qApp->installEventFilter(this); +} + +void QEventWatcher::addFilter(QEventWatcherFilter* filter) +{ + QTT_TRACE_FUNCTION(); + d->filters << filter; +} + +int QEventWatcher::count() const +{ + QTT_TRACE_FUNCTION(); + return d->count; +} + +QString QEventWatcher::toString() const +{ + QTT_TRACE_FUNCTION(); + QString ret; + QString sep; + for (int i = d->filters.count()-1; i >= 0; --i) { + ret += sep + d->filters.at(i)->toString(); + sep = ", "; + } + return ret; +} + +bool QEventWatcher::eventFilter(QObject* obj, QEvent* e) +{ + QTT_TRACE_FUNCTION(); + if (!d->objects.contains(obj)) return false; + + bool accept = (d->filters.count() ? false : true); + for (int i = d->filters.count()-1; i >= 0 && !accept; --i) { + accept = d->filters.at(i)->accept(obj,e); + } + + if (accept) { + ++d->count; + emit event(obj, e->type()); + } + + return false; +} + diff --git a/src/remote/slave/lib/qeventwatcher_p.h b/src/remote/slave/lib/qeventwatcher_p.h new file mode 100644 index 0000000..c6e6809 --- /dev/null +++ b/src/remote/slave/lib/qeventwatcher_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QEVENTWATCHER_H +#define QEVENTWATCHER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtUiTest API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QObject> +#include <QEvent> + +struct QEventWatcherPrivate; +class QEventWatcherFilter; + +class QEventWatcher : public QObject +{ + Q_OBJECT + +public: + explicit QEventWatcher(QObject* parent =0); + virtual ~QEventWatcher(); + + void addObject(QObject*); + void addFilter(QEventWatcherFilter*); + + int count() const; + + QString toString() const; + +signals: + void event(QObject*,int); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +private: + QEventWatcherPrivate* d; +}; + +class QEventWatcherFilter +{ +public: + virtual ~QEventWatcherFilter() {} + +protected: + virtual bool accept(QObject*,QEvent*) const =0; + virtual QString toString() const =0; + + friend class QEventWatcher; +}; + +#endif + diff --git a/src/remote/slave/lib/qinputgenerator.cpp b/src/remote/slave/lib/qinputgenerator.cpp new file mode 100644 index 0000000..c97ca24 --- /dev/null +++ b/src/remote/slave/lib/qinputgenerator.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qinputgenerator_p.h" + +#include <QPoint> +#include <QtSystemTest/QstDebug> + +QInputGenerator::QInputGenerator(QObject* parent) + : QObject(parent) +{ + QTT_TRACE_FUNCTION(); +} + +QInputGenerator::~QInputGenerator() +{ + QTT_TRACE_FUNCTION(); +} + +void QInputGenerator::keyPress (Qt::Key, Qt::KeyboardModifiers, bool) {}; +void QInputGenerator::keyRelease(Qt::Key, Qt::KeyboardModifiers) {}; +void QInputGenerator::keyClick (Qt::Key, Qt::KeyboardModifiers) {}; + +void QInputGenerator::touchPress (const QVariantList&) {}; +void QInputGenerator::touchUpdate (const QVariantList&) {}; +void QInputGenerator::touchRelease (const QVariantList&) {}; + +void QInputGenerator::mousePress (const QPoint&, Qt::MouseButtons) {}; +void QInputGenerator::mouseRelease(const QPoint&, Qt::MouseButtons) {}; +void QInputGenerator::mouseClick (const QPoint&, Qt::MouseButtons) {}; +void QInputGenerator::mouseDClick (const QPoint&, Qt::MouseButtons) {}; +void QInputGenerator::mouseMove (const QPoint&) {}; + + +Qt::KeyboardModifier const QInputGenerator::AllModifiers[] = + { Qt::ShiftModifier, Qt::ControlModifier, Qt::AltModifier, Qt::MetaModifier }; + +Qt::Key QInputGenerator::modifierToKey(Qt::KeyboardModifier mod) +{ + QTT_TRACE_FUNCTION(); + switch (mod) { + case Qt::ShiftModifier: + return Qt::Key_Shift; + case Qt::ControlModifier: + return Qt::Key_Control; + case Qt::AltModifier: + return Qt::Key_Alt; + case Qt::MetaModifier: + return Qt::Key_Meta; + default: + break; + } + return Qt::Key(0); +} diff --git a/src/remote/slave/lib/qinputgenerator_generic.cpp b/src/remote/slave/lib/qinputgenerator_generic.cpp new file mode 100644 index 0000000..dd616ed --- /dev/null +++ b/src/remote/slave/lib/qinputgenerator_generic.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qinputgenerator_generic_p.h" +#include "qtuitestnamespace.h" + +static QWidget *focusWidget() +{ + QTT_TRACE_FUNCTION(); + QWidget *ret = QApplication::focusWidget(); + if (!ret) { + QWidgetList topLevel = QApplication::topLevelWidgets(); + if (!topLevel.isEmpty()) + return topLevel.first(); + } + return ret; +} + +QInputGeneratorGeneric::QInputGeneratorGeneric(QObject* parent) + : QInputGenerator(parent), + currentPos(), + currentButtons(0) +{ + QTT_TRACE_FUNCTION(); +} + +QInputGeneratorGeneric::~QInputGeneratorGeneric() +{ + QTT_TRACE_FUNCTION(); +} + +void QInputGeneratorGeneric::keyPress(Qt::Key key, Qt::KeyboardModifiers mod, bool autoRepeat) +{ + QTT_TRACE_FUNCTION(); + qttDebug() << "keyPress" << key << mod << autoRepeat; + Q_UNUSED(autoRepeat); + keyEvent(Press, focusWidget(), key, mod); +} + +void QInputGeneratorGeneric::keyRelease(Qt::Key key, Qt::KeyboardModifiers mod) +{ + QTT_TRACE_FUNCTION(); + qttDebug() << "keyRelease" << key << mod; + keyEvent(Release, focusWidget(), key, mod); +} + +void QInputGeneratorGeneric::keyClick(Qt::Key key, Qt::KeyboardModifiers mod) +{ + QTT_TRACE_FUNCTION(); + qttDebug() << "keyClick" << key << mod; + keyEvent(Click, focusWidget(), key, mod); +} + +void QInputGeneratorGeneric::touchPress(const QVariantList& points) +{ + Q_UNUSED(points); + QTT_TRACE_FUNCTION(); +} + +void QInputGeneratorGeneric::touchUpdate(const QVariantList& points) +{ + Q_UNUSED(points); + QTT_TRACE_FUNCTION(); +} + +void QInputGeneratorGeneric::touchRelease(const QVariantList& points) +{ + Q_UNUSED(points); + QTT_TRACE_FUNCTION(); +} + +void QInputGeneratorGeneric::mousePress(const QPoint& pos, Qt::MouseButtons state) +{ + QTT_TRACE_FUNCTION(); + const Qt::MouseButton buttons[] = {Qt::LeftButton, Qt::RightButton, Qt::MidButton, Qt::XButton1, Qt::XButton2}; + QWidget *widget=QApplication::widgetAt(pos); + if (pos != currentPos) { + mouseEvent(MouseMove, widget, Qt::NoButton, currentButtons, 0, widget->mapFromGlobal(pos)); + currentPos = pos; + } + for (unsigned int i=0; i<sizeof(buttons)/sizeof(Qt::MouseButton); i++) { + if (state.testFlag(buttons[i])) { + qttDebug() << "mousePress" << pos << buttons[i] << currentButtons; + currentButtons |= buttons[i]; + mouseEvent(MousePress, widget, buttons[i], buttons[i], 0, widget->mapFromGlobal(pos)); + } + } +} + +void QInputGeneratorGeneric::mouseRelease(const QPoint& pos, Qt::MouseButtons state) +{ + QTT_TRACE_FUNCTION(); + const Qt::MouseButton buttons[] = {Qt::LeftButton, Qt::RightButton, Qt::MidButton, Qt::XButton1, Qt::XButton2}; + QWidget *widget=QApplication::widgetAt(pos); + qttDebug() << "widget:" << widget; + if (pos != currentPos) { + mouseEvent(MouseMove, widget, Qt::NoButton, currentButtons, 0, widget->mapFromGlobal(pos)); + currentPos = pos; + } + for (unsigned int i=0; i<sizeof(buttons)/sizeof(Qt::MouseButton); i++) { + if (state.testFlag(buttons[i])) { + qttDebug() << "mouseRelease" << pos << buttons[i] << currentButtons; + currentButtons ^= buttons[i]; + mouseEvent(MouseRelease, widget, buttons[i], currentButtons, 0, widget->mapFromGlobal(pos)); + } + } +} + +void QInputGeneratorGeneric::mouseClick(const QPoint& pos, Qt::MouseButtons state) +{ + QTT_TRACE_FUNCTION(); + const Qt::MouseButton buttons[] = {Qt::LeftButton, Qt::RightButton, Qt::MidButton, Qt::XButton1, Qt::XButton2}; + QWidget *widget=QApplication::widgetAt(pos); + if (pos != currentPos) { + mouseEvent(MouseMove, widget, Qt::NoButton, currentButtons, 0, widget->mapFromGlobal(pos)); + currentPos = pos; + } + for (unsigned int i=0; i<sizeof(buttons)/sizeof(Qt::MouseButton); i++) { + if (state.testFlag(buttons[i])) { + qttDebug() << "mouseClick" << pos << buttons[i]; + mouseEvent(MouseClick, widget, buttons[i], state, 0, widget->mapFromGlobal(pos)); + } + } +} + +void QInputGeneratorGeneric::mouseDClick(const QPoint& pos, Qt::MouseButtons state) +{ + QTT_TRACE_FUNCTION(); + const Qt::MouseButton buttons[] = {Qt::LeftButton, Qt::RightButton, Qt::MidButton, Qt::XButton1, Qt::XButton2}; + QWidget *widget=QApplication::widgetAt(pos); + if (pos != currentPos) { + mouseEvent(MouseMove, widget, Qt::NoButton, currentButtons, 0, widget->mapFromGlobal(pos)); + currentPos = pos; + } + for (unsigned int i=0; i<sizeof(buttons)/sizeof(Qt::MouseButton); i++) { + if (state.testFlag(buttons[i])) { + qttDebug() << "mouseClick" << pos << buttons[i]; + mouseEvent(MouseDClick, widget, buttons[i], state, 0, widget->mapFromGlobal(pos)); + } + } +} + +void QInputGeneratorGeneric::mouseMove(const QPoint& pos) +{ + QTT_TRACE_FUNCTION(); + qttDebug() << "mouseMove" << pos; + QWidget *widget=QApplication::widgetAt(pos); + if (pos != currentPos) { + currentPos = pos; + } + mouseEvent(MouseMove, widget, Qt::NoButton, currentButtons, 0, widget->mapFromGlobal(pos)); +} + diff --git a/src/remote/slave/lib/qinputgenerator_generic_p.h b/src/remote/slave/lib/qinputgenerator_generic_p.h new file mode 100644 index 0000000..a44de33 --- /dev/null +++ b/src/remote/slave/lib/qinputgenerator_generic_p.h @@ -0,0 +1,236 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QINPUTGENERATORGENERIC_P_H +#define QINPUTGENERATORGENERIC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtUiTest API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGlobal> +#include <QWidget> +#include <QMouseEvent> +#include <QPoint> +#include <QPointer> +#include <QApplication> +#include <QtSystemTest/qstglobal.h> +#include <qinputgenerator_p.h> +#include <QtSystemTest/QstDebug> +#include <QtTest/qtestspontaneevent.h> + +enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDClick, MouseMove }; + +static void mouseEvent(MouseAction action, QWidget *widget, Qt::MouseButton button, Qt::MouseButtons buttons, + Qt::KeyboardModifiers stateKey, QPoint pos) +{ + QTT_TRACE_FUNCTION(); + if (pos.isNull()) + pos = widget->rect().center(); + + if (action == MouseClick) { + mouseEvent(MousePress, widget, button, buttons, stateKey, pos); + mouseEvent(MouseRelease, widget, button, 0, stateKey, pos); + return; + } + + stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask); + + QMouseEvent me(QEvent::User, QPoint(), Qt::LeftButton, button, stateKey); + switch (action) + { + case MousePress: + me = QMouseEvent(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, buttons, stateKey); + break; + case MouseRelease: + me = QMouseEvent(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, buttons, stateKey); + break; + case MouseDClick: + me = QMouseEvent(QEvent::MouseButtonDblClick, pos, widget->mapToGlobal(pos), button, buttons, stateKey); + break; + case MouseMove: + me = QMouseEvent(QEvent::MouseMove, pos, widget->mapToGlobal(pos), Qt::NoButton, buttons, stateKey); + break; + default: + break; + } + QSpontaneKeyEvent::setSpontaneous(&me); + if (!qApp->notify(widget, &me)) { + static const char *mouseActionNames[] = + { "MousePress", "MouseRelease", "MouseClick", "MouseDClick", "MouseMove" }; + QString warning = QString::fromLatin1("Mouse event \"%1\" not accepted by receiving widget"); + qWarning() << warning.arg(QString::fromLatin1(mouseActionNames[static_cast<int>(action)])); + } + +} + +enum KeyAction { Press, Release, Click }; + +static void simulateEvent(QWidget *widget, bool press, int code, + Qt::KeyboardModifiers modifier, QString text, bool repeat) +{ + QTT_TRACE_FUNCTION(); + QKeyEvent a(press ? QEvent::KeyPress : QEvent::KeyRelease, code, modifier, text, repeat); + QSpontaneKeyEvent::setSpontaneous(&a); + if (!qApp->notify(widget, &a)) + qWarning() << "Keyboard event not accepted by receiving widget"; +} + +static void sendKeyEvent(KeyAction action, QWidget *widget, Qt::Key code, + QString text, Qt::KeyboardModifiers modifier) +{ + QTT_TRACE_FUNCTION(); + if (!widget) + widget = QWidget::keyboardGrabber(); + if (!widget) { + if (QWidget *apw = QApplication::activePopupWidget()) + widget = apw->focusWidget() ? apw->focusWidget() : apw; + else + widget = QApplication::focusWidget(); + } + if (!widget) + widget = QApplication::activeWindow(); + + if (action == Click) { + QPointer<QWidget> ptr(widget); + sendKeyEvent(Press, widget, code, text, modifier); + if (!ptr) { + // if we send key-events to embedded widgets, they might be destroyed + // when the user presses Return + return; + } + sendKeyEvent(Release, widget, code, text, modifier); + return; + } + + bool repeat = false; + + if (action == Press) { + if (modifier & Qt::ShiftModifier) + simulateEvent(widget, true, Qt::Key_Shift, 0, QString(), false); + + if (modifier & Qt::ControlModifier) + simulateEvent(widget, true, Qt::Key_Control, modifier & Qt::ShiftModifier, QString(), false); + + if (modifier & Qt::AltModifier) + simulateEvent(widget, true, Qt::Key_Alt, + modifier & (Qt::ShiftModifier | Qt::ControlModifier), QString(), false); + if (modifier & Qt::MetaModifier) + simulateEvent(widget, true, Qt::Key_Meta, modifier & (Qt::ShiftModifier + | Qt::ControlModifier | Qt::AltModifier), QString(), false); + simulateEvent(widget, true, code, modifier, text, repeat); + } else if (action == Release) { + simulateEvent(widget, false, code, modifier, text, repeat); + + if (modifier & Qt::MetaModifier) + simulateEvent(widget, false, Qt::Key_Meta, modifier, QString(), false); + if (modifier & Qt::AltModifier) + simulateEvent(widget, false, Qt::Key_Alt, modifier & + (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier), QString(), false); + + if (modifier & Qt::ControlModifier) + simulateEvent(widget, false, Qt::Key_Control, + modifier & (Qt::ShiftModifier | Qt::ControlModifier), QString(), false); + + if (modifier & Qt::ShiftModifier) + simulateEvent(widget, false, Qt::Key_Shift, modifier & Qt::ShiftModifier, QString(), false); + } +} + +// Convenience function +static void sendKeyEvent(KeyAction action, QWidget *widget, Qt::Key code, + char ascii, Qt::KeyboardModifiers modifier) +{ + QTT_TRACE_FUNCTION(); + QString text; + if (ascii) + text = QString(QChar::fromLatin1(ascii)); + sendKeyEvent(action, widget, code, text, modifier); +} + +inline static void keyEvent(KeyAction action, QWidget *widget, Qt::Key key, + Qt::KeyboardModifiers modifier = Qt::NoModifier) +{ + QTT_TRACE_FUNCTION(); + if (modifier & Qt::ShiftModifier) + sendKeyEvent(action, widget, key, QChar(key).toUpper().unicode(), modifier); + else + sendKeyEvent(action, widget, key, QChar(key).toLower().unicode(), modifier); +} + + +class QTUITEST_EXPORT QInputGeneratorGeneric : public QInputGenerator +{ +Q_OBJECT +public: + explicit QInputGeneratorGeneric(QObject* =0); + virtual ~QInputGeneratorGeneric(); + + virtual void keyPress (Qt::Key, Qt::KeyboardModifiers, bool=false); + virtual void keyRelease(Qt::Key, Qt::KeyboardModifiers); + virtual void keyClick (Qt::Key, Qt::KeyboardModifiers); + + virtual void touchPress (const QVariantList&); + virtual void touchUpdate (const QVariantList&); + virtual void touchRelease(const QVariantList&); + + virtual void mousePress (const QPoint&, Qt::MouseButtons); + virtual void mouseRelease(const QPoint&, Qt::MouseButtons); + virtual void mouseClick (const QPoint&, Qt::MouseButtons); + virtual void mouseDClick (const QPoint&, Qt::MouseButtons); + virtual void mouseMove (const QPoint&); + +protected: + QPoint currentPos; + Qt::MouseButtons currentButtons; + +}; + +#endif + diff --git a/src/remote/slave/lib/qinputgenerator_p.h b/src/remote/slave/lib/qinputgenerator_p.h new file mode 100644 index 0000000..26df042 --- /dev/null +++ b/src/remote/slave/lib/qinputgenerator_p.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QKEYGENERATOR_P_H +#define QKEYGENERATOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtUiTest API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGlobal> +#include <QObject> +#include <QVariantList> +#include <QtSystemTest/qstglobal.h> + +class QPoint; +class QInputGeneratorPrivate; + +class QTUITEST_EXPORT QInputGenerator : public QObject +{ +Q_OBJECT +public: + explicit QInputGenerator(QObject* =0); + virtual ~QInputGenerator(); + + virtual void keyPress (Qt::Key, Qt::KeyboardModifiers, bool=false); + virtual void keyRelease(Qt::Key, Qt::KeyboardModifiers); + virtual void keyClick (Qt::Key, Qt::KeyboardModifiers); + + virtual void touchPress (const QVariantList&); + virtual void touchUpdate (const QVariantList&); + virtual void touchRelease(const QVariantList&); + + virtual void mousePress (const QPoint&, Qt::MouseButtons); + virtual void mouseRelease(const QPoint&, Qt::MouseButtons); + virtual void mouseClick (const QPoint&, Qt::MouseButtons); + virtual void mouseDClick (const QPoint&, Qt::MouseButtons); + virtual void mouseMove (const QPoint&); + +protected: + QInputGeneratorPrivate* d; + friend class QInputGeneratorPrivate; + + static Qt::Key modifierToKey(Qt::KeyboardModifier); + static Qt::KeyboardModifier const AllModifiers[4]; +}; + +#endif + diff --git a/src/remote/slave/lib/qinputgenerator_qwindow.cpp b/src/remote/slave/lib/qinputgenerator_qwindow.cpp new file mode 100644 index 0000000..155e9c2 --- /dev/null +++ b/src/remote/slave/lib/qinputgenerator_qwindow.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qinputgenerator_qwindow_p.h" +#include "qtuitestnamespace.h" + +static QWindow *activeWindow() +{ + QTT_TRACE_FUNCTION(); + QWindow *w=0; + if (!qApp->topLevelWindows().isEmpty()) + w = qApp->topLevelWindows().first(); + + return w; +} + +QInputGeneratorGeneric::QInputGeneratorGeneric(QObject* parent) + : QInputGenerator(parent), + currentPos(), + currentButtons(0) +{ + QTT_TRACE_FUNCTION(); +} + +QInputGeneratorGeneric::~QInputGeneratorGeneric() +{ + QTT_TRACE_FUNCTION(); +} + +void QInputGeneratorGeneric::keyPress(Qt::Key key, Qt::KeyboardModifiers mod, bool autoRepeat) +{ + QTT_TRACE_FUNCTION(); + qttDebug() << "keyPress" << key << mod << autoRepeat; + Q_UNUSED(autoRepeat); + keyEvent(Press, activeWindow(), key, mod); +} + +void QInputGeneratorGeneric::keyRelease(Qt::Key key, Qt::KeyboardModifiers mod) +{ + QTT_TRACE_FUNCTION(); + qttDebug() << "keyRelease" << key << mod; + keyEvent(Release, activeWindow(), key, mod); +} + +void QInputGeneratorGeneric::keyClick(Qt::Key key, Qt::KeyboardModifiers mod) +{ + QTT_TRACE_FUNCTION(); + qttDebug() << "keyClick" << key << mod; + keyEvent(Click, activeWindow(), key, mod); +} + +void QInputGeneratorGeneric::touchPress(const QVariantList& points) +{ + QTT_TRACE_FUNCTION(); + QWindow *window=activeWindow(); + + touchEvent(TouchPress, window, points); +} + +void QInputGeneratorGeneric::touchUpdate(const QVariantList& points) +{ + QTT_TRACE_FUNCTION(); + QWindow *window=activeWindow(); + touchEvent(TouchUpdate, window, points); +} + +void QInputGeneratorGeneric::touchRelease(const QVariantList& points) +{ + QTT_TRACE_FUNCTION(); + QWindow *window=activeWindow(); + touchEvent(TouchRelease, window, points); +} + +void QInputGeneratorGeneric::mousePress(const QPoint& pos, Qt::MouseButtons state) +{ + QTT_TRACE_FUNCTION(); + const Qt::MouseButton buttons[] = {Qt::LeftButton, Qt::RightButton, Qt::MidButton, Qt::XButton1, Qt::XButton2}; + QWindow *window=activeWindow(); + if (pos != currentPos) { + mouseEvent(MouseMove, window, Qt::NoButton, currentButtons, 0, window->mapFromGlobal(pos)); + currentPos = pos; + } + for (unsigned int i=0; i<sizeof(buttons)/sizeof(Qt::MouseButton); i++) { + if (state.testFlag(buttons[i])) { + qttDebug() << "mousePress" << pos << buttons[i] << currentButtons; + currentButtons |= buttons[i]; + mouseEvent(MousePress, window, buttons[i], buttons[i], 0, window->mapFromGlobal(pos)); + } + } +} + +void QInputGeneratorGeneric::mouseRelease(const QPoint& pos, Qt::MouseButtons state) +{ + QTT_TRACE_FUNCTION(); + const Qt::MouseButton buttons[] = {Qt::LeftButton, Qt::RightButton, Qt::MidButton, Qt::XButton1, Qt::XButton2}; + QWindow *window=activeWindow(); + qttDebug() << "window:" << window; + if (pos != currentPos) { + mouseEvent(MouseMove, window, Qt::NoButton, currentButtons, 0, window->mapFromGlobal(pos)); + currentPos = pos; + } + for (unsigned int i=0; i<sizeof(buttons)/sizeof(Qt::MouseButton); i++) { + if (state.testFlag(buttons[i])) { + qttDebug() << "mouseRelease" << pos << buttons[i] << currentButtons; + currentButtons ^= buttons[i]; + mouseEvent(MouseRelease, window, buttons[i], currentButtons, 0, window->mapFromGlobal(pos)); + } + } +} + +void QInputGeneratorGeneric::mouseClick(const QPoint& pos, Qt::MouseButtons state) +{ + QTT_TRACE_FUNCTION(); + const Qt::MouseButton buttons[] = {Qt::LeftButton, Qt::RightButton, Qt::MidButton, Qt::XButton1, Qt::XButton2}; + QWindow *window=activeWindow(); + if (pos != currentPos) { + mouseEvent(MouseMove, window, Qt::NoButton, currentButtons, 0, window->mapFromGlobal(pos)); + currentPos = pos; + } + for (unsigned int i=0; i<sizeof(buttons)/sizeof(Qt::MouseButton); i++) { + if (state.testFlag(buttons[i])) { + qttDebug() << "mouseClick" << pos << buttons[i]; + mouseEvent(MouseClick, window, buttons[i], state, 0, window->mapFromGlobal(pos)); + } + } +} + +void QInputGeneratorGeneric::mouseDClick(const QPoint& pos, Qt::MouseButtons state) +{ + QTT_TRACE_FUNCTION(); + const Qt::MouseButton buttons[] = {Qt::LeftButton, Qt::RightButton, Qt::MidButton, Qt::XButton1, Qt::XButton2}; + QWindow *window=activeWindow(); + if (pos != currentPos) { + mouseEvent(MouseMove, window, Qt::NoButton, currentButtons, 0, window->mapFromGlobal(pos)); + currentPos = pos; + } + for (unsigned int i=0; i<sizeof(buttons)/sizeof(Qt::MouseButton); i++) { + if (state.testFlag(buttons[i])) { + qttDebug() << "mouseClick" << pos << buttons[i]; + mouseEvent(MouseDClick, window, buttons[i], state, 0, window->mapFromGlobal(pos)); + } + } +} + +void QInputGeneratorGeneric::mouseMove(const QPoint& pos) +{ + QTT_TRACE_FUNCTION(); + qttDebug() << "mouseMove" << pos; + QWindow *window=activeWindow(); + if (pos != currentPos) { + currentPos = pos; + } + mouseEvent(MouseMove, window, Qt::NoButton, currentButtons, 0, window->mapFromGlobal(pos)); +} diff --git a/src/remote/slave/lib/qinputgenerator_qwindow_p.h b/src/remote/slave/lib/qinputgenerator_qwindow_p.h new file mode 100644 index 0000000..705de44 --- /dev/null +++ b/src/remote/slave/lib/qinputgenerator_qwindow_p.h @@ -0,0 +1,288 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QINPUTGENERATORQWINDOW_P_H +#define QINPUTGENERATORQWINDOW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtUiTest API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGlobal> +#include <QMouseEvent> +#include <QPoint> +#include <QPointer> +#include <QApplication> +#include <QtSystemTest/qstglobal.h> +#include <qinputgenerator_p.h> +#include <qtuitestnamespace.h> +#include <QtTest/qtestspontaneevent.h> +#include <QtGui/qwindowsysteminterface_qpa.h> +#include <QtSystemTest/QstDebug> + +enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDClick, MouseMove }; +enum TouchAction { TouchPress, TouchRelease, TouchUpdate }; + +static void mouseEvent(MouseAction action, QWindow *widget, Qt::MouseButton button, Qt::MouseButtons buttons, + Qt::KeyboardModifiers stateKey, QPoint pos) +{ + QTT_TRACE_FUNCTION(); + if (pos.isNull()) + pos = widget->geometry().center(); + + if (action == MouseClick) { + mouseEvent(MousePress, widget, button, buttons, stateKey, pos); + mouseEvent(MouseRelease, widget, button, 0, stateKey, pos); + return; + } + + stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask); + + QMouseEvent me(QEvent::User, QPoint(), Qt::LeftButton, button, stateKey); + switch (action) + { + case MousePress: + me = QMouseEvent(QEvent::MouseButtonPress, pos, widget->mapToGlobal(pos), button, buttons, stateKey); + break; + case MouseRelease: + me = QMouseEvent(QEvent::MouseButtonRelease, pos, widget->mapToGlobal(pos), button, buttons, stateKey); + break; + case MouseDClick: + me = QMouseEvent(QEvent::MouseButtonDblClick, pos, widget->mapToGlobal(pos), button, buttons, stateKey); + break; + case MouseMove: + me = QMouseEvent(QEvent::MouseMove, pos, widget->mapToGlobal(pos), Qt::NoButton, buttons, stateKey); + break; + default: + break; + } + QSpontaneKeyEvent::setSpontaneous(&me); + if (!qApp->notify(widget, &me)) { + static const char *mouseActionNames[] = + { "MousePress", "MouseRelease", "MouseClick", "MouseDClick", "MouseMove" }; + QString warning = QString::fromLatin1("Mouse event \"%1\" not accepted by receiving widget"); + qWarning() << warning.arg(QString::fromLatin1(mouseActionNames[static_cast<int>(action)])); + } + +} + +static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint &pt) +{ + QWindowSystemInterface::TouchPoint p; + p.id = pt.id(); + p.flags = pt.flags(); + p.normalPosition = pt.normalizedPos(); + p.area = pt.screenRect(); + p.pressure = pt.pressure(); + p.state = pt.state(); + p.velocity = pt.velocity(); + p.rawPositions = pt.rawScreenPositions(); + return p; +} + +static QList<struct QWindowSystemInterface::TouchPoint> touchPointList(const QList<QTouchEvent::TouchPoint> &pointList) +{ + QList<struct QWindowSystemInterface::TouchPoint> newList; + + Q_FOREACH (QTouchEvent::TouchPoint p, pointList) + { + newList.append(touchPoint(p)); + } + return newList; +} + +static void touchEvent(TouchAction action, QWindow *widget, const QVariantList &points) +{ + QTT_TRACE_FUNCTION(); + + const QTouchDevice *dev = 0; + QList<const QTouchDevice *> devices = QTouchDevice::devices(); + if (devices.size()) + dev = devices.at(0); + + QList<QTouchEvent::TouchPoint> newList; + + for (int i = 0; i < points.size(); ++i) { + QTouchEvent::TouchPoint p(i); + p.setPos(points[i].toPoint()); + p.setScreenPos(widget->mapToGlobal(points[i].toPoint())); + + switch (action) + { + case TouchPress: + p.setState(Qt::TouchPointPressed); + break; + case TouchRelease: + p.setState(Qt::TouchPointReleased); + break; + default: + p.setState(Qt::TouchPointMoved); + break; + } + + newList.append(p); + } + + QWindowSystemInterface::handleTouchEvent(widget, const_cast<QTouchDevice*>(dev), touchPointList(newList)); +} + +enum KeyAction { Press, Release, Click }; + +static void simulateEvent(QWindow *window, bool press, int code, + Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1) +{ + QTT_TRACE_FUNCTION(); + QEvent::Type type; + type = press ? QEvent::KeyPress : QEvent::KeyRelease; + QWindowSystemInterface::handleKeyEvent(window, type, code, modifier, text, repeat, delay); +} + +static void sendKeyEvent(KeyAction action, QWindow *window, Qt::Key code, + QString text, Qt::KeyboardModifiers modifier, int delay=-1) +{ + QTT_TRACE_FUNCTION(); + if (action == Click) { + sendKeyEvent(Press, window, code, text, modifier, delay); + sendKeyEvent(Release, window, code, text, modifier, delay); + return; + } + + bool repeat = false; + + if (action == Press) { + if (modifier & Qt::ShiftModifier) + simulateEvent(window, true, Qt::Key_Shift, 0, QString(), false, delay); + + if (modifier & Qt::ControlModifier) + simulateEvent(window, true, Qt::Key_Control, modifier & Qt::ShiftModifier, QString(), false, delay); + + if (modifier & Qt::AltModifier) + simulateEvent(window, true, Qt::Key_Alt, + modifier & (Qt::ShiftModifier | Qt::ControlModifier), QString(), false, delay); + if (modifier & Qt::MetaModifier) + simulateEvent(window, true, Qt::Key_Meta, modifier & (Qt::ShiftModifier + | Qt::ControlModifier | Qt::AltModifier), QString(), false, delay); + simulateEvent(window, true, code, modifier, text, repeat, delay); + } else if (action == Release) { + simulateEvent(window, false, code, modifier, text, repeat, delay); + + if (modifier & Qt::MetaModifier) + simulateEvent(window, false, Qt::Key_Meta, modifier, QString(), false, delay); + if (modifier & Qt::AltModifier) + simulateEvent(window, false, Qt::Key_Alt, modifier & + (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier), QString(), false, delay); + + if (modifier & Qt::ControlModifier) + simulateEvent(window, false, Qt::Key_Control, + modifier & (Qt::ShiftModifier | Qt::ControlModifier), QString(), false, delay); + + if (modifier & Qt::ShiftModifier) + simulateEvent(window, false, Qt::Key_Shift, modifier & Qt::ShiftModifier, QString(), false, delay); + } +} + +static void sendKeyEvent(KeyAction action, QWindow *window, Qt::Key code, + char ascii, Qt::KeyboardModifiers modifier, int delay=-1) +{ + QTT_TRACE_FUNCTION(); + QString text; + if (ascii) + text = QString(QChar::fromLatin1(ascii)); + sendKeyEvent(action, window, code, text, modifier, delay); +} + +inline static void keyEvent(KeyAction action, QWindow *window, char ascii, + Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) +{ + QTT_TRACE_FUNCTION(); + sendKeyEvent(action, window, QtUiTest::asciiToKey(ascii), ascii, modifier, delay); +} + +inline static void keyEvent(KeyAction action, QWindow *window, Qt::Key key, + Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) +{ + QTT_TRACE_FUNCTION(); + if (modifier & Qt::ShiftModifier) + sendKeyEvent(action, window, key, QChar(key).toUpper().unicode(), modifier, delay); + else + sendKeyEvent(action, window, key, QChar(key).toLower().unicode(), modifier, delay); +} + + +class QTUITEST_EXPORT QInputGeneratorGeneric : public QInputGenerator +{ +Q_OBJECT +public: + explicit QInputGeneratorGeneric(QObject* =0); + virtual ~QInputGeneratorGeneric(); + + virtual void keyPress (Qt::Key, Qt::KeyboardModifiers, bool=false); + virtual void keyRelease(Qt::Key, Qt::KeyboardModifiers); + virtual void keyClick (Qt::Key, Qt::KeyboardModifiers); + + virtual void touchPress (const QVariantList&); + virtual void touchUpdate (const QVariantList&); + virtual void touchRelease(const QVariantList&); + + virtual void mousePress (const QPoint&, Qt::MouseButtons); + virtual void mouseRelease(const QPoint&, Qt::MouseButtons); + virtual void mouseClick (const QPoint&, Qt::MouseButtons); + virtual void mouseDClick (const QPoint&, Qt::MouseButtons); + virtual void mouseMove (const QPoint&); + +protected: + void registerDevice(); + + QPoint currentPos; + Qt::MouseButtons currentButtons; + QTouchDevice *device; +}; + +#endif + diff --git a/src/remote/slave/lib/qsensorgenerator.cpp b/src/remote/slave/lib/qsensorgenerator.cpp new file mode 100644 index 0000000..7c62b59 --- /dev/null +++ b/src/remote/slave/lib/qsensorgenerator.cpp @@ -0,0 +1,355 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qsensorgenerator_p.h" +#include <qtuitestnamespace.h> +#include <QtSystemTest/QstDebug> +#include <QTimerEvent> +#include <QTimer> +#include <QDateTime> +#include <QMetaObject> +#include <QMetaProperty> + +static void copySensorProperties(QObject *source, QObject *dest) +{ + const QMetaObject *meta = source->metaObject(); + for (int i = QSensor::staticMetaObject.propertyOffset(); i < meta->propertyCount(); i++) { + QMetaProperty prop = meta->property(i); + // Not these ones... + if (prop.name() == QLatin1String("type") || + prop.name() == QLatin1String("sensorid") || + prop.name() == QLatin1String("connectedToBackend") || + prop.name() == QLatin1String("availableDataRates") || + prop.name() == QLatin1String("dataRate") || + prop.name() == QLatin1String("reading") || + prop.name() == QLatin1String("busy") || + prop.name() == QLatin1String("active") || + prop.name() == QLatin1String("outputRanges") || + prop.name() == QLatin1String("outputRange") || + prop.name() == QLatin1String("description") || + prop.name() == QLatin1String("error")) { + continue; + } + dest->setProperty(prop.name(), prop.read(source)); + } +} + +QtUiTestSensorBackend::QtUiTestSensorBackend(QSensor *sensor, const QByteArray &sensorId, const QByteArray &fallThroughId) + : QSensorBackend(sensor), m_fallThrough(0), m_mode(PassThrough), m_timerId(0) +{ + // see if we have a fall-through sensor + if (!fallThroughId.isEmpty()) { + QList<QByteArray> list = sensor->sensorsForType(sensor->type()); + if (list.contains(fallThroughId)) { + m_fallThrough = new QSensor(sensor->type(), this); + m_fallThrough->setIdentifier(fallThroughId); + + // Connect to the fallthrough sensor + bool connectedToFallThrough = m_fallThrough->connectToBackend(); + Q_ASSERT(connectedToFallThrough); + + // Set informative properties + setDescription(m_fallThrough->description()); + setDataRates(m_fallThrough); + foreach (const qoutputrange &r, m_fallThrough->outputRanges()) { + addOutputRange(r.minimum, r.maximum, r.accuracy); + } + + // Set any other properties from the fallthrough sensor + copySensorProperties(m_fallThrough, sensor); + + // Handle signals from the fallthrough sensor + connect(m_fallThrough, SIGNAL(readingChanged()), this, SLOT(forwardFallthroughReading())); + connect(m_fallThrough, SIGNAL(sensorError(int)), sensor, SIGNAL(sensorError(int))); + connect(m_fallThrough, SIGNAL(busyChanged()), sensor, SIGNAL(busyChanged())); + } + } + + // set the mode to match any existing active backends + setMode(mode(sensorId)); + + if (!m_fallThrough) { + addDataRate(100, 100); + } + + // add ourselves to the list of backends. + activeBackends().append(this); +} + +QtUiTestSensorBackend::~QtUiTestSensorBackend() +{ + activeBackends().removeAll(this); +} + +int QtUiTestSensorBackend::interval() const +{ + int dataRate, interval; + dataRate = sensor()->dataRate(); + if (dataRate == 0) { + if (sensor()->availableDataRates().count()) + // Use the first available rate when -1 is chosen + dataRate = sensor()->availableDataRates().first().first; + else + dataRate = 1; + } + + interval = 1000 / dataRate; + return interval; +} + +void QtUiTestSensorBackend::start() +{ + if (m_timerId) + return; + + switch (m_mode) { + case PassThrough: + case Record: + if (m_fallThrough) { + m_fallThrough->setDataRate(sensor()->dataRate()); + m_fallThrough->setOutputRange(sensor()->outputRange()); + // Set extra properties onto the fallthrough sensor + copySensorProperties(sensor(), m_fallThrough); + m_fallThrough->start(); + if (!m_fallThrough->isActive()) + sensorStopped(); + } + m_timerId = -1; + break; + case Generate: + m_timerId = startTimer(interval()); + break; + } +} + +void QtUiTestSensorBackend::stop() +{ + if (!m_timerId) + return; + + switch (m_mode) { + case PassThrough: + case Record: + if (m_fallThrough) + m_fallThrough->stop(); + m_timerId = 0; + case Generate: + killTimer(m_timerId); + m_timerId = 0; + } +} + +void QtUiTestSensorBackend::timerEvent(QTimerEvent *event) +{ + if (event->timerId() != m_timerId) + return; + switch (m_mode) { + case PassThrough: + case Record: + break; + case Generate: + if (m_testData.count() > 1) + setCurrentTestData(m_testData.takeFirst()); + else if (!m_testData.isEmpty()) + setCurrentTestData(m_testData.first()); + break; + } +} + +void QtUiTestSensorBackend::setMode(Mode mode) +{ + if (m_mode == mode) + return; + // test data shouldn't survive mode changes + // as it has diffeerent meanings in each mode + m_testData.clear(); + // check if we need to turn timers on/off + if (m_timerId) { + if (m_mode == Generate) { + killTimer(m_timerId); + m_timerId = -1; + } else if (mode == Generate) { + m_timerId = startTimer(interval()); + } + } + m_mode = mode; + // some sensors are not noisy, get at least one value updated + // for new mode. + forwardFallthroughReading(); +} + +void QtUiTestSensorBackend::queueTestData(const QList<QVariant> &data) +{ + m_testData = data; +} + +void QtUiTestSensorBackend::forwardFallthroughReading() +{ + if (!m_fallThrough->reading()) + return; + + QVariant data; + QList<QVariant> parts; + int i; + switch (m_mode) { + case PassThrough: + case Record: + // copy sensor reading to reading + parts << m_fallThrough->reading()->timestamp(); + for (i = 0; i < m_fallThrough->reading()->valueCount(); ++i) + parts << m_fallThrough->reading()->value(i); + data = QVariant(parts); + setCurrentTestData(data); + if (m_mode == Record) { + // from above, + store the value + m_testData.append(data); + } + break; + case Generate: + break; + } +} + +void QtUiTestSensorBackend::setMode(const QByteArray &id, Mode mode) +{ + backendModes().insert(id, mode); + foreach (QtUiTestSensorBackend *backend, activeBackends()) { + if (backend->identity() == id) + backend->setMode(mode); + } +} + +QtUiTestSensorBackend::Mode QtUiTestSensorBackend::mode(const QByteArray &id) +{ + return backendModes().value(id, PassThrough); +} + +void QtUiTestSensorBackend::queueTestData(const QByteArray &id, const QList<QVariant> &data) +{ + foreach (QtUiTestSensorBackend *backend, activeBackends()) { + if (backend->identity() == id) + backend->queueTestData(data); + } +} + +QList<QVariant> QtUiTestSensorBackend::testData(const QByteArray &id) +{ + foreach (QtUiTestSensorBackend *backend, activeBackends()) { + if (backend->identity() == id) + return backend->testData(); + } + return QList<QVariant>(); +} + +QList<QtUiTestSensorBackend *> &QtUiTestSensorBackend::activeBackends() +{ + static QList<QtUiTestSensorBackend *> list; + return list; +} + +QMap<QByteArray, QtUiTestSensorBackend::Mode> &QtUiTestSensorBackend::backendModes() +{ + static QMap<QByteArray, Mode> map; + return map; +} + +const char * QAccelerometerGenerator::id("com.nokia.qtuitest.sensor.accelerometer"); + +QAccelerometerGenerator::QAccelerometerGenerator(QSensor *sensor, const QByteArray &fallThroughId) + : QtUiTestSensorBackend(sensor, identity(), fallThroughId) +{ + m_reading.setTimestamp(0); + m_reading.setX(0.0); + m_reading.setY(0.0); + m_reading.setZ(0.0); + setReading(&m_reading); +} + +QAccelerometerGenerator::~QAccelerometerGenerator() +{ +} + +void QAccelerometerGenerator::setCurrentTestData(const QVariant &value) +{ + QVariantList list = value.toList(); + if (list.count() == 4) { + m_reading.setTimestamp(list.at(0).value<quint64>()); + m_reading.setX(list.at(1).toReal()); + m_reading.setY(list.at(2).toReal()); + m_reading.setZ(list.at(3).toReal()); + newReadingAvailable(); + } else if (list.count() == 3) { + m_reading.setTimestamp(QDateTime::currentMSecsSinceEpoch()); + m_reading.setX(list.at(0).toReal()); + m_reading.setY(list.at(1).toReal()); + m_reading.setZ(list.at(2).toReal()); + newReadingAvailable(); + } +} + +const char * QOrientationGenerator::id("com.nokia.qtuitest.sensor.orientation"); + +QOrientationGenerator::QOrientationGenerator(QSensor *sensor, const QByteArray &fallThroughId) + : QtUiTestSensorBackend(sensor, identity(), fallThroughId) +{ + m_reading.setTimestamp(0); + m_reading.setOrientation(QOrientationReading::Undefined); + setReading(&m_reading); +} + +QOrientationGenerator::~QOrientationGenerator() +{ +} + +void QOrientationGenerator::setCurrentTestData(const QVariant &value) +{ + QVariantList list = value.toList(); + if (list.count() == 2) { + m_reading.setTimestamp(list.at(0).value<quint64>()); + m_reading.setOrientation(static_cast<QOrientationReading::Orientation>(list.at(1).toInt())); + newReadingAvailable(); + } else if (list.count() == 1) { + m_reading.setTimestamp(QDateTime::currentMSecsSinceEpoch()); + m_reading.setOrientation(static_cast<QOrientationReading::Orientation>(list.at(0).toInt())); + newReadingAvailable(); + } +} diff --git a/src/remote/slave/lib/qsensorgenerator_p.h b/src/remote/slave/lib/qsensorgenerator_p.h new file mode 100644 index 0000000..568bfe9 --- /dev/null +++ b/src/remote/slave/lib/qsensorgenerator_p.h @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QSENSORGENERATOR_P_H +#define QSENSORGENERATOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtUiTest API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGlobal> +#include <QtSystemTest/qstglobal.h> + +#include <QSensorBackend> +#include <QAccelerometerReading> +#include <QOrientationReading> +#include <QSensorBackendFactory> +#include <QList> + +class QTUITEST_EXPORT QtUiTestSensorBackend : public QSensorBackend +{ +Q_OBJECT +public: + QtUiTestSensorBackend(QSensor *sensor, const QByteArray &sensorId, const QByteArray &fallThroughId); + ~QtUiTestSensorBackend(); + + void start(); + void stop(); + + enum Mode { + PassThrough = 0, + Generate = 1, + Record = 2 + }; + + static void setMode(const QByteArray &id, Mode mode); + static Mode mode(const QByteArray &); + static void queueTestData(const QByteArray &, const QList<QVariant> &); + static QList<QVariant> testData(const QByteArray &); + + virtual QByteArray identity() const = 0; + +protected: + void timerEvent(QTimerEvent *); + + void setMode(Mode mode); + Mode mode() const { return m_mode; } + void queueTestData(const QList<QVariant> &); + QList<QVariant> testData() { return m_testData; } + + virtual void setCurrentTestData(const QVariant &) = 0; + +private slots: + void forwardFallthroughReading(); + +private: + int interval() const; + + QSensor *m_fallThrough; + QList<QVariant> m_testData; + Mode m_mode; + int m_timerId; + + static QList<QtUiTestSensorBackend *> &activeBackends(); + static QMap<QByteArray, Mode> &backendModes(); +}; + +class QTUITEST_EXPORT QAccelerometerGenerator : public QtUiTestSensorBackend +{ +Q_OBJECT +public: + QAccelerometerGenerator(QSensor *sensor, const QByteArray &fallThroughId = QByteArray()); + ~QAccelerometerGenerator(); + + QByteArray identity() const { return id; } + static const char *id; + +protected: + void setCurrentTestData(const QVariant &); + +private: + QAccelerometerReading m_reading; +}; + +class QTUITEST_EXPORT QOrientationGenerator : public QtUiTestSensorBackend +{ +Q_OBJECT +public: + QOrientationGenerator(QSensor *sensor, const QByteArray &fallThroughId = QByteArray()); + ~QOrientationGenerator(); + + QByteArray identity() const { return id; } + static const char *id; + +protected: + void setCurrentTestData(const QVariant &); + +private: + QOrientationReading m_reading; +}; + +class QTUITEST_EXPORT QSensorGeneratorFactory : public QSensorBackendFactory +{ +public: + QSensorGeneratorFactory() + {} + + void registerSensors() { + m_previousDefaultSensors.insert(QAccelerometer::type, + QSensor::defaultSensorForType(QAccelerometer::type)); + m_previousDefaultSensors.insert(QOrientationSensor::type, + QSensor::defaultSensorForType(QOrientationSensor::type)); + + QSensorManager::registerBackend(QAccelerometer::type, QAccelerometerGenerator::id, this); + QSensorManager::registerBackend(QOrientationSensor::type, QOrientationGenerator::id, this); + + QSensorManager::setDefaultBackend(QAccelerometer::type, QAccelerometerGenerator::id); + QSensorManager::setDefaultBackend(QOrientationSensor::type, QOrientationGenerator::id); + } + + QSensorBackend *createBackend(QSensor *sensor) + { + QByteArray wrapped = m_previousDefaultSensors.value(sensor->type(), QByteArray()); + if (sensor->identifier() == QAccelerometerGenerator::id) { + if (wrapped == QAccelerometerGenerator::id) + return 0; + return new QAccelerometerGenerator(sensor, wrapped); + } + if (sensor->identifier() == QOrientationGenerator::id) { + if (wrapped == QOrientationGenerator::id) + return 0; + return new QOrientationGenerator(sensor, wrapped); + } + return 0; + } +private: + QMap<QByteArray, QByteArray> m_previousDefaultSensors; +}; + +#endif // QSENSORGENERATOR_P_H + diff --git a/src/remote/slave/lib/qtestslave.cpp b/src/remote/slave/lib/qtestslave.cpp new file mode 100644 index 0000000..ccbd5ba --- /dev/null +++ b/src/remote/slave/lib/qtestslave.cpp @@ -0,0 +1,1678 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qtestslave.h> +#include <qtestwidgets.h> +#include <qtuitestnamespace.h> +#include <qtuitestconnectionmanager_p.h> + +#include <QImage> +#include <QCoreApplication> +#include <QVariant> +#include <QMetaProperty> +#include <QMetaObject> +#include <QMetaType> +#include <QPoint> +#include <QLocale> +#include <QtSystemTest/QstDebug> +#include <QElapsedTimer> +#include <QtGui/QPlatformIntegration> + +#include <QDir> +#include <QPluginLoader> + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + #include <private/qguiapplication_p.h> +// #include <qsensorgenerator_p.h> + #include <qplatforminputcontext_qpa.h> +#endif + +#ifdef QTUITEST_CPU_TICKS +# include <QtTest/private/cycle_p.h> +#endif + +#define qLog() if(1); else QtUiTest::debug() + +using namespace QtUiTest; + +class QtUiTestSignalReceiver : public QObject +{ +public: + QtUiTestSignalReceiver(QTestSlavePrivate* = 0); + + bool connectSignal(QObject *sender, const char *signal); + QVariantList argValues() const { return m_argValues; } + int qt_metacall(QMetaObject::Call call, int methodId, void **a); + virtual void signalReceived(); + +protected: + QTestSlavePrivate *m_slave; + QObject *m_sender; + QString m_signal; + bool m_received; + QList<int> m_args; + QVariantList m_argValues; +}; + +class QtUiTestSignalWaiter : public QtUiTestSignalReceiver +{ +public: + QtUiTestSignalWaiter(QTestSlavePrivate* = 0); + + bool setExpectedSignal(QObject *sender, const char *signal); + void clear(); + bool waitForSignal( int timeout = 10000 ); + virtual void signalReceived(); + int elapsed() const { return m_elapsed; } + +private: + QEventLoop m_eventLoop; + QTime m_time; + int m_elapsed; +}; + +typedef QPair<QObject*,QString> ReceiverKey; + +// Handler for test messages +class QTestSlavePrivate : public QObject +{ +Q_OBJECT +public: + QTestSlavePrivate(QTestSlave *parent) + : p(parent) + { + } + + QPoint mousePointForMessage(const QstMessage&); + QVariantList touchPointsForMessage(const QstMessage&); + + void signalReceived(QObject *sender, const QString &signal, const QVariantList &argValues); + + void resetBenchmarks(); + qint64 cpuTicks(); + + QTestSlave *p; + QtUiTestSignalWaiter m_signalWaiter; + QMap<ReceiverKey,QtUiTestSignalReceiver*> m_signalReceivers; + +#ifdef QTUITEST_CPU_TICKS + CycleCounterTicks startTicks; +#endif + +public slots: + QstMessage appName (const QstMessage&); + QstMessage isVisible (const QstMessage&); + QstMessage hasContents (const QstMessage&); + + QstMessage grabImage (const QstMessage&); + QstMessage window (const QstMessage&); + QstMessage getCenter (const QstMessage&); + QstMessage enterText (const QstMessage&); + QstMessage isHigher (const QstMessage&); + + QstMessage inputMethod (const QstMessage&); + + QstMessage activeWidgetInfo (const QstMessage&); + QstMessage getObjects (const QstMessage&); + + QstMessage applicationData (const QstMessage&); + QstMessage applicationWindows (const QstMessage&); + QstMessage windowProperty (const QstMessage&); + QstMessage invokeMethod (const QstMessage&); + QstMessage setProperty (const QstMessage&); + QstMessage getProperty (const QstMessage&); + QstMessage getProperties (const QstMessage&); + QstMessage queryProperties (const QstMessage&); + + QstMessage getGeometry (const QstMessage&); + + QstMessage keyPress (const QstMessage&); + QstMessage keyRelease (const QstMessage&); + QstMessage keyClick (const QstMessage&); + + QstMessage touchPress (const QstMessage&); + QstMessage touchUpdate (const QstMessage&); + QstMessage touchRelease (const QstMessage&); + + QstMessage mousePress (const QstMessage&); + QstMessage mouseRelease (const QstMessage&); + QstMessage mouseClick (const QstMessage&); + QstMessage mouseDoubleClick (const QstMessage&); + QstMessage mouseMove (const QstMessage&); + + QstMessage translate (const QstMessage&); + QstMessage trId (const QstMessage&); + QstMessage getLocale (const QstMessage&); + QstMessage setConfig (const QstMessage&); + QstMessage rescan (const QstMessage&); + QstMessage typeOf (const QstMessage&); + QstMessage inheritance (const QstMessage&); + QstMessage queuedMessage (const QstMessage&); + + QstMessage getMethods (const QstMessage&); + QstMessage expectSignal (const QstMessage&); + QstMessage waitForSignal (const QstMessage&); + + QstMessage connectSignal (const QstMessage&); + QstMessage disconnectSignal (const QstMessage&); + QstMessage cleanup (const QstMessage&); + +/* + QstMessage setSensorMode (const QstMessage&); + QstMessage getSensorMode (const QstMessage&); + QstMessage queueSensorValues (const QstMessage&); + QstMessage getSensorValues (const QstMessage&); +*/ +protected slots: + void disconnectAllSignals(QObject*); + +}; + +#include "qtestslave.moc" + +QTestSlave::QTestSlave() + : QstProtocol() + , d(new QTestSlavePrivate(this)) +{ + QTT_TRACE_FUNCTION(); + QtUiTest::testInputOption(QtUiTest::NoOptions); + refreshPlugins(); +} + +QTestSlave::~QTestSlave() +{ + QTT_TRACE_FUNCTION(); + delete d; + disconnect(); +} + +void QTestSlave::onConnected() +{ + QTT_TRACE_FUNCTION(); + QstProtocol::onConnected(); + QstMessage msg("APP_NAME"); + msg["appName"] = qApp->applicationName(); + msg["appVersion"] = qApp->applicationVersion(); + msg["qtVersion"] = QT_VERSION_STR; + postMessage( msg ); +} + +QtUiTestSignalReceiver::QtUiTestSignalReceiver(QTestSlavePrivate *slave) + : m_slave(slave) + , m_sender(0) + , m_received(false) +{ +} + +bool QtUiTestSignalReceiver::connectSignal(QObject *sender, const char *signal) +{ + m_sender = sender; + m_signal = QString(signal); + + const QMetaObject* const senderMo = sender->metaObject(); + static const int memberOffset = QObject::staticMetaObject.methodCount(); + + int signalIndex = senderMo->indexOfSignal(signal); + if (signalIndex < 0) { + signalIndex = senderMo->indexOfSignal(QMetaObject::normalizedSignature(signal)); + } + if (signalIndex < 0) { + return false; + } + + QMetaMethod method = senderMo->method(signalIndex); + QList<QByteArray> params = method.parameterTypes(); + for (int i = 0; i < params.count(); ++i) { + m_args << QMetaType::type(params.at(i).constData()); + } + + QtUiTestConnectionManager::instance()->connect(sender, signalIndex, this, memberOffset); + return true; +} + +int QtUiTestSignalReceiver::qt_metacall(QMetaObject::Call call, int methodId, void **a) +{ + methodId = QObject::qt_metacall(call, methodId, a); + if (methodId < 0) + return methodId; + + if (call == QMetaObject::InvokeMetaMethod) { + if (methodId == 0) { + m_argValues.clear(); + for (int i = 0; i < m_args.count(); ++i) { + QMetaType::Type type = static_cast<QMetaType::Type>(m_args.at(i)); + m_argValues << QVariant(type, a[i + 1]); + } + m_received = true; + signalReceived(); + + if (m_slave) { + m_slave->signalReceived(m_sender, m_signal, m_argValues); + } + } + --methodId; + } + return methodId; +} + +void QtUiTestSignalReceiver::signalReceived() +{ +} + +QtUiTestSignalWaiter::QtUiTestSignalWaiter(QTestSlavePrivate *slave) + : QtUiTestSignalReceiver(slave), m_elapsed(0) +{ +} + +bool QtUiTestSignalWaiter::setExpectedSignal(QObject *sender, const char *signal) +{ + clear(); + if (!connectSignal(sender, signal)) { + return false; + } + m_time.start(); + return true; +} + +void QtUiTestSignalWaiter::clear() +{ + if (m_sender) { + QtUiTestConnectionManager::instance()->disconnect(m_sender, -1, this, -1); + m_sender = 0; + } + m_received = false; + m_args.clear(); + m_argValues.clear(); + m_elapsed = 0; +} + +void QtUiTestSignalWaiter::signalReceived() +{ + m_elapsed = m_time.elapsed(); + + if (m_eventLoop.isRunning()) + m_eventLoop.quit(); +} + +bool QtUiTestSignalWaiter::waitForSignal(int timeout) +{ + if (m_received) + return true; + + QTimer timer; + timer.setInterval(timeout); + timer.setSingleShot(true); + QObject::connect(&timer, SIGNAL(timeout()), &m_eventLoop, SLOT(quit())); + timer.start(); + m_eventLoop.exec(); + + return m_received; +} + +QstMessage QTestSlavePrivate::grabImage(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QImage img; + + Widget *tw = 0; + if (!message["widgetSpecifier"].toString().isEmpty()) { + tw = findTestWidget<Widget>(message); + } + + if (!tw) { + if (QtUiTest::errorString().isEmpty()) { + setErrorString(QLatin1String("Widget not found")); + } + return reply; + } + + tw->grabImage(img); + reply["grabImage"] = img; + return reply; +} + +QstMessage QTestSlavePrivate::window(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + Widget *w = findTestWidget<Widget>(message); + qDebug() << "Finding window for " << w; + if (w) { + QObject *window = w->window(); + qDebug() << "window " << window; + if (window) { + QActiveTestWidget::instance()->registerTestWidget(window); + reply["window"] = QTestSlave::objectToMap(window); + } + } + + return reply; +} + +QstMessage QTestSlavePrivate::activeWidgetInfo(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; + QString error; + if (!QActiveTestWidget::instance()->rescan()) { + return reply; + } + + QString ret = QString("applicationIdentifier = '%1'\n\n").arg(QTestWidgets::windowProperty(QLatin1String("applicationIdentifier")).toString()); + ret += QActiveTestWidget::instance()->descendantTree(QTestWidgets::activeWidget()).join(QLatin1String("\n")); + + reply["activeWidgetInfo"] = ret; + return reply; +} + +QstMessage QTestSlavePrivate::getObjects(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + reply["getObjects"] = QActiveTestWidget::instance()->getObjects(message["widgetSpecifier"].toString()); + return reply; +} + +QstMessage QTestSlavePrivate::isVisible(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + Widget *w = findTestWidget<Widget>(message); + if (w) { + reply["isVisible"] = w->isVisible(); + } else { + reply["isVisible"] = false; + } + + return reply; +} + +QstMessage QTestSlavePrivate::hasContents(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QtUiTest::Object *w = findTestWidget<QtUiTest::Object>(message); + if (w) { + reply["hasContents"] = w->hasContents(); + } else { + reply["hasContents"] = false; + } + + return reply; +} + +QstMessage QTestSlavePrivate::getCenter(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + Widget *qw = findTestWidget<Widget>(message); + if (qw) { + QPoint pos = qw->center(); + reply["getCenter"] = QVariant::fromValue(pos); + } + + return reply; +} + +QstMessage QTestSlavePrivate::inputMethod(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + QObject *obj = qGuiApp->inputMethod(); + if (obj) { + QActiveTestWidget::instance()->registerTestWidget(obj); + reply["inputMethod"] = QTestSlave::objectToMap(obj); + } else { + QtUiTest::setErrorString("Could not find inputMethod"); + } +#else + QtUiTest::setErrorString("inputMethod() requires Qt 5"); +#endif + return reply; +} + +QstMessage QTestSlavePrivate::appName(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; + reply["appName"] = qApp->applicationName(); + return reply; +} + +QstMessage QTestSlavePrivate::applicationData(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; + QVariantMap appData; + appData["rootItem"] = QTestSlave::objectToMap(QTestWidgets::activeWidget()); + appData["appObject"] = QTestSlave::objectToMap(qApp); + appData["appId"] = QTestWidgets::windowProperty(QLatin1String("applicationIdentifier")); + appData["appName"] = qApp->applicationName(); + reply["applicationData"] = appData; + return reply; +} + +QstMessage QTestSlavePrivate::applicationWindows(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + QWindow *focusWindow = qApp->focusWindow(); + + QVariantList topLevel; + foreach (QWindow* window, qApp->topLevelWindows()) { + QActiveTestWidget::instance()->registerTestWidget(window); + topLevel << QTestSlave::objectToMap(window); + } + QVariantList allWindows; + foreach (QWindow* window, qApp->allWindows()) { + QActiveTestWidget::instance()->registerTestWidget(window); + allWindows << QTestSlave::objectToMap(window); + } + + QVariantMap windowData; + QActiveTestWidget::instance()->registerTestWidget(focusWindow); + windowData["focusWindow"] = QTestSlave::objectToMap(qApp->focusWindow()); + windowData["topLevelWindows"] = topLevel; + windowData["allWindows"] = allWindows; + reply["applicationWindows"] = windowData; +#endif + return reply; +} + +//FIXME: This should require a window to be specified, should be handled in +// window handler code +QstMessage QTestSlavePrivate::windowProperty(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; + QString property = message["property"].toString(); + QVariant value = QTestWidgets::windowProperty(property); + reply["windowProperty"] = value; + return reply; +} + +static QByteArray methodSignature(const QMetaMethod &method) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + return method.methodSignature(); +#else + return QByteArray::fromRawData(method.signature(), qstrlen(method.signature())); +#endif +} + +QstMessage QTestSlavePrivate::invokeMethod(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QObject *o; + QString error; + QstMessage reply; + if (!QActiveTestWidget::instance()->findWidget( message["widgetSpecifier"].toString(), o, error)) + return MESSAGE_ERROR(reply,error); + + QString method = message["method"].toString(); + bool returns = message["returns"].toBool(); + Qt::ConnectionType connType = (Qt::ConnectionType)message["conntype"].toInt(); + + method = QMetaObject::normalizedSignature(qPrintable(method)); + + QVariantList argList = message["args"].toList(); + + QMetaObject const *mo = o->metaObject(); + + int m = mo->indexOfMethod(QMetaObject::normalizedSignature(qPrintable(method))); + if (-1 == m) { + (void) MESSAGE_ERROR(reply, "ERROR_NO_METHOD"); + reply["warning"] = QString("method '%1' is not valid").arg(method); + return reply; + } + QMetaMethod mm = mo->method(m); + QList<QByteArray> paramTypes = mm.parameterTypes(); + QList<QByteArray> paramNames = mm.parameterNames(); + + if (paramTypes.count() != argList.count()) { + (void)MESSAGE_ERROR(reply, "ERROR_WRONG_ARG_COUNT"); + reply["warning"] = QString("method '%1' invoked with actual args %2, expected args %3") + .arg(QString::fromLatin1(methodSignature(mm))).arg(argList.count()).arg(paramTypes.count()); + return reply; + } + QString retType = mm.typeName(); + if (returns && retType.isEmpty()) { + (void)MESSAGE_ERROR(reply, "ERROR_NO_RETURN"); + reply["warning"] = QString("method '%1' does not return a value").arg(QString::fromLatin1(methodSignature(mm))); + return reply; + } + + QGenericArgument args[10]; + for (int index = 0;index < argList.count(); index++) { + int typeId = QMetaType::type(paramTypes[index]); + if (typeId != QMetaType::QVariant) { + if (argList[index].canConvert(static_cast<QVariant::Type>(typeId))) { + argList[index].convert(static_cast<QVariant::Type>(typeId)); + } else { + (void) MESSAGE_ERROR(reply, "ERROR_IN_INVOKE"); + reply["warning"] = QString("invalid parameter type for parameter %1 (was %2 but expected %3)") + .arg(index).arg(argList[index].typeName()).arg(qPrintable(paramTypes[index])); + return reply; + } + } + + args[index] = QGenericArgument(paramTypes[index].constData(), argList[index].constData()); + } + + QString methodName = method.left(method.indexOf('(')); + if (retType != QLatin1String("void")) { + QVariant returnValue; + int typeId = QMetaType::type(mm.typeName()); + + if (!typeId) { + (void) MESSAGE_ERROR(reply, "ERROR_IN_INVOKE"); + reply["warning"] = QString("could not look up type id for type %1)") + .arg(mm.typeName()); + return reply; + } else if (typeId != QMetaType::QVariant) { + returnValue = QVariant(typeId, (const void*)NULL); + } + + if (!mm.invoke(o, connType, + QGenericReturnArgument(mm.typeName(), returnValue.data()), args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9])) { + (void) MESSAGE_ERROR(reply, "ERROR_IN_INVOKE"); + reply["warning"] = QString("invoke of method '%1' with %2 args and a return type of '%3' failed") + .arg(method).arg(paramTypes.count()).arg(retType); + return reply; + } + reply["returns"] = returnValue; + } else { + if (!QMetaObject::invokeMethod(o, qPrintable(methodName), connType, + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9])) { + (void) MESSAGE_ERROR(reply, "ERROR_IN_INVOKE"); + reply["warning"] = QString("invoke of method '%1' with %2 args failed").arg(method).arg(paramTypes.count()); + return reply; + } + } + + return reply; +} + +QstMessage QTestSlavePrivate::setProperty(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QtUiTest::Object *w = findTestWidget<Object>(message); + if (w) { + QString property = message["property"].toString(); + QVariant value = message["value"]; + if (!w->setProperty(property, value) && QtUiTest::errorString().isEmpty()) { + // was a dynamic property created? + if (!w->getProperties().contains(property)) { + return MESSAGE_ERROR(reply, "ERROR_SETTING_PROPERTY"); + } + } + } + + return reply; +} + +QstMessage QTestSlavePrivate::getProperty(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QtUiTest::Object *w = findTestWidget<Object>(message); + if (w) { + QString property = message["property"].toString(); + QVariant value = QTestSlave::getObjectProperty(w, property); + reply["getProperty"] = value; + if (!value.isValid()) { + QtUiTest::setErrorString("Failed to retrieve property from object"); + } + } + + return reply; +} + +QVariant QTestSlave::getObjectProperty(QtUiTest::Object *w, const QString &property) +{ + QVariant value; + if (!w) { + QtUiTest::setErrorString(QString("Cannot retrieve property '%1' from null object").arg(property)); + return value; + } + value = w->getProperty(property); + if (!value.isValid()) { + QtUiTest::setErrorString(QString("Failed to retrieve property '%1' from object").arg(property)); + return value; + } + + return QTestSlave::updateVariant(value); +} + +QVariant QTestSlave::updateVariant(const QVariant &value) +{ + if (value.userType() == QMetaType::QObjectStar) { + if (QObject *obj = value.value<QObject*>()) { + QActiveTestWidget::instance()->registerTestWidget(obj); + return QTestSlave::objectToMap(obj); + } else { + return QLatin1String("<Null Object>"); + } + } else if (value.userType() == QVariant::List) { + QVariantList valueList; + foreach (const QVariant &item, value.toList()) { + valueList << QTestSlave::updateVariant(item); + } + return valueList; + } else if (value.type() == QVariant::Map) { + QVariantMap map = value.toMap(); + QVariantMap::iterator i; + for (i = map.begin(); i != map.end(); ++i) { + i.value() = QTestSlave::updateVariant(i.value()); + } + return map; + } else if ((int)value.type() == QMetaType::QVariant) { + return QTestSlave::updateVariant(value.value<QVariant>()); + } else if ((value.type() == QVariant::Hash) + || (value.type() == QVariant::UserType) + || (value.type() == QMetaType::VoidStar)) { + return QString("<%1>").arg(value.typeName()); + } + + return value; +} + +QVariantMap QTestSlave::objectToMap(const QObject *obj, const QStringList &properties) +{ + QVariantMap map; + map["_signature_"] = QTestWidgets::signature(obj); + QtUiTest::Object *qw = qtuitest_cast<Object*>(obj); + if (qw) { + map["_type_"] = qw->typeOf(); + if (!properties.isEmpty()) { + QVariantMap prefetch; + foreach (const QString &property, properties) { + QVariant value = QTestSlave::getObjectProperty(qw, property); + prefetch[property] = value; + } + map["_prefetch_"] = prefetch; + } + } + return map; +} + +QstMessage QTestSlavePrivate::getProperties(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QtUiTest::Object *w = findTestWidget<Object>(message); + + if (!w) { + QtUiTest::setErrorString(QLatin1String("Unable to find specified widget")); + return reply; + } + + QVariantMap map = w->getProperties(); + if (map.isEmpty()) { + QtUiTest::setErrorString(QLatin1String("Failed to retrieve properties from object")); + } + + foreach (const QString &key, map.keys()) { + map[key] = QTestSlave::updateVariant(map[key]); + } + + reply[QLatin1String("getProperties")] = map; + return reply; +} + +QstMessage QTestSlavePrivate::queryProperties(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QString error; + + QVariantMap searchValues = message["searchvalues"].toMap(); + if ( searchValues.isEmpty() ) { + QtUiTest::setErrorString(QLatin1String("ERROR_MISSING_PARAMETERS")); + return reply; + } + + int flags = message["flags"].toInt(); + QObjectList ol = QActiveTestWidget::instance()->queryProperties( searchValues, static_cast<QtUiTest::QueryFlags>(flags) ); + + if (!QtUiTest::errorString().isEmpty()) + return reply; + + if (!(flags & QtUiTest::NoSort)) { + // Sort the list by widget position + qStableSort(ol.begin(), ol.end(), QTestWidgets::lessThan); + } + + QStringList properties = message["properties"].toStringList(); + QVariantList matches; + foreach (QObject *o, ol) { + QActiveTestWidget::instance()->registerTestWidget(o); + matches << QTestSlave::objectToMap(o, properties); + } + + reply["queryProperties"] = matches; + return reply; +} + +QstMessage QTestSlavePrivate::getGeometry(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + Widget *w = findTestWidget<Widget>(message); + if (w) { + QRect ret = w->geometry(); + reply["getGeometry"] = ret; + } + + return reply; +} + +void QTestSlavePrivate::resetBenchmarks() +{ +#ifdef QTUITEST_CPU_TICKS + startTicks = getticks(); +#endif +} + +qint64 QTestSlavePrivate::cpuTicks() +{ +#ifdef QTUITEST_CPU_TICKS + CycleCounterTicks now = getticks(); + return qRound64(elapsed(now, startTicks)); +#else + return -1; +#endif +} + +Q_DECLARE_METATYPE(QVariant); + +void QTestSlave::processMessage( QstMessage *msg ) +{ + QTT_TRACE_FUNCTION(); + QtUiTest::setErrorString(QString()); + QstMessage reply = constructReplyToMessage(*msg); + if (reply.state() != QstMessage::MessageEmpty) { + replyMessage(msg, reply); + } +} + +void QTestSlave::registerHandler(QtUiTest::MessageHandler *handler) +{ + m_messageHandlers[handler->handlerName()] = handler; + qDebug() << "registered handler " << handler->handlerName() << handler; +} + +void QTestSlave::refreshPlugins() +{ + QTT_TRACE_FUNCTION(); + + QSet<QString> pluginsToLoad; + QList<QDir> pluginDirs; + + const QString pluginType("qtuitest"); + QSet<QString> libPaths = QCoreApplication::libraryPaths().toSet(); + + foreach (const QString& libPath, libPaths) { + QDir dir(libPath + "/" + pluginType); + if (!dir.exists()) { + continue; + } + pluginDirs << dir; + } + + foreach (QDir const& dir, pluginDirs) { + foreach (const QString& file, dir.entryList(QDir::Files|QDir::NoDotAndDotDot)) { + QString filename = dir.canonicalPath() + "/" + file; + if (!QLibrary::isLibrary(filename)) continue; + pluginsToLoad << filename; + } + } + QPluginLoader pluginLoader; + QSet<QString> lastPluginsToLoad; + QStringList errors; + + // dumb dependency handling: keep trying to load plugins until we + // definitely can't progress. + while (lastPluginsToLoad != pluginsToLoad) { + lastPluginsToLoad = pluginsToLoad; + errors.clear(); + foreach (const QString& plugin, pluginsToLoad) { + pluginLoader.setFileName(plugin); + // enable RTLD_GLOBAL, so plugins can access each other's symbols. + pluginLoader.setLoadHints(QLibrary::ExportExternalSymbolsHint); + pluginLoader.load(); + + QObject *instance = pluginLoader.instance(); + QString error; + if (!instance) + error = "cannot resolve 'qt_plugin_instance': " + pluginLoader.errorString(); + + QtUiTest::MessageHandler *handler = qobject_cast<QtUiTest::MessageHandler*>(instance); + if (!handler) { + if (error.isEmpty()) error = pluginLoader.errorString(); + QString formattedError; + QDebug(&formattedError) + << "QtUitest: failed to load qtuitest widgets plugin" + << "\n plugin" << plugin + << "\n instance" << instance + << "\n error" << error; + errors << formattedError; + } else { + pluginsToLoad -= plugin; + registerHandler(handler); + } + } + } + + foreach (const QString& error, errors) + qWarning() << qPrintable(error); +} + +QstMessage QTestSlave::constructReplyToMessage( const QstMessage &_msg ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QstMessage msg(_msg); + +// TO HANDLE A NEW SYSTEM TEST EVENT: +// implement a function with signature: +// QstMessage QTestSlavePrivate::eventName(const QstMessage &message) + + QString event = msg.event(); + int pos = event.lastIndexOf(QChar('/')); + if (pos != -1) { + QtUiTest::MessageHandler *handler = m_messageHandlers[event.left(pos)]; + if (handler) { + msg.setEvent(event.mid(pos+1)); + reply = handler->handleMessage(msg); + } + // TODO: Ensure correct plugin is loaded + // and call constructReplyToMessage there (handleMessage?) + } else { + d->resetBenchmarks(); + if (!QMetaObject::invokeMethod(d, msg.event().toLatin1().constData(), Qt::DirectConnection, + Q_RETURN_ARG(QstMessage, reply), + Q_ARG(QstMessage, msg))) { + (void)MESSAGE_ERROR(reply, "ERROR: Unhandled event '" + msg.event() + "'"); + } + +#ifdef QTUITEST_CPU_TICKS + reply["cpuTicks"] = d->cpuTicks(); +#endif + } + + if (!QtUiTest::debugOutput().isEmpty()) { + reply["debug"] = QtUiTest::debugOutput();\ + } + + if (!QtUiTest::errorString().isEmpty()) { + reply.setState(QstMessage::MessageError); + return MESSAGE_ERROR(reply, QtUiTest::errorString()); + } + + if (reply.state() == QstMessage::MessageEmpty) { + reply.setState(QstMessage::MessageSuccess); + } + return reply; +} + +/* + Return true if first item is higher than second item, based on z-order. + This does not mean that the higher item obscures the other, as they may + not be overlapping, or the higher item may be transparent. + + See http://doc.qt.nokia.com/qt5-snapshot/qml-qtquick2-item.html#z-prop + + * Find nearestCommonAncestor (common ancestor closest to both items) + + Neither item is ancestor of other ¦ One item is ancestor of another + ¦ + root ¦ root + +-- ... ¦ +-- ... + +-- nearestCommonAncestor ¦ +-- o1 == keyAncestor1 * + +-- ... ¦ +-- keyAncestor2 + +-- keyAncestor1 ¦ +-- ... + ¦ +-- ... ¦ +-- o2 + ¦ +-- o1 ¦ + +-- keyAncestor2 ¦ * nearestCommonAncestor == o1 + +-- ... ¦ + +-- o2 ¦ + + * There should always be at least one common ancestor + * The nearestCommonAncestor may be o1 or o2 (if one item is an ancestor + of the other). If nearestCommonAncestor == o1 then keyAncestor1 == o1, + (and similarly for o2) + * z1 is keyAncestor1's z property, z2 == keyAncestor2's z property + * If neither item is an ancestor of the other, then keyAncestors will be + siblings. Their z values (z1 and z2) are compared: + (z1 > z2) --> o1 is above o2 (return true) + (z1 < z2) --> o2 is above o1 (return false) + If (z1 == z2), use the position of each keyAncestor in the + nearestCommonAncestor's child list (later sibling is above the earlier) + * If o1 is an ancestor of o2, then o2 will be above o1 UNLESS z2 is negative + * If o2 is an ancestor of o1, then o1 will be above o2 UNLESS z1 is negative + +*/ +QstMessage QTestSlavePrivate::isHigher( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QString error; + + QString sig1 = message["widgetSpecifier"].toString(); + QObject *o1; + if (!QActiveTestWidget::instance()->findWidget( sig1, o1, error)) { + return reply; + } + QtUiTest::Object *w1 = qtuitest_cast<QtUiTest::Object*>(o1); + + QString sig2 = message["otherwidget"].toString(); + QObject *o2; + if (!QActiveTestWidget::instance()->findWidget( sig2, o2, error)) { + return reply; + } + QtUiTest::Object *w2 = qtuitest_cast<QtUiTest::Object*>(o2); + + if (!(w1 && w2)) { + if (!QtUiTest::errorString().isEmpty()) + return reply; + QtUiTest::setErrorString(QLatin1String("Widget not found")); + return reply; + } + + QObjectList ancestors1 = w1->ancestors(); + QObjectList ancestors2 = w2->ancestors(); + ancestors1.prepend(o1); + ancestors2.prepend(o2); + + QObject *nearestCommonAncestor = 0; + QObject *keyAncestor1 = 0; + QObject *keyAncestor2 = 0; + int al1 = ancestors1.length(); + int al2 = ancestors2.length(); + int alength = ((al1 > al2) ? al2 : al1); + + // Work from end of list (root item) to start (the item) + for (int i=0; i< alength; i++) { + QObject *a1 = ancestors1.takeLast(); + QObject *a2 = ancestors2.takeLast(); + if (a1 == a2) { + nearestCommonAncestor = a1; + } else { + keyAncestor1 = a1; + keyAncestor2 = a2; + break; + } + } + if (keyAncestor1 == 0) { + if (ancestors1.isEmpty()) { + keyAncestor1 = o1; + } else { + keyAncestor1 = ancestors1.takeLast(); + } + } + if (keyAncestor2 == 0) { + if (ancestors2.isEmpty()) { + keyAncestor2 = o2; + } else { + keyAncestor2 = ancestors2.takeLast(); + } + } + if (nearestCommonAncestor == 0) { + // no common ancestor, this should not be possible + reply["ishigher"] = false; + QtUiTest::setErrorString(QLatin1String("Cannot find a common ancestor item")); + return reply; + } + + bool ok; + double z1 = keyAncestor1->property("z").toDouble(&ok); + if (!ok) { + z1 = 0; + } + + double z2 = keyAncestor2->property("z").toDouble(&ok); + if (!ok) { + z2 = 0; + } + + QtUiTest::Object *nca = qtuitest_cast<QtUiTest::Object*>(nearestCommonAncestor); + bool ret = false; + if (nearestCommonAncestor == keyAncestor1) { + // first item is ancestor of second item, so can only be + // above it if z2 < 0 + ret = (z2 < 0); + } else if (nearestCommonAncestor == keyAncestor2) { + // second item is ancestor of first item + ret = (z1 >= 0); + } else if (z1 > z2) { + ret = true; + } else if (z1 == z2) { + // The z values are equal, so which item is on top depends + // on the position in list of children + QObjectList ncaChildren = nca->children(); + ret = (ncaChildren.indexOf(keyAncestor1) > ncaChildren.indexOf(keyAncestor2)); + } + + reply["isHigher"] = ret; + return reply; +} + +QstMessage QTestSlavePrivate::enterText(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + if (!message["text"].isValid()) { + return MESSAGE_ERROR(reply, "ERROR_MISSING_PARAMETERS"); + } + QString text = message["text"].toString(); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + QPlatformInputContext *ic = QGuiApplicationPrivate::platformIntegration()->inputContext(); + foreach (const QChar& c, text) { + Qt::KeyboardModifiers modifiers = asciiToModifiers(c.toLatin1()); + QKeyEvent pressEvent(QEvent::KeyPress, c.unicode(), modifiers, QString(c), false, 1); + QKeyEvent releaseEvent(QEvent::KeyRelease, c.unicode(), modifiers, QString(c), false, 1); + QMetaObject::invokeMethod(ic, "sendKeyEvent", Qt::DirectConnection, Q_ARG(QKeyEvent*, &pressEvent)); + QMetaObject::invokeMethod(ic, "sendKeyEvent", Qt::DirectConnection, Q_ARG(QKeyEvent*, &releaseEvent)); + } +#endif + return reply; +} + +QstMessage QTestSlavePrivate::keyPress(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + if (!message["key"].isValid()) { + return MESSAGE_ERROR(reply, "ERROR_MISSING_KEY"); + } + + Qt::Key key = QtUiTest::variantToKey(message["key"]); + + if (!key) return MESSAGE_ERROR(reply, "ERROR_ZERO_KEY"); + + QtUiTest::keyPress(key); + + if (message["duration"].isValid()) { + int duration = message["duration"].toInt(); + if (duration >= 500) { + QtUiTest::wait(500); + duration -= 500; + bool keyRepeat=QtUiTest::testInputOption(QtUiTest::KeyRepeat); + QtUiTest::setInputOption(QtUiTest::KeyRepeat, true); + QtUiTest::keyPress(key); + while (duration > 0) { + QtUiTest::wait(150); + duration -= 150; + QtUiTest::keyPress(key); + } + QtUiTest::setInputOption(QtUiTest::KeyRepeat, keyRepeat); + } else { + QtUiTest::wait(duration); + } + } + + return reply; +} + +QstMessage QTestSlavePrivate::keyRelease(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + if (!message["key"].isValid()) { + return MESSAGE_ERROR(reply, "ERROR_MISSING_KEY"); + } + + Qt::Key key = QtUiTest::variantToKey(message["key"]); + + if (!key) return MESSAGE_ERROR(reply, "ERROR_ZERO_KEY"); + QtUiTest::keyRelease(key); + return reply; +} + +QstMessage QTestSlavePrivate::keyClick(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + if (!message["key"].isValid()) { + return MESSAGE_ERROR(reply, "ERROR_MISSING_KEY"); + } + + Qt::Key key = QtUiTest::variantToKey(message["key"]); + + if (!key) return MESSAGE_ERROR(reply, "ERROR_ZERO_KEY"); + QtUiTest::keyClick(key); + return reply; +} + +QstMessage QTestSlavePrivate::touchPress(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + + QVariantList points(touchPointsForMessage(message)); + if (!QtUiTest::errorString().isEmpty()) + return reply; + + QtUiTest::touchPress(points); + return reply; +} + +QstMessage QTestSlavePrivate::touchUpdate(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + + QVariantList points(touchPointsForMessage(message)); + if (!QtUiTest::errorString().isEmpty()) + return reply; + + QtUiTest::touchUpdate(points); + return reply; +} + +QstMessage QTestSlavePrivate::touchRelease(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + + QVariantList points(touchPointsForMessage(message)); + if (!QtUiTest::errorString().isEmpty()) + return reply; + + QtUiTest::touchRelease(points); + return reply; +} + + +QstMessage QTestSlavePrivate::mousePress(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + bool ok; + Qt::MouseButtons buttons = (Qt::MouseButtons)(message["buttons"].toInt(&ok)); + if (!ok) buttons = Qt::LeftButton; + + QPoint pos(mousePointForMessage(message)); + if (!QtUiTest::errorString().isEmpty()) + return reply; + + QtUiTest::mousePress(pos, buttons); + return reply; +} + +QstMessage QTestSlavePrivate::mouseRelease(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + bool ok; + Qt::MouseButtons buttons = (Qt::MouseButtons)(message["buttons"].toInt(&ok)); + if (!ok) buttons = Qt::LeftButton; + + QPoint pos(mousePointForMessage(message)); + if (!QtUiTest::errorString().isEmpty()) + return reply; + + QtUiTest::mouseRelease(pos, buttons); + return reply; +} + +QstMessage QTestSlavePrivate::mouseClick(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + bool ok; + Qt::MouseButtons buttons = (Qt::MouseButtons)(message["buttons"].toInt(&ok)); + if (!ok) buttons = Qt::LeftButton; + + QPoint pos(mousePointForMessage(message)); + if (!QtUiTest::errorString().isEmpty()) + return reply; + + QtUiTest::mouseClick(pos, buttons); + return reply; +} + +QstMessage QTestSlavePrivate::mouseDoubleClick(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + bool ok; + Qt::MouseButtons buttons = (Qt::MouseButtons)(message["buttons"].toInt(&ok)); + if (!ok) buttons = Qt::LeftButton; + + QPoint pos(mousePointForMessage(message)); + if (!QtUiTest::errorString().isEmpty()) + return reply; + + QtUiTest::mouseDClick(pos, buttons); + return reply; +} + +QstMessage QTestSlavePrivate::mouseMove(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QPoint pos(mousePointForMessage(message)); + + if (!QtUiTest::errorString().isEmpty()) + return reply; + + QtUiTest::mouseMove(pos); + return reply; +} + +QVariantList QTestSlavePrivate::touchPointsForMessage(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + if (message["points"].isValid()) + return message["points"].toList(); + + QVariantList ret; + Widget *w = findTestWidget<Widget>(message); + if (w) + ret += w->geometry().center(); + + return ret; +} + +QPoint QTestSlavePrivate::mousePointForMessage(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + if (message["pos"].isValid()) + return message["pos"].value<QPoint>(); + + QPoint ret; + Widget *w = findTestWidget<Widget>(message); + if (w) { + ret = w->geometry().center(); + } + + return ret; +} + +QstMessage QTestSlavePrivate::translate( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QByteArray context = message["context"].toString().toLatin1(); + QByteArray text = message["text"].toString().toLatin1(); + QByteArray comment = message["comment"].toString().toLatin1(); + int n = message["number"].toInt(); + reply["translate"] = QCoreApplication::translate(context, text, comment, QCoreApplication::CodecForTr, n); + return reply; +} + +QstMessage QTestSlavePrivate::trId( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QByteArray id = message["id"].toString().toLatin1(); + int n = message["number"].toInt(); + reply["trId"] = qtTrId(id, n); + return reply; +} + +QstMessage QTestSlavePrivate::getLocale( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; + reply["getLocale"] = QLocale::system(); + return reply; +} + +QstMessage QTestSlavePrivate::setConfig(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; + if (message["autoScan"].isValid()) { + QActiveTestWidget::instance()->setAutoScan(message["autoScan"].toBool()); + } + + return reply; +} + +QstMessage QTestSlavePrivate::rescan(const QstMessage &message) +{ + QTT_TRACE_FUNCTION(); + Q_UNUSED(message); + QstMessage reply; + QString error; + QActiveTestWidget::instance()->forceRescan(); + return reply; +} + +QstMessage QTestSlavePrivate::typeOf( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QtUiTest::Object *w = findTestWidget<QtUiTest::Object>(message); + if (w) { + reply["typeOf"] = w->typeOf(); + } + return reply; +} + +QstMessage QTestSlavePrivate::inheritance( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + QtUiTest::Object *w = findTestWidget<QtUiTest::Object>(message); + if (w) { + reply["inheritance"] = w->inheritance(); + } + return reply; +} + +QstMessage QTestSlavePrivate::queuedMessage( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + bool ok; + int count = message["count"].toInt(&ok); + if (ok) { + for (int i=0; i<count; i++) { + QString event = message[QString("event_%1").arg(i)].toString(); + QVariantMap map = message[QString("map_%1").arg(i)].toMap(); + if (event == "wait") { + QtUiTest::wait(map["delay"].toInt()); + } else { + QstMessage msg(event, map); + QstMessage reply = p->constructReplyToMessage(msg); + if (reply.state() != QstMessage::MessageSuccess) { + return reply; + } + } + } + } + + return reply; +} + +QstMessage QTestSlavePrivate::getMethods(const QstMessage &message) +{ + QObject *o; + QString error; + QstMessage reply; + if (!QActiveTestWidget::instance()->findWidget( message["widgetSpecifier"].toString(), o, error)) + return MESSAGE_ERROR(reply, error); + + QMetaObject const *mo = o->metaObject(); + int count = mo->methodCount(); + QVariantList methods; + for (int i=0; i<count; i++) { + QMetaMethod mm = mo->method(i); + QVariantMap methodMap; + methodMap["signature"] = methodSignature(mm); + methodMap["methodType"] = mm.methodType(); + QStringList paramNames; + foreach (const QByteArray ¶m, mm.parameterNames()) { + paramNames << param; + } + if (!paramNames.isEmpty()) { + methodMap["paramNames"] = paramNames; + } + QStringList paramTypes; + foreach (const QByteArray ¶mType, mm.parameterTypes()) { + paramTypes << paramType; + } + if (!paramTypes.isEmpty()) { + methodMap["paramTypes"] = paramTypes; + } + QString typeName(mm.typeName()); + if (!typeName.isEmpty()) { + methodMap["returnType"] = typeName; + } + methods << methodMap; + } + + reply[QLatin1String("getMethods")] = methods; + return reply; +} + +QstMessage QTestSlavePrivate::expectSignal( const QstMessage &message ) +{ + QstMessage reply; + QString error; + + QString object = message["widgetSpecifier"].toString(); + QString signal = message["signal"].toString(); + if (object.isEmpty() || signal.isEmpty()) { + return MESSAGE_ERROR(reply, "ERROR_MISSING_PARAMETERS"); + } + + QObject *o; + if (!QActiveTestWidget::instance()->findWidget(object, o, error)) + return MESSAGE_ERROR(reply, error); + QMetaObject const *mo = o->metaObject(); + int m = mo->indexOfMethod(QMetaObject::normalizedSignature(qPrintable(signal))); + QMetaMethod mm = mo->method(m); + if (mm.methodType() != QMetaMethod::Signal) { + return MESSAGE_ERROR(reply, "Method is not a signal"); + } + + if (!m_signalWaiter.setExpectedSignal(o, signal.toLatin1())) { + return MESSAGE_ERROR(reply, "Unable to connect signal"); + } + + return reply; +} + +QstMessage QTestSlavePrivate::waitForSignal( const QstMessage &message ) +{ + QstMessage reply; + QString error; + + int timeout = message["timeout"].toInt(); + bool received = m_signalWaiter.waitForSignal(timeout); + + if (!received) { + return MESSAGE_ERROR(reply, "Signal not received"); + } + + reply["args"] = QTestSlave::updateVariant(m_signalWaiter.argValues()); + reply["elapsed"] = m_signalWaiter.elapsed(); + return reply; +} + +QstMessage QTestSlavePrivate::connectSignal( const QstMessage &message ) +{ + QstMessage reply; + QString error; + + QString object = message["widgetSpecifier"].toString(); + QString signal = message["signal"].toString(); + if (object.isEmpty() || signal.isEmpty()) { + return MESSAGE_ERROR(reply, "ERROR_MISSING_PARAMETERS"); + } + + QObject *o; + if (!QActiveTestWidget::instance()->findWidget(object, o, error)) + return MESSAGE_ERROR(reply, error); + QMetaObject const *mo = o->metaObject(); + int m = mo->indexOfMethod(QMetaObject::normalizedSignature(qPrintable(signal))); + QMetaMethod mm = mo->method(m); + if (mm.methodType() != QMetaMethod::Signal) { + return MESSAGE_ERROR(reply, "Method is not a signal"); + } + + ReceiverKey key(o, signal); + if (m_signalReceivers.contains(key)) { + // Already connected to this signal + return reply; + } + QtUiTestSignalReceiver* signalReceiver = new QtUiTestSignalReceiver(this); + m_signalReceivers[key] = signalReceiver; + + if (!signalReceiver->connectSignal(o, signal.toLatin1())) { + delete signalReceiver; + return MESSAGE_ERROR(reply, "Unable to connect signal"); + } + + connect(o, SIGNAL(destroyed(QObject*)), this, SLOT(disconnectAllSignals(QObject*)), Qt::DirectConnection); + return reply; +} + +QstMessage QTestSlavePrivate::disconnectSignal( const QstMessage &message ) +{ + QstMessage reply; + QString error; + + QString object = message["widgetSpecifier"].toString(); + QString signal = message["signal"].toString(); + if (object.isEmpty()) { + return MESSAGE_ERROR(reply, "ERROR_MISSING_PARAMETERS"); + } + + QObject *o; + if (!QActiveTestWidget::instance()->findWidget(object, o, error)) + return MESSAGE_ERROR(reply, error); + + if (signal.isEmpty()) { + disconnectAllSignals(o); + return reply; + } + + ReceiverKey key(o, signal); + if (!m_signalReceivers.contains(key)) { + return MESSAGE_ERROR(reply, "Not connected to signal"); + } + + delete m_signalReceivers[key]; + m_signalReceivers.remove(key); + return reply; +} + +void QTestSlavePrivate::disconnectAllSignals(QObject *o) +{ + foreach (ReceiverKey key, m_signalReceivers.keys()) { + if (key.first == o) { + delete m_signalReceivers[key]; + m_signalReceivers.remove(key); + } + } +} + +QstMessage QTestSlavePrivate::cleanup( const QstMessage &message ) +{ + Q_UNUSED(message); + + foreach (QtUiTestSignalReceiver *receiver, m_signalReceivers.values()) { + delete receiver; + } + m_signalReceivers.clear(); + QstMessage reply; + return reply; +} + +void QTestSlavePrivate::signalReceived(QObject *sender, const QString &signal, const QVariantList &argValues) +{ + QstMessage msg("SIGNAL_RECEIVED"); + msg["signal"] = signal; + msg["sender"] = QTestSlave::updateVariant(QVariant::fromValue(sender)); + msg["args"] = QTestSlave::updateVariant(argValues); + p->postMessage( msg ); +} + +/* +QstMessage QTestSlavePrivate::setSensorMode( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + + QByteArray sensorId = message["sensorId"].toByteArray(); + QtUiTestSensorBackend::Mode mode = (QtUiTestSensorBackend::Mode)message["sensorMode"].toInt(); + + QtUiTestSensorBackend::setMode(sensorId, mode); + + return reply; +} + +QstMessage QTestSlavePrivate::getSensorMode( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + + QByteArray sensorId = message["sensorId"].toByteArray(); + QtUiTestSensorBackend::Mode mode = QtUiTestSensorBackend::mode(sensorId); + reply["sensorMode"] = (int)mode; + + return reply; +} + +QstMessage QTestSlavePrivate::queueSensorValues( const QstMessage &message ) +{ + QTT_TRACE_FUNCTION(); + QstMessage reply; + + QByteArray sensorId = message["sensorId"].toByteArray(); + QList<QVariant> values = message["sensorValues"].toList(); + + QtUiTestSensorBackend::queueTestData(sensorId, values); + + return reply; +} + +QstMessage QTestSlavePrivate::getSensorValues( const QstMessage &message ) +{ + QstMessage reply; + + QByteArray sensorId = message["sensorId"].toByteArray(); + + reply["values"] = QVariant(QtUiTestSensorBackend::testData(sensorId)); + + return reply; +} +*/ diff --git a/src/remote/slave/lib/qtestslave.h b/src/remote/slave/lib/qtestslave.h new file mode 100644 index 0000000..2f245fe --- /dev/null +++ b/src/remote/slave/lib/qtestslave.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTESTSLAVE_H +#define QTESTSLAVE_H + +#include "qtestwidgets.h" +#include "qtuitestmessagehandler.h" + +#include <QtSystemTest/QstProtocol> + +class QTestSlavePrivate; + +class QTSLAVE_EXPORT QTestSlave : public QstProtocol +{ + Q_OBJECT +public: + QTestSlave(); + virtual ~QTestSlave(); + + virtual void processMessage(QstMessage*); + virtual QstMessage constructReplyToMessage(const QstMessage&); + + static QVariant getObjectProperty(QtUiTest::Object *w, const QString &property); + static QVariant updateVariant(const QVariant &value); + static QVariantMap objectToMap(const QObject *obj, const QStringList& = QStringList()); + +public slots: + virtual void onConnected(); + +protected: + void registerHandler(QtUiTest::MessageHandler *handler); + void refreshPlugins(); + +private: + QTestSlavePrivate *d; + QMap<QString,QtUiTest::MessageHandler*> m_messageHandlers; +}; + +template <typename T> +T* findTestWidget(const QstMessage& message) +{ + using namespace QtUiTest; + T* ret = 0; + QstMessage reply; + QString error; + QString qp = message["widgetSpecifier"].toString(); + QObject *o; + if (!QActiveTestWidget::instance()->findWidget( qp, o, error)) { + setErrorString(error); + return ret; + } + + ret = qtuitest_cast<T*>(o); + if (!ret) { + setErrorString(QString("Error: %1 is not of type %2").arg(qp).arg(static_cast<T*>(0)->_q_interfaceName())); + } else { + setErrorString(QString()); + } + + return ret; +} + +#endif diff --git a/src/remote/slave/lib/qtestwidgets.cpp b/src/remote/slave/lib/qtestwidgets.cpp new file mode 100644 index 0000000..f2e9077 --- /dev/null +++ b/src/remote/slave/lib/qtestwidgets.cpp @@ -0,0 +1,623 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qtestwidgets.h> +#include <QtSystemTest/QstDebug> +#include <QRect> + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + #include <QGuiApplication> + #include <QWindow> +#else + #include <QApplication> + #include <QWidget> +#endif + +#include <QPlatformNativeInterface> + +#define qLog() if (1); else QtUiTest::debug() + +uint qHash(QPointer<QObject> o) +{ return qHash((QObject*)o); } + +/*! + Returns a unique string identifier for \a object. +*/ +QString QTestWidgets::signature( const QObject *o ) +{ + if (!o) { + return QLatin1String("ERROR_NO_OBJECT"); + } + QString ret = QActiveTestWidget::instance()->signature(o); + if (!ret.isEmpty()) { + return ret; + } + + QtUiTest::Object* w = qtuitest_cast<QtUiTest::Object*>(o); + QString typeName; + if (w) { + typeName = w->typeOf(); + } else { + typeName = o->metaObject()->className(); + } + + return QString("%1[%2]").arg(typeName).arg((long)(void*)o,0,32).replace(QLatin1Char(' '), QLatin1Char('_')); +} + +/*! + Returns the testWidget that is associated with the given \a signature. +*/ +QObject *QTestWidgets::testWidget( const QString &signature ) +{ + QTT_TRACE_FUNCTION(); + return QActiveTestWidget::instance()->testWidget(signature); +} + +QObject *QActiveTestWidget::testWidget( const QString &signature ) +{ + QTT_TRACE_FUNCTION(); + QObject *rec = d->testWidgetsBySignature.value( signature, 0 ); + return rec; +} + +QString QActiveTestWidget::signature( const QObject *o ) const +{ + return d->signaturesByObject.value(o); +} + +void QActiveTestWidget::registerTestWidget( QObject *ao ) +{ + QTT_TRACE_FUNCTION(); + QString new_signature = QTestWidgets::signature( ao ); + if (d->testWidgetsBySignature.contains(new_signature)) { + return; + } + d->testWidgetsBySignature[new_signature] = ao; + d->signaturesByObject[ao] = new_signature; + connect( ao, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)), Qt::DirectConnection ); +} + +void QActiveTestWidget::onDestroyed(QObject *o) +{ + QTT_TRACE_FUNCTION(); + if (o) { + d->removeTestWidget(o); + } +} + +QVariant QTestWidgets::windowProperty(const QString &property) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + QTT_TRACE_FUNCTION(); + QWindow *rootWindow = qobject_cast<QWindow*>(activeWidget()); + if (qGuiApp && rootWindow && qGuiApp->platformNativeInterface() && rootWindow->handle()) { + return qGuiApp->platformNativeInterface()->windowProperty(rootWindow->handle(), property); + } +#endif + return QVariant(); +} + +/*! + Returns the current activeWindow, activePopupWidget or activeModalWidget. +*/ +QObject* QTestWidgets::activeWidget() +{ + QTT_TRACE_FUNCTION(); + QObject *w = 0; + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + w = qApp->focusWindow(); + + if (!w && !qApp->topLevelWindows().isEmpty()) + w = qApp->topLevelWindows().first(); +#else + if (w == 0) w = qApp->activeModalWidget(); + if (w == 0) w = qApp->activePopupWidget(); + if (w == 0) w = qApp->activeWindow(); + if (w == 0) w = qApp->focusWidget(); +#endif + + return w; +} + +QStringList QTestWidgets::objectListToSignatures(const QObjectList& ol) +{ + QTT_TRACE_FUNCTION(); + QStringList ret; + foreach (QObject *obj, ol) { + ret << QTestWidgets::signature(obj); + } + return ret; +} + + +QActiveTestWidgetData::QActiveTestWidgetData() +{ + QTT_TRACE_FUNCTION(); +} + +QActiveTestWidgetData::~QActiveTestWidgetData() +{ + QTT_TRACE_FUNCTION(); +} + +void QActiveTestWidgetData::clear() +{ + QTT_TRACE_FUNCTION(); + testWidgetsBySignature.clear(); + signaturesByObject.clear(); + m_scannedItems.clear(); +} + +void QActiveTestWidgetData::removeTestWidget( QObject *w ) +{ + QTT_TRACE_FUNCTION(); + m_scannedItems.remove(w); + testWidgetsBySignature.remove( QTestWidgets::signature(w) ); + signaturesByObject.remove(w); +} + +bool QActiveTestWidgetData::scan( QObject *ao, QtUiTest::QueryFlags flags ) +{ + QTT_TRACE_FUNCTION(); + if (!ao) return false; + + QActiveTestWidget::instance()->registerTestWidget(ao); + QtUiTest::Object* aw = qtuitest_cast<QtUiTest::Object*>(ao); + if (aw == 0) return false; + bool any_appended = false; + foreach(QObject *o, aw->children()) { + QActiveTestWidget::instance()->registerTestWidget(o); + + QtUiTest::Widget* qw = qtuitest_cast<QtUiTest::Widget*>(o); + + if (!qw->isVisible() && !(flags & QtUiTest::ScanInvisible)) { + continue; + } + + if (!qw->ignoreScan() || (flags & QtUiTest::ScanDisabledItems)) { + // Recursively scan child widgets + any_appended |= scan(o, flags); + } + + if (!m_scannedItems.contains(o)) { + any_appended = true; + m_scannedItems.insert(o); + } + } + + return any_appended; +} + + +QActiveTestWidget::QActiveTestWidget() +{ + QTT_TRACE_FUNCTION(); + d = new QActiveTestWidgetData(); + auto_scan = true; +} + +QActiveTestWidget::~QActiveTestWidget() +{ + QTT_TRACE_FUNCTION(); + delete d; +} + +QActiveTestWidget* QActiveTestWidget::instance() +{ + static QActiveTestWidget qatw; + return &qatw; +} + +void QActiveTestWidget::clear() +{ + QTT_TRACE_FUNCTION(); + if (d == 0) { + d = new QActiveTestWidgetData(); + } else + d->clear(); +} + +const QLatin1String QActiveTestWidget::NoActiveWidgetError("ERROR: No active widget available"); + +bool QActiveTestWidget::rescan(QtUiTest::QueryFlags flags) +{ + QTT_TRACE_FUNCTION(); + if (!auto_scan) return true; + + if (d == 0) d = new QActiveTestWidgetData(); + d->m_scannedItems.clear(); + + QObject *activeWidget = QTestWidgets::activeWidget(); + if (activeWidget == 0) { + QtUiTest::setErrorString(NoActiveWidgetError); + return false; + } + + d->scan(qApp, flags); + return true; +} + +QStringList QActiveTestWidget::descendantTree(QObject *obj) +{ + QStringList ret; + QtUiTest::Object *tw = qtuitest_cast<QtUiTest::Object*>(obj); + if (!tw) { + return ret; + } + ret << QString("%1 [ %2 ]").arg(QTestWidgets::signature(obj)).arg(tw->debugString()); + QObjectList children = tw->children(); + int length = children.length(); + for (int i=0; i<length; ++i) { + QObject *child = children[i]; + QStringList childTree = descendantTree(child); + ret << QString("+- %1").arg(childTree.takeFirst()); + foreach (const QString &row, childTree) { + if (i < length-1) { + ret << QString("| %1").arg(row); + } else { + ret << QString(" %1").arg(row); + } + } + } + return ret; +} + +void QActiveTestWidget::setAutoScan(bool doScan) +{ + auto_scan = doScan; +} + +bool QActiveTestWidget::forceRescan() +{ + bool prev = auto_scan; + auto_scan = true; + bool ret = rescan(); + auto_scan = prev; + return ret; +} + +bool QActiveTestWidget::findWidget( const QString &signature, QObject *&buddy, QString &error ) +{ + QTT_TRACE_FUNCTION(); + if (signature.isEmpty()) { + error = QLatin1String("ERROR: No widget specified\n"); + return false; + } + buddy = QTestWidgets::testWidget(signature); + return (buddy != 0); +} + +/*! + Returns a QVariantMap containing details of object specified by \a signature + and descendants. This is used by the Object Browser. +*/ +QVariantMap QActiveTestWidget::getObjects(const QString &signature) +{ + QTT_TRACE_FUNCTION(); + QVariantMap map; + QObject *baseObject = QTestWidgets::testWidget(signature); + + //FIXME: For now: + baseObject = qApp; + + if (!baseObject) { + return map; + } + + QtUiTest::Object *tw = qtuitest_cast<QtUiTest::Object*>(baseObject); + if (!tw) { + return map; + } + + QObjectList objects; + objects << baseObject << tw->descendants(); + + QVariantMap idMap; + QVariantMap geometryMap; + QVariantMap childMap; + QVariantMap typeMap; + QVariantMap objectNameMap; + QVariantMap visibleMap; + QVariantMap textMap; + QVariantMap windowMap; + + foreach (QObject *obj, objects) { + QActiveTestWidget::instance()->registerTestWidget(obj); + QtUiTest::Object *to = qtuitest_cast<QtUiTest::Object*>(obj); + + if (to) { + QString sig = QTestWidgets::signature(obj); + QObjectList children = to->children(); + if (!children.isEmpty()) { + childMap[sig] = QTestWidgets::objectListToSignatures(to->children()); + } + objectNameMap[sig] = to->getProperty("objectName"); + typeMap[sig] = to->typeOf(); + QtUiTest::Widget *tw = qtuitest_cast<QtUiTest::Widget*>(obj); + if (tw) { + geometryMap[sig] = tw->geometry(); + idMap[sig] = to->getProperty("QMLID"); + visibleMap[sig] = to->getProperty("visible"); + textMap[sig] = to->getProperty("text"); + windowMap[sig] = QTestWidgets::signature(tw->window()); + } + } + } + + map["geometry"] = geometryMap; + map["qmlid"] = idMap; + map["children"] = childMap; + map["type"] = typeMap; + map["objectName"] = objectNameMap; + map["visible"] = visibleMap; + map["text"] = textMap; + map["window"] = windowMap; + + return map; +} + +const QLatin1String QActiveTestWidget::childOfProperty("CHILD_OF"); +const QLatin1String QActiveTestWidget::descendantOfProperty("DESCENDANT_OF"); +const QLatin1String QActiveTestWidget::ancestorOfProperty("ANCESTOR_OF"); +const QLatin1String QActiveTestWidget::parentOfProperty("PARENT_OF"); +const QLatin1String QActiveTestWidget::resourceOfProperty("RESOURCE_OF"); + +QObjectList QActiveTestWidget::findObjectsByProperty( const QString &property, const QVariant &searchValue, const QObjectList &searchList ) +{ + QTT_TRACE_FUNCTION(); + QObjectList foundList; + QString propertyUpper = property.toUpper(); + + bool ok; + PropertyMatcher matcher(searchValue, ok); + if (!ok) { + QtUiTest::setErrorString(QString("Unable to match for property '%1'").arg(property)); + return foundList; + } + + foreach (QObject *obj, searchList) { + QtUiTest::Object *qo = qtuitest_cast<QtUiTest::Object*>(obj); + if (!qo) { + continue; + } + + QVariant value = qo->getProperty(property); + if (value.isValid()) { + if (QObject *obj = value.value<QObject*>()) { + value = QTestWidgets::signature(obj); + } + + // Allow enums to match by value or by string + if (value.type() == QVariant::Map + && value.toMap().contains(QLatin1String("_value_"))) { + if (searchValue.type() == QVariant::String + || searchValue.type() == QVariant::ByteArray) { + value = value.toMap().value(QLatin1String("_enum_")); + } else { + value = value.toMap().value(QLatin1String("_value_")); + } + } + + if (matcher.match(value)) { + foundList << obj; + } + continue; + } + + if (qo->matchProperty(propertyUpper, searchValue)) { + foundList << obj; + continue; + } + } + + return foundList; +} + +QObjectList QActiveTestWidget::queryProperties( const QVariantMap &searchValues, QtUiTest::QueryFlags flags ) +{ + QTT_TRACE_FUNCTION(); + QSet<QObject*> initObjects; + QObjectList searchList; + + if (!((flags & QtUiTest::NoScan) || (flags & QtUiTest::IgnoreScanned))) { + if (!rescan(flags)) { + return searchList; + } + } + + if (!(flags & QtUiTest::IgnoreScanned)) { + initObjects << QTestWidgets::activeWidget(); + initObjects.unite(d->m_scannedItems); + } + + static QStringList filterProperties(QStringList() + << ancestorOfProperty << childOfProperty << descendantOfProperty + << parentOfProperty << resourceOfProperty); + + QVariantMap::const_iterator i = searchValues.constBegin(); + while (i != searchValues.constEnd()) { + QString property = i.key().toUpper(); + if (filterProperties.contains(property)) { + QObjectList filterList; + QString signature; + if (i.value().type() == QVariant::Map) { + signature = i.value().toMap().value(QLatin1String("_signature_")).toString(); + } else { + signature = i.value().toString(); + } + + QString error; + QObject *w; + + if (findWidget(signature, w, error)) { + QtUiTest::Object *qw = qtuitest_cast<QtUiTest::Object*>(w); + if (!qw) { + QtUiTest::setErrorString(QString("Can't find widget '%1' for property '%2'").arg(signature).arg(property)); + return searchList; + } + if (property == childOfProperty) { + filterList << qw->children(); + } else if (property == descendantOfProperty) { + filterList << qw->descendants(); + } else if (property == ancestorOfProperty) { + filterList << qw->ancestors(); + } else if (property == parentOfProperty) { + filterList << qw->parent(); + } else if (property == resourceOfProperty) { + QVariantList resources = qw->resources(); + foreach (const QVariant resource, resources) { + if (QObject *obj = resource.value<QObject*>()) { + filterList << obj; + } + } + } + } + + if (initObjects.isEmpty()) { + initObjects = QSet<QObject*>::fromList(filterList); + } else { + foreach (QObject *obj, initObjects) { + if (!filterList.contains(obj)) { + initObjects.remove(obj); + } + } + if (initObjects.isEmpty()) { + return searchList; + } + } + } + ++i; + } + + searchList = initObjects.toList(); + + i = searchValues.constBegin(); + while (i != searchValues.constEnd()) { + if (!filterProperties.contains(i.key().toUpper())) { + searchList = findObjectsByProperty(i.key(), i.value(), searchList); + if (searchList.isEmpty()) + break; + } + ++i; + } + + return searchList; +} + +PropertyMatcher::PropertyMatcher(const QVariant &searchValue, bool &ok) + : m_matchFunction(0) + , m_searchDouble(0) +{ + ok = true; + if (searchValue.type() == QVariant::Map) { + QVariantMap map = searchValue.toMap(); + m_searchValue = map["_value_"]; + QString op = map["_op_"].toString(); + if (op == QLatin1String("eq")) { + m_matchFunction = &PropertyMatcher::equals; + } else if (op == QLatin1String("ne")) { + m_matchFunction = &PropertyMatcher::notEquals; + } else if (op == QLatin1String("in")) { + m_matchFunction = &PropertyMatcher::containedIn; + ok = m_searchValue.canConvert(QVariant::StringList); + if (ok) + m_searchList = m_searchValue.toStringList(); + } else if (op == QLatin1String("gt")) { + m_matchFunction = &PropertyMatcher::greaterThan; + ok = m_searchValue.canConvert(QVariant::Double); + if (ok) + m_searchDouble = m_searchValue.toDouble(); + } else if (op == QLatin1String("lt")) { + m_matchFunction = &PropertyMatcher::lessThan; + ok = m_searchValue.canConvert(QVariant::Double); + if (ok) + m_searchDouble = m_searchValue.toDouble(); + } else { + ok = false; + } + return; + } else if (searchValue.type() == QVariant::RegExp) { + m_searchRegExp = searchValue.toRegExp(); + m_matchFunction = &PropertyMatcher::regExpMatch; + ok = m_searchRegExp.isValid(); + return; + } + + m_matchFunction = &PropertyMatcher::equals; + m_searchValue = searchValue; +} + +bool PropertyMatcher::match(const QVariant &value) const +{ + return (const_cast<const PropertyMatcher*>(this)->*m_matchFunction)(value); +} + +bool PropertyMatcher::equals(const QVariant &value) const +{ + return value == m_searchValue; +} + +bool PropertyMatcher::notEquals(const QVariant &value) const +{ + return value != m_searchValue; +} + +bool PropertyMatcher::containedIn(const QVariant &value) const +{ + return m_searchList.contains(value.toString()); +} + +bool PropertyMatcher::greaterThan(const QVariant &value) const +{ + return value.toDouble() > m_searchDouble; +} + +bool PropertyMatcher::lessThan(const QVariant &value) const +{ + return value.toDouble() < m_searchDouble; +} + +bool PropertyMatcher::regExpMatch(const QVariant &value) const +{ + return m_searchRegExp.exactMatch(value.toString()); +} diff --git a/src/remote/slave/lib/qtestwidgets.h b/src/remote/slave/lib/qtestwidgets.h new file mode 100644 index 0000000..bc74432 --- /dev/null +++ b/src/remote/slave/lib/qtestwidgets.h @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTESTWIDGETS_H +#define QTESTWIDGETS_H + +#include <QHash> +#include <QMetaType> +#include <QObject> +#include <QPointer> +#include <QString> +#include <QStringList> +#include <QVariantMap> + +#include <QtSystemTest/qstglobal.h> + +#include "qtuitestnamespace.h" + +class QTestWidget; + +class QTSLAVE_EXPORT QActiveTestWidgetData : public QObject +{ +public: + QActiveTestWidgetData(); + ~QActiveTestWidgetData(); + + void clear(); + void removeTestWidget( QObject* ); + bool scan( QObject* aw, QtUiTest::QueryFlags flags=0 ); + + QHash<QString, QObject*> testWidgetsBySignature; + QHash<const QObject*, QString> signaturesByObject; + QSet<QObject*> m_scannedItems; +}; + +class QTSLAVE_EXPORT QActiveTestWidget : public QObject +{ + Q_OBJECT + +public: + static QActiveTestWidget* instance(); + void clear(); + bool rescan( QtUiTest::QueryFlags flags=0 ); + QStringList descendantTree(QObject *obj); + bool findWidget( const QString &signature, QObject *&widget, QString &error ); + QObjectList findObjectsByProperty( const QString&, const QVariant&, const QObjectList& = QObjectList() ); + QObjectList queryProperties( const QVariantMap&, QtUiTest::QueryFlags flags ); + QVariantMap getObjects(const QString&); + QObject* testWidget( const QString &signature ); + QString signature( const QObject *) const; + void registerTestWidget( QObject *ao ); + void setAutoScan(bool); + bool forceRescan(); + + static const QLatin1String NoActiveWidgetError; + + static const QLatin1String ancestorOfProperty; + static const QLatin1String childOfProperty; + static const QLatin1String descendantOfProperty; + static const QLatin1String parentOfProperty; + static const QLatin1String resourceOfProperty; + +protected slots: + void onDestroyed(QObject*); + +private: + QActiveTestWidget(); + ~QActiveTestWidget(); + + bool auto_scan; + QActiveTestWidgetData *d; +}; + +// +// This is the class that manages the test widgets and handles queries about them. +// +class QTSLAVE_EXPORT QTestWidgets +{ +public: + static QObject* activeWidget(); + static QVariant windowProperty(const QString&); + static QObject* testWidget( const QString &signature ); + static QString signature( const QObject* object ); + static QStringList objectListToSignatures(const QObjectList&); + + static bool lessThan(QObject *a, QObject *b) { + QtUiTest::Widget *wa = qtuitest_cast<QtUiTest::Widget*>(a); + QtUiTest::Widget *wb = qtuitest_cast<QtUiTest::Widget*>(b); + if (!wa) return true; + if (!wb) return false; + if (wa->y() == wb->y()) + return wa->x() < wb->x(); + else + return wa->y() < wb->y(); + } +}; + +class PropertyMatcher +{ +public: + PropertyMatcher(const QVariant &searchValue, bool &ok); + bool match(const QVariant &value) const; + +private: + bool equals(const QVariant &value) const; + bool notEquals(const QVariant &value) const; + bool containedIn(const QVariant &value) const; + bool greaterThan(const QVariant &value) const; + bool lessThan(const QVariant &value) const; + bool regExpMatch(const QVariant &value) const; + + QVariant m_searchValue; + QStringList m_searchList; + QRegExp m_searchRegExp; + bool (PropertyMatcher::*m_matchFunction)(const QVariant&) const; + double m_searchDouble; +}; + +#endif diff --git a/src/remote/slave/lib/qtuitestconnectionmanager.cpp b/src/remote/slave/lib/qtuitestconnectionmanager.cpp new file mode 100644 index 0000000..dbb95b6 --- /dev/null +++ b/src/remote/slave/lib/qtuitestconnectionmanager.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qtuitestconnectionmanager_p.h" + +#include <QCoreApplication> +#include <QObject> +#include <QThread> + +// from qobject_p.h +struct QSignalSpyCallbackSet +{ + typedef void (*BeginCallback)(QObject*,int,void**); + typedef void (*EndCallback)(QObject*,int); + BeginCallback signal_begin_callback, + slot_begin_callback; + EndCallback signal_end_callback, + slot_end_callback; +}; +extern void Q_CORE_EXPORT qt_register_signal_spy_callbacks(QSignalSpyCallbackSet const&); +void qtuitest_signal_begin(QObject*,int,void**); + +Q_GLOBAL_STATIC(QtUiTestConnectionManager,_q_qtUiTestConnectionManager); + +QtUiTestConnectionManager::~QtUiTestConnectionManager() +{ + unregisterCallback(); +} + +QtUiTestConnectionManager* QtUiTestConnectionManager::instance() +{ + return _q_qtUiTestConnectionManager(); +} + +void qtuitest_signal_begin(QObject* sender, int signal, void** argv) +{ + QtUiTestConnectionManager* cm = QtUiTestConnectionManager::instance(); + + // Should only ever be null when the application is shutting down, but in that case, + // this callback should already have been unregistered. + Q_ASSERT(cm); + + // During the destructor it isn't safe to check which thread we are. + // We'll just ignore all signals during this time. + if (QCoreApplication::closingDown()) return; + + // Connections are only supported in the main thread. + if (QThread::currentThread() != QCoreApplication::instance()->thread()) return; + + cm->activateConnections(sender,signal,argv); +} + +void QtUiTestConnectionManager::connect(const QObject* sender, int senderMethod, + const QObject* receiver, int receiverMethod) +{ + Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); + + registerCallback(); + + Connection c = { + const_cast<QObject*>(sender), senderMethod, + const_cast<QObject*>(receiver), receiverMethod + }; + m_connections << c; +} + +bool QtUiTestConnectionManager::disconnect(const QObject* sender, int senderMethod, + const QObject* receiver, int receiverMethod) +{ + Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); + + bool ret = false; + + QList<Connection>::iterator iter = m_connections.begin(); + while (iter != m_connections.end()) + { + bool remove = true; + + if (sender && (sender != iter->sender)) remove = false; + if ((senderMethod != -1) && (senderMethod != iter->senderMethod)) remove = false; + if (receiver && (receiver != iter->receiver)) remove = false; + if ((receiverMethod != -1) && (receiverMethod != iter->receiverMethod)) remove = false; + + if (remove) { + ret = true; + iter = m_connections.erase(iter); + } + else { + ++iter; + } + } + + unregisterCallback(); + + return ret; +} + +void QtUiTestConnectionManager::registerCallback() +{ + // If this is the first connect, then register the callback function + if (m_connections.isEmpty()) { + QSignalSpyCallbackSet callbacks = { qtuitest_signal_begin, 0, 0, 0 }; + qt_register_signal_spy_callbacks(callbacks); + } +} + +void QtUiTestConnectionManager::unregisterCallback() +{ + // If everything has been disconnected, remove the callback function + if (m_connections.isEmpty()) { + QSignalSpyCallbackSet callbacks = { 0, 0, 0, 0 }; + qt_register_signal_spy_callbacks(callbacks); + } +} + +void QtUiTestConnectionManager::activateConnections(QObject* sender, int senderMethod, void** argv) +{ + static const int destroyedMethod = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); + const bool destroyed = (senderMethod == destroyedMethod); + + // Find all of the connections we need to activate. + QList<Connection> toActivate; + QList<Connection>::iterator iter = m_connections.begin(); + while (iter != m_connections.end()) + { + if (sender == iter->sender && senderMethod == iter->senderMethod) + toActivate << *iter; + + // Remove this connection if either the sender or receiver is being destroyed + if (destroyed && (sender == iter->sender || sender == iter->receiver)) { + iter = m_connections.erase(iter); + unregisterCallback(); + } + else + ++iter; + } + + foreach (Connection const& c, toActivate) + { if (c.receiver) c.receiver->qt_metacall(QMetaObject::InvokeMetaMethod, c.receiverMethod, argv); } +} + diff --git a/src/remote/slave/lib/qtuitestconnectionmanager_p.h b/src/remote/slave/lib/qtuitestconnectionmanager_p.h new file mode 100644 index 0000000..7a25b2b --- /dev/null +++ b/src/remote/slave/lib/qtuitestconnectionmanager_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITESTCONNECTIONMANAGER_P_H +#define QTUITESTCONNECTIONMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtUiTest API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QList> +#include <QtSystemTest/qstglobal.h> + +class QObject; + +class QTUITEST_EXPORT QtUiTestConnectionManager +{ +public: + static QtUiTestConnectionManager* instance(); + + void connect (const QObject*,int,const QObject*,int); + bool disconnect(const QObject*,int,const QObject*,int); + + QtUiTestConnectionManager() {} + ~QtUiTestConnectionManager(); + void registerCallback(); + void unregisterCallback(); + + void activateConnections(QObject*,int,void**); + + struct Connection { + QObject* sender; + int senderMethod; + QObject* receiver; + int receiverMethod; + }; + QList<Connection> m_connections; +}; + +#endif + diff --git a/src/remote/slave/lib/qtuitestmessagehandler.h b/src/remote/slave/lib/qtuitestmessagehandler.h new file mode 100644 index 0000000..2a34b6c --- /dev/null +++ b/src/remote/slave/lib/qtuitestmessagehandler.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITEST_MESSAGE_HANDLER_INTERFACE_H +#define QTUITEST_MESSAGE_HANDLER_INTERFACE_H + +#include <QtSystemTest/QstProtocol> + +class QTestSlavePrivate; + +namespace QtUiTest { + + class QTSLAVE_EXPORT MessageHandler + { + QTUITEST_INTERFACE(MessageHandler) + + public: + virtual QString handlerName() const = 0; + virtual QstMessage handleMessage(const QstMessage&) = 0; + }; + +}; + +Q_DECLARE_INTERFACE(QtUiTest::MessageHandler, "com.nokia.qt.QtUiTest.MessageHandler/1.0") + +#endif diff --git a/src/remote/slave/lib/qtuitestnamespace.cpp b/src/remote/slave/lib/qtuitestnamespace.cpp new file mode 100644 index 0000000..3500300 --- /dev/null +++ b/src/remote/slave/lib/qtuitestnamespace.cpp @@ -0,0 +1,1038 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qtuitestnamespace.h" + +#include "qeventwatcher_p.h" +#include "qtuitestconnectionmanager_p.h" +#include "qtuitestwidgets_p.h" + +#include <QtSystemTest/QstDebug> +#include <QEventLoop> +#include <QKeyEvent> +#include <QKeySequence> +#include <QPointer> +#include <QTimer> + +/* + A simple auto pointer class which deletes the pointed-to QObject + later via deleteLater() +*/ +template <typename T> +class QDelayedAutoPointer +{ +public: + inline QDelayedAutoPointer(T* thing) + : raw(thing) + {} + inline ~QDelayedAutoPointer() + { + QObject::disconnect(raw, 0, 0, 0); + raw->deleteLater(); + } + + inline T* operator->() + { return raw; } + + inline operator T*() + { return raw; } + +private: + T* raw; +}; + +/* + A helper class to encapsulate generation of input events +*/ +struct QtUiTestInput +{ + virtual ~QtUiTestInput() {} + virtual void post() const =0; + virtual QString toString() const =0; +}; + + +namespace QtUiTest { + QString toString(QObject* obj) + { + if (!obj) return "QObject(0x0)"; + return QString("%1(0x%2 \"%3\")") + .arg(obj->metaObject()->className()) + .arg(QString::number(qptrdiff(obj), 16)) + .arg(obj->objectName()) + ; + } + + QString toString(QEvent::Type type) + { +#define DO(A) if (type == QEvent::A) return #A + DO(KeyPress); + DO(KeyRelease); + DO(MouseButtonPress); + DO(MouseButtonRelease); + DO(Show); + DO(Hide); + DO(FocusIn); + DO(FocusOut); + DO(WindowBlocked); +#undef DO + return QString::number(int(type)); + } + + QString toString(QList<QEvent::Type> const& types) + { + QString ret; + QString sep; + foreach (QEvent::Type type, types) { + ret += sep + toString(type); + sep = ","; + } + return ret; + } + + QString toString(Qt::Key key) + { return QKeySequence(key).toString(); } + + QString toString(const QPoint& pos) + { return QString("(%1,%2)").arg(pos.x()).arg(pos.y()); } + + QString toString(Qt::MouseButtons const& buttons) + { + QStringList ret; +#define DO(A) if (buttons & Qt::A) ret << #A + DO(LeftButton); + DO(RightButton); + DO(MidButton); + DO(XButton1); + DO(XButton2); +#undef DO + return ret.join(","); + } + + bool keyClick(QObject*, QList<QEvent::Type> const&, int, Qt::KeyboardModifiers, QtUiTest::InputOption); + bool mouseClick(QObject*, QList<QEvent::Type> const&, const QPoint&, Qt::MouseButtons, QtUiTest::InputOption); + bool mouseDClick(QObject*, QList<QEvent::Type> const&, const QPoint&, Qt::MouseButtons, QtUiTest::InputOption); + bool inputWithEvent(QObject*, QList<QEventWatcherFilter*> const&, QtUiTestInput const&); + bool inputWithSignal(QObject*, const QByteArray&, QtUiTestInput const&); +}; + +struct QtUiTestKeyClick : public QtUiTestInput +{ + QtUiTestKeyClick(Qt::Key key, Qt::KeyboardModifiers modifiers, QtUiTest::InputOption options) + : m_key(key), m_modifiers(modifiers), m_options(options) + {} + + virtual void post() const + { QtUiTest::keyClick(m_key, m_modifiers, m_options); } + + virtual QString toString() const + { return QString("Key click \"%1\"").arg(QtUiTest::toString(m_key)); } + + Qt::Key m_key; + Qt::KeyboardModifiers m_modifiers; + QtUiTest::InputOption m_options; +}; + +struct QtUiTestMouseClick : public QtUiTestInput +{ + QtUiTestMouseClick(const QPoint& pos, Qt::MouseButtons buttons, QtUiTest::InputOption options) + : m_pos(pos), m_buttons(buttons), m_options(options) + {} + + virtual void post() const + { QtUiTest::mouseClick(m_pos, m_buttons, m_options); } + + virtual QString toString() const + { + return QString("Mouse click \"%1\" at %2") + .arg(QtUiTest::toString(m_buttons)) + .arg(QtUiTest::toString(m_pos)) + ; + } + + const QPoint& m_pos; + Qt::MouseButtons m_buttons; + QtUiTest::InputOption m_options; +}; + +struct QtUiTestMouseDClick : public QtUiTestInput +{ + QtUiTestMouseDClick(const QPoint& pos, Qt::MouseButtons buttons, QtUiTest::InputOption options) + : m_pos(pos), m_buttons(buttons), m_options(options) + {} + + virtual void post() const + { QtUiTest::mouseDClick(m_pos, m_buttons, m_options); } + + virtual QString toString() const + { + return QString("Mouse click \"%1\" at %2") + .arg(QtUiTest::toString(m_buttons)) + .arg(QtUiTest::toString(m_pos)) + ; + } + + const QPoint& m_pos; + Qt::MouseButtons m_buttons; + QtUiTest::InputOption m_options; +}; + +/* + Filter which implements watching for events of a specific type. +*/ +class QEventWatcherTypeFilter : public QEventWatcherFilter +{ +public: + QEventWatcherTypeFilter(QEvent::Type type) + : m_type(type) + {} + +protected: + virtual bool accept(QObject*,QEvent* e) const + { return e->type() == m_type; } + + virtual QString toString() const + { return QString("event of type %1").arg(QtUiTest::toString(m_type)); } + +private: + QEvent::Type m_type; +}; + +/* + Filter which implements watching for specific key events. +*/ + +class QEventWatcherKeyFilter : public QEventWatcherTypeFilter +{ +public: + QEventWatcherKeyFilter(Qt::Key key, QEvent::Type type) + : QEventWatcherTypeFilter(type) + , m_key(key) + {} + + static QEvent::Type keyPressType() + { static int ret = QEvent::registerEventType(); return QEvent::Type(ret); } + + static QEvent::Type keyReleaseType() + { static int ret = QEvent::registerEventType(); return QEvent::Type(ret); } + +protected: + virtual bool accept(QObject* o, QEvent* e) const + { + if (!QEventWatcherTypeFilter::accept(o,e)) + return false; + if (e->type() != QEvent::KeyPress && e->type() != QEvent::KeyRelease) + return false; + return static_cast<QKeyEvent*>(e)->key() == m_key; + } + + virtual QString toString() const + { + return QString("%1 (key:%2)") + .arg(QEventWatcherTypeFilter::toString()) + .arg(QtUiTest::toString(m_key)); + } + +private: + Qt::Key m_key; +}; + + +/*! + \preliminary + \namespace QtUiTest + \inpublicgroup QtUiTestModule + + \brief The QtUiTest namespace provides the plugin interfaces used for + customizing the behaviour of QtUiTest. +*/ + +/*! + \fn T QtUiTest::qtuitest_cast_helper(QObject* object,T dummy) + \internal +*/ + +/*! + \relates QtUiTest + \fn T qtuitest_cast(const QObject *object) + + Casts \a object to the specified QtUiTest test widget interface \c{T}. + + If \a object already implements \c{T}, it is simply casted and returned. + Otherwise, QtUiTest will attempt to find or create a test widget to + wrap \a object, using all loaded QtUiTest::WidgetFactory plugins. + If a test widget cannot be created to wrap \a object, 0 is returned. + + In either case, the returned value must not be deleted by the caller. +*/ + + +/*! + \enum QtUiTest::InputOption + + This enum type specifies the options to be used when simulating key + and mouse events. + + \value NoOptions no options. + \value KeyRepeat when simulating key press events, simulate auto-repeat + key press events. The default is to simulate regular key + press events. +*/ + +/*! + \enum QtUiTest::Key + + This enum provides mappings for high-level conceptual keys to platform-specific + values of Qt::Key. + + \value Key_Activate Key used to activate generic UI elements. + \value Key_ActivateButton Key used to activate buttons. + \value Key_Select Key used to select an item from lists. +*/ + +/*! + Set or clear the specified \a option for subsequent simulated input + events. The option is set if \a on is true, otherwise it is cleared. +*/ +void QtUiTest::setInputOption(QtUiTest::InputOption option, bool on) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->setInputOption(option, on); +} + +/*! + Returns true if \a option is currently set. +*/ +bool QtUiTest::testInputOption(QtUiTest::InputOption option) +{ + QTT_TRACE_FUNCTION(); + return QtUiTestWidgets::instance()->testInputOption(option); +} + +/*! + Simulate a mouse press event at the co-ordinates given by \a pos, + for the specified \a buttons. \a options are applied to the simulated + event. + + \a pos is interpreted as local co-ordinates for the currently active + window in this application. +*/ +void QtUiTest::mousePress(const QPoint& pos, Qt::MouseButtons buttons, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->mousePress(pos, buttons, options); +} + +void QtUiTest::touchPress(const QVariantList &points) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->touchPress(points); +} + +void QtUiTest::touchUpdate(const QVariantList &points) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->touchUpdate(points); +} + +void QtUiTest::touchRelease(const QVariantList &points) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->touchRelease(points); +} + +/*! + Simulate a mouse release event at the global co-ordinates given by \a pos, + for the specified \a buttons. \a options are applied to the simulated + event. + + \a pos is interpreted as local co-ordinates for the currently active + window in this application. +*/ +void QtUiTest::mouseRelease(const QPoint& pos, Qt::MouseButtons buttons, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->mouseRelease(pos, buttons, options); +} + +/*! + Simulate a mouse click event at the global co-ordinates given by \a pos, + for the specified \a buttons. \a options are applied to the simulated + event. + + \a pos is interpreted as local co-ordinates for the currently active + window in this application. +*/ +void QtUiTest::mouseClick(const QPoint& pos, Qt::MouseButtons buttons, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->mouseClick(pos, buttons, options); +} + +/*! + Simulate a mouse double-click event at the global co-ordinates given by \a pos, + for the specified \a buttons. \a options are applied to the simulated + event. + + \a pos is interpreted as local co-ordinates for the currently active + window in this application. +*/ +void QtUiTest::mouseDClick(const QPoint& pos, Qt::MouseButtons buttons, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->mouseDClick(pos, buttons, options); +} + +/*! + \overload + Simulate a mouse click event. + Returns true if the event appears to be delivered to \a object within maximumUiTimeout() + milliseconds. + If it does not, the errorString() will be set accordingly. +*/ +bool QtUiTest::mouseClick(QObject* object, const QPoint& pos, Qt::MouseButtons buttons, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + return mouseClick(object, + QList<QEvent::Type>() << QEvent::MouseButtonRelease << QEvent::Hide << QEvent::WindowBlocked, + pos, buttons, options + ); +} + +/*! + \overload + Simulate a mouse double-click event. + Returns true if the event appears to be delivered to \a object within maximumUiTimeout() + milliseconds. + If it does not, the errorString() will be set accordingly. +*/ +bool QtUiTest::mouseDClick(QObject* object, const QPoint& pos, Qt::MouseButtons buttons, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + return mouseDClick(object, + QList<QEvent::Type>() << QEvent::MouseButtonRelease << QEvent::Hide << QEvent::WindowBlocked, + pos, buttons, options + ); +} + +/*! + Simulate moving the mouse pointer to the global co-ordinates given by \a pos. + \a options are applied to the simulated event. +*/ +void QtUiTest::mouseMove(const QPoint& pos, QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->mouseMove(pos, options); +} + +/*! + \internal +*/ +bool QtUiTest::mouseClick(QObject* object, QList<QEvent::Type> const& types, const QPoint& pos, + Qt::MouseButtons buttons, QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QList<QEventWatcherFilter*> filters; + foreach (QEvent::Type type, types) { + filters << new QEventWatcherTypeFilter(type); + } + return inputWithEvent(object, filters, QtUiTestMouseClick(pos, buttons, options)); +} + +/*! + \internal +*/ +bool QtUiTest::mouseDClick(QObject* object, QList<QEvent::Type> const& types, const QPoint& pos, + Qt::MouseButtons buttons, QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QList<QEventWatcherFilter*> filters; + foreach (QEvent::Type type, types) { + filters << new QEventWatcherTypeFilter(type); + } + return inputWithEvent(object, filters, QtUiTestMouseDClick(pos, buttons, options)); +} + +/*! + \overload + Simulate a mouse click event. + Returns true if the event causes \a object to emit \a signal within maximumUiTimeout() + milliseconds. + If it does not, the errorString() will be set accordingly. +*/ +bool QtUiTest::mouseClick(QObject* object, const QByteArray& signal, const QPoint& pos, + Qt::MouseButtons buttons, QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + return inputWithSignal(object, signal, QtUiTestMouseClick(pos, buttons, options)); +} + +/*! + \overload + Simulate a mouse double-click event. + Returns true if the event causes \a object to emit \a signal within maximumUiTimeout() + milliseconds. + If it does not, the errorString() will be set accordingly. +*/ +bool QtUiTest::mouseDClick(QObject* object, const QByteArray& signal, const QPoint& pos, + Qt::MouseButtons buttons, QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + return inputWithSignal(object, signal, QtUiTestMouseDClick(pos, buttons, options)); +} + +/*! + Simulate a key press event, using the given \a key and \a modifiers. + \a key must be a valid Qt::Key or QtUiTest::Key. + \a options are applied to the simulated event. +*/ +void QtUiTest::keyPress(int key, Qt::KeyboardModifiers modifiers, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->keyPress(static_cast<Qt::Key>(key), modifiers, options); +} + +/*! + Simulate a key release event, using the given \a key and \a modifiers. + \a key must be a valid Qt::Key or QtUiTest::Key. + \a options are applied to the simulated event. +*/ +void QtUiTest::keyRelease(int key, Qt::KeyboardModifiers modifiers, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->keyRelease(static_cast<Qt::Key>(key), modifiers, options); +} + +/*! + Simulate a key click event, using the given \a key and \a modifiers. + \a key must be a valid Qt::Key or QtUiTest::Key. + \a options are applied to the simulated event. +*/ +void QtUiTest::keyClick(int key, Qt::KeyboardModifiers modifiers, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QtUiTestWidgets::instance()->keyClick(static_cast<Qt::Key>(key), modifiers, options); +} + +/*! + \overload + Simulate a key click event. + Returns true if the event appears to be delivered to \a object within maximumUiTimeout() + milliseconds. + If it does not, the errorString() will be set accordingly. +*/ +bool QtUiTest::keyClick(QObject* object, int key, Qt::KeyboardModifiers modifiers, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + return keyClick(object, + QList<QEvent::Type>() << QEventWatcherKeyFilter::keyReleaseType() + << QEvent::Hide << QEvent::WindowBlocked << QEvent::Show, + key, modifiers, options + ); +} + +/*! + \internal +*/ +bool QtUiTest::inputWithEvent(QObject* object, QList<QEventWatcherFilter*> const& filters, + QtUiTestInput const& event) +{ + QTT_TRACE_FUNCTION(); + QPointer<QObject> sender = object; + QDelayedAutoPointer<QEventWatcher> w = new QEventWatcher; + w->addObject(sender); + foreach (QEventWatcherFilter* filter, filters) + w->addFilter(filter); + + event.post(); + + if (!w->count() && !QtUiTest::waitForSignal(w, SIGNAL(event(QObject*,int)))) { + setErrorString(QString( + "%1 was expected to result in %2 receiving an event matching one of the following, " + "but it didn't:\n%3") + .arg(event.toString()) + .arg(toString(sender)) + .arg(w->toString())); + return false; + } + return true; +} + +/*! + \internal +*/ +bool QtUiTest::inputWithSignal(QObject* object, const QByteArray& signal, + QtUiTestInput const& event) +{ + QTT_TRACE_FUNCTION(); + if (signal.isEmpty()) return false; + QPointer<QObject> sender = object; + + QTimer dummy; + dummy.setInterval(1000); + if (!QtUiTest::connectFirst(sender, signal, &dummy, SLOT(start()))) { + setErrorString(QString("Object %1 has no signal %2").arg(toString(sender)).arg(&signal.constData()[1])); + return false; + } + + // Ensure connectNotify is called + if (!QObject::connect(sender, signal, &dummy, SLOT(start()))) + Q_ASSERT(0); + + event.post(); + + if (!dummy.isActive() && !QtUiTest::waitForSignal(sender, signal)) { + setErrorString(QString( + "%1 was expected to result in %2 emitting the signal %3, " + "but it didn't.") + .arg(event.toString()) + .arg(toString(sender)) + .arg(&signal.constData()[1])); + return false; + } + return true; +} + +/*! + \internal + \overload + Simulate a key click event. + Returns true if \a object receives any event of the given \a types within maximumUiTimeout() + milliseconds. + If it does not, the errorString() will be set accordingly. +*/ +bool QtUiTest::keyClick(QObject* object, QList<QEvent::Type> const& types, int key, + Qt::KeyboardModifiers modifiers, QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + QList<QEventWatcherFilter*> filters; + foreach (QEvent::Type type, types) { + // These cases result in waiting for specific key events rather than just "any key press". + if (type == QEventWatcherKeyFilter::keyPressType()) { + filters << new QEventWatcherKeyFilter(Qt::Key(key), QEvent::KeyPress); + } else if (type == QEventWatcherKeyFilter::keyReleaseType()) { + filters << new QEventWatcherKeyFilter(Qt::Key(key), QEvent::KeyRelease); + } else { + filters << new QEventWatcherTypeFilter(type); + } + } + return inputWithEvent(object, filters, QtUiTestKeyClick(Qt::Key(key), modifiers, options)); +} + +/*! + \overload + Simulate a key click event. + Returns true if \a object emits \a signal within maximumUiTimeout() + milliseconds. + If it does not, the errorString() will be set accordingly. +*/ +bool QtUiTest::keyClick(QObject* object, const QByteArray& signal, int key, Qt::KeyboardModifiers modifiers, + QtUiTest::InputOption options) +{ + QTT_TRACE_FUNCTION(); + return inputWithSignal(object, signal, QtUiTestKeyClick(Qt::Key(key), modifiers, options)); +} + +/*! + Returns the maximum amount of time, in milliseconds, the user interface is allowed to take + to generate some response to a user's action. + + This value is useful to determine how long test widgets should wait for certain events to occur + after simulating key/mouse events. The value may be device-specific. +*/ +int QtUiTest::maximumUiTimeout() +{ return 2000; } + +/*! + Returns the Qt::Key corresponding to \a c. + + This function is commonly used in conjunction with keyClick() to enter + a string of characters using the keypad. + + Example: + \code + using namespace QtUiTest; + QString text = "hello world"; + // ... + foreach (QChar c, text) { + keyClick( asciiToKey(c.toLatin1()), asciiToModifiers(c.toLatin1()) ); + } + \endcode +*/ +// Now implemented in qasciikey.cpp + +/*! + Returns any Qt::KeyboardModifiers which would be required to input \a c. + + This function is commonly used in conjunction with keyClick() to enter + a string of characters using the keypad. + + Example: + \code + using namespace QtUiTest; + QString text = "hello world"; + // ... + foreach (QChar c, text) { + keyClick( asciiToKey(c.toLatin1()), asciiToModifiers(c.toLatin1()) ); + } + \endcode +*/ +Qt::KeyboardModifiers QtUiTest::asciiToModifiers(char c) +{ + QTT_TRACE_FUNCTION(); + Qt::KeyboardModifiers ret = Qt::NoModifier; + if (QChar(c).isUpper()) ret |= Qt::ShiftModifier; + return ret; +} + +/*! + Returns a human-readable error string describing the last error which + occurred while accessing a testwidget. + + The error string is used to report directly to a tester any unexpected + errors. The string will typically be used as a test failure message. + + \sa setErrorString() +*/ +QString QtUiTest::errorString() +{ + return QtUiTestWidgets::instance()->errorString(); +} + +/*! + Returns a QDebug object which can be used as an output stream for debugging + information. The debug information is sent to the test runner for output. + This ensures a consistent handling of debugging information on different + test platforms. + + Example: + \code + QtUiTest::debug() << "This is a debug message"; + \endcode +*/ +QDebug QtUiTest::debug() +{ + return QtUiTestWidgets::instance()->debug(); +} + +/*! + \internal +*/ +QString QtUiTest::debugOutput() +{ + return QtUiTestWidgets::instance()->debugOutput(); +} + +/*! + Sets the human-readable \a error string describing the last error which + occurred while accessing a testwidget. + + \sa errorString() +*/ +void QtUiTest::setErrorString(const QString& error) +{ + QtUiTestWidgets::instance()->setErrorString(error); +} + +/*! + \internal + Returns a test widget wrapper for \a object which implements + \a interface. +*/ +QObject* QtUiTest::testWidget(QObject* object, const char* interface) +{ + return QtUiTestWidgets::instance()->testWidget(object, interface); +} + +/*! + Causes the process to wait for \a ms milliseconds. While waiting, events will be processed. +*/ +void QtUiTest::wait(int ms) +{ + QTT_TRACE_FUNCTION(); + QEventLoop loop; + QTimer::singleShot(ms, &loop, SLOT(quit())); + loop.exec(); +} + +#include <QDebug> + +/*! + Causes the process to wait for \a ms milliseconds or until \a signal is + emitted from \a object, whichever comes first. + + While waiting, events will be processed. + + Returns true if \a signal was emitted from \a object before timing out. + When false is returned, errorString() is set accordingly. + + If \a connectionType specifies a direct connection, this function will return + immediately when the signal occurs, possibly before some objects have + received the signal. If \a connectionType specifies a queued connection, this + function will return once the event loop has run following the emit. +*/ +bool QtUiTest::waitForSignal(QObject* object, const char* signal, int ms, Qt::ConnectionType connectionType) +{ + QTT_TRACE_FUNCTION(); + if (ms < 0) return false; + if (!signal || !signal[0]) return false; + + QPointer<QObject> sender = object; + + // Dummy variable to detect signal emission. + QTimer dummy; + dummy.setInterval(1000); + if (!QtUiTest::connectFirst(sender, signal, &dummy, SLOT(start()))) + return false; + + // Ensure connectNotify is called + if (!QObject::connect(sender, signal, &dummy, SLOT(start()))) + Q_ASSERT(0); + + QEventLoop loop; + if (!QObject::connect(sender, signal, &loop, SLOT(quit()))) + return false; + QTimer::singleShot(ms, &loop, SLOT(quit())); + + loop.exec(); + + return dummy.isActive(); +} + +/*! + Causes the process to wait for \a ms milliseconds or until an event of + any of the given \a types is received by \a object, whichever comes first. + + While waiting, events will be processed. + + Returns true if the event was received by \a object before timing out. + When false is returned, errorString() is set accordingly. + + If \a connectionType specifies a direct connection, this function will return + immediately before the event is processed by \a object. + If \a connectionType specifies a queued connection, this function will return + once the event loop has run following the processing of the event. +*/ +bool QtUiTest::waitForEvent(QObject* object, QList<QEvent::Type> const& types, int ms, Qt::ConnectionType connectionType) +{ + QTT_TRACE_FUNCTION(); + QPointer<QObject> sender = object; + QDelayedAutoPointer<QEventWatcher> w = new QEventWatcher; + w->setObjectName("qtuitest_waitForEvent_watcher"); + w->addObject(sender); + foreach (QEvent::Type type, types) + w->addFilter(new QEventWatcherTypeFilter(type)); + + if (!QtUiTest::waitForSignal(w, SIGNAL(event(QObject*,int)), ms, connectionType)) { + setErrorString(QString("Object %1 was expected to receive an event of type(s) %2 within " + "%3 milliseconds, but it didn't.") + .arg(toString(sender)) + .arg(toString(types)) + .arg(ms) + ); + return false; + } + return true; +} + +/*! + \overload + Waits for an event of the given \a type. +*/ +bool QtUiTest::waitForEvent(QObject* object, QEvent::Type type, int ms, Qt::ConnectionType connectionType) +{ + QTT_TRACE_FUNCTION(); + return waitForEvent(object, QList<QEvent::Type>() << type, ms, connectionType); +} + +/*! + Creates a connection from the \a signal in the \a sender object to + the \a method in the \a receiver object. Returns true if the connection succeeds; + otherwise returns false. + + This function behaves similarly to QObject::connect() with the following + important differences. + \list + \o The connection is guaranteed to be activated before + any connections made with QObject::connect(). + \o The connection type is always Qt::DirectConnection. + \o The connection cannot be disconnected using QObject::disconnect() + (QtUiTest::disconnectFirst() must be used instead). + \o The connection does not affect the return value of QObject::receivers(). + \o While \a method is being executed, the return value of + QObject::sender() is undefined. + \o QObject::connectNotify() is not called on the sending object. + \endlist + + This function is primarily used in conjunction with QtUiTestRecorder to + ensure events are recorded in the correct order. + + Note that this function cannot be used in a program which uses QSignalSpy. + + \sa QObject::connect(), QtUiTest::disconnectFirst() +*/ +bool QtUiTest::connectFirst(const QObject* sender, const char* signal, + const QObject* receiver, const char* method) +{ + QTT_TRACE_FUNCTION(); + // On failure, we use QObject::connect to get the same error message as + // we normally would. + if (sender == 0 || receiver == 0 || signal == 0 || method == 0) { + return QObject::connect(sender,signal,receiver,method); + } + if (qstrlen(signal) < 1 || qstrlen(method) < 1) { + return QObject::connect(sender,signal,receiver,method); + } + + const QMetaObject* const senderMo = sender->metaObject(); + + QByteArray normalSignal = QByteArray::fromRawData(signal+1, qstrlen(signal)-1); + int signal_index = senderMo->indexOfSignal(normalSignal); + + if (signal_index < 0) { + // See if we can find the signal after normalizing. + normalSignal = QMetaObject::normalizedSignature(normalSignal); + signal_index = senderMo->indexOfSignal(normalSignal); + } + if (signal_index < 0) { + // Nope, bail out. + return QObject::connect(sender,signal,receiver,method); + } + + const QMetaObject* const receiverMo = receiver->metaObject(); + + QByteArray normalMethod = QByteArray::fromRawData(method+1, qstrlen(method)-1); + int method_index = receiverMo->indexOfMethod(normalMethod); + + if (method_index < 0) { + // See if we can find the method after normalizing. + normalMethod = QMetaObject::normalizedSignature(normalMethod); + method_index = senderMo->indexOfMethod(normalMethod); + } + if (method_index < 0) { + // Nope, bail out. + return QObject::connect(sender,signal,receiver,method); + } + + // Ensure signal and slot are compatible. + if (!QMetaObject::checkConnectArgs(normalSignal.constData(), normalMethod.constData())) { + return QObject::connect(sender,signal,receiver,method); + } + + // If we get here, then everything is valid. + QtUiTestConnectionManager::instance()->connect(sender, signal_index, receiver, method_index); + return true; +} + +/*! + Disconnects \a signal in object \a sender from \a method in object \a receiver. Returns true if the connection is successfully broken; otherwise returns false. + + The connection must have been established with QtUiTest::connectFirst(). + + Passing null arguments has the same wildcard effects as documented in QObject::disconnect(). + + If the same connection has been established multiple times, disconnectFirst() will disconnect + all instances of the connection. There is no way to disconnect a single instance of a + connection. This behavior matches QObject::disconnect(). + + \sa QObject::disconnect(), QtUiTest::connectFirst() +*/ +bool QtUiTest::disconnectFirst(const QObject* sender, const char* signal, + const QObject* receiver, const char* method) +{ + QTT_TRACE_FUNCTION(); + // On failure, we use QObject::disconnect to get the same error message as + // we normally would. + if (sender == 0) { + return QObject::disconnect(sender,signal,receiver,method); + } + + const QMetaObject* const senderMo = sender->metaObject(); + + QByteArray normalSignal = (signal) + ? QByteArray::fromRawData(signal+1, qstrlen(signal)-1) + : QByteArray(); + int signal_index = (signal) ? senderMo->indexOfSignal(normalSignal) : -1; + if (signal && (signal_index < 0)) { + // See if we can find the signal after normalizing. + normalSignal = QMetaObject::normalizedSignature(signal); + signal_index = senderMo->indexOfSignal(normalSignal); + } + if (signal && (signal_index < 0)) { + // Nope, bail out. + return QObject::disconnect(sender,signal,receiver,method); + } + + if (method && !receiver) { + return QObject::disconnect(sender,signal,receiver,method); + } + + const QMetaObject* const receiverMo = (receiver) ? receiver->metaObject() : 0; + + QByteArray normalMethod = (method) + ? QByteArray::fromRawData(method+1, qstrlen(method)-1) + : QByteArray(); + int method_index = (method) ? receiverMo->indexOfMethod(normalMethod) : -1; + + if (method && (method_index < 0)) { + // See if we can find the method after normalizing. + normalMethod = QMetaObject::normalizedSignature(method); + method_index = senderMo->indexOfMethod(normalMethod); + } + if (method && (method_index < 0)) { + // Nope, bail out. + return QObject::disconnect(sender,signal,receiver,method); + } + + return QtUiTestConnectionManager::instance()->disconnect(sender,signal_index,receiver,method_index); +} + diff --git a/src/remote/slave/lib/qtuitestnamespace.h b/src/remote/slave/lib/qtuitestnamespace.h new file mode 100644 index 0000000..c142cee --- /dev/null +++ b/src/remote/slave/lib/qtuitestnamespace.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITESTNAMESPACE_H +#define QTUITESTNAMESPACE_H + +#include <QtSystemTest/qstglobal.h> + +#include <QEvent> +#include <QObject> +#include <Qt> +#include <QVariant> + +class QPoint; + +namespace QtUiTest +{ + enum InputOption { + NoOptions = 0x0, + KeyRepeat = 0x1 + }; + + enum Key { +#ifdef Q_WS_QWS + Key_Activate = Qt::Key_Select, +#else + Key_Activate = Qt::Key_Enter, +#endif + +#ifdef Q_WS_QWS + Key_Select = Qt::Key_Select, +#else + Key_Select = Qt::Key_Space, +#endif + +#if defined(Q_WS_QWS) || defined (Q_OS_SYMBIAN) + Key_ActivateButton = Qt::Key_Select +#else + Key_ActivateButton = Qt::Key_Space +#endif + }; + + enum QueryFlag + { + NoSort = 0x01, + NoScan = 0x02, + ScanInvisible = 0x04, + ScanDisabledItems = 0x08, + IgnoreScanned = 0x10 + }; + Q_DECLARE_FLAGS(QueryFlags, QueryFlag); + + QTUITEST_EXPORT void setInputOption(InputOption,bool = true); + QTUITEST_EXPORT bool testInputOption(InputOption); + + QTUITEST_EXPORT QString errorString(); + QTUITEST_EXPORT void setErrorString(const QString&); + QTUITEST_EXPORT QDebug debug(); + QTUITEST_EXPORT QString debugOutput(); + + QTUITEST_EXPORT void touchPress(const QVariantList&); + QTUITEST_EXPORT void touchUpdate(const QVariantList&); + QTUITEST_EXPORT void touchRelease(const QVariantList&); + + QTUITEST_EXPORT void mousePress (const QPoint&,Qt::MouseButtons = Qt::LeftButton, + InputOption = NoOptions); + QTUITEST_EXPORT void mouseRelease(const QPoint&,Qt::MouseButtons = Qt::LeftButton, + InputOption = NoOptions); + QTUITEST_EXPORT void mouseClick (const QPoint&,Qt::MouseButtons = Qt::LeftButton, + InputOption = NoOptions); + QTUITEST_EXPORT bool mouseClick (QObject*,const QPoint&,Qt::MouseButtons = Qt::LeftButton, + InputOption = NoOptions); + QTUITEST_EXPORT bool mouseClick (QObject*,const QByteArray&,const QPoint&, + Qt::MouseButtons = Qt::LeftButton, InputOption = NoOptions); + QTUITEST_EXPORT void mouseDClick (const QPoint&,Qt::MouseButtons = Qt::LeftButton, + InputOption = NoOptions); + QTUITEST_EXPORT bool mouseDClick (QObject*,const QPoint&,Qt::MouseButtons = Qt::LeftButton, + InputOption = NoOptions); + QTUITEST_EXPORT bool mouseDClick (QObject*,const QByteArray&,const QPoint&, + Qt::MouseButtons = Qt::LeftButton, InputOption = NoOptions); + QTUITEST_EXPORT void mouseMove (const QPoint&, InputOption = NoOptions); + + QTUITEST_EXPORT void keyPress (int,Qt::KeyboardModifiers = 0, + InputOption = NoOptions); + QTUITEST_EXPORT void keyRelease(int,Qt::KeyboardModifiers = 0, + InputOption = NoOptions); + QTUITEST_EXPORT void keyClick (int,Qt::KeyboardModifiers = 0, + InputOption = NoOptions); + QTUITEST_EXPORT bool keyClick (QObject*,int,Qt::KeyboardModifiers = 0, + InputOption = NoOptions); + QTUITEST_EXPORT bool keyClick (QObject*,const QByteArray&,int,Qt::KeyboardModifiers = 0, + InputOption = NoOptions); + + QTUITEST_EXPORT int maximumUiTimeout(); + + QTUITEST_EXPORT Qt::Key asciiToKey(char); + QTUITEST_EXPORT Qt::Key variantToKey(const QVariant &); + QTUITEST_EXPORT Qt::KeyboardModifiers asciiToModifiers(char); + + QTUITEST_EXPORT QObject* testWidget(QObject*,const char*); + + QTUITEST_EXPORT bool connectFirst (const QObject*, const char*, const QObject*, const char*); + QTUITEST_EXPORT bool disconnectFirst(const QObject*, const char*, const QObject*, const char*); + + template<class T> inline T qtuitest_cast_helper(QObject* object, T) + { + T ret; + if ((ret = qobject_cast<T>(object))) {} + else { + ret = qobject_cast<T>(QtUiTest::testWidget(object, + static_cast<T>(0)->_q_interfaceName())); + } + return ret; + } + + QTUITEST_EXPORT void wait(int); + QTUITEST_EXPORT bool waitForSignal(QObject*, const char*, int = QtUiTest::maximumUiTimeout(), Qt::ConnectionType = Qt::QueuedConnection); + QTUITEST_EXPORT bool waitForEvent(QObject*, QEvent::Type, int = QtUiTest::maximumUiTimeout(), Qt::ConnectionType = Qt::QueuedConnection); + QTUITEST_EXPORT bool waitForEvent(QObject*, QList<QEvent::Type> const&, int = QtUiTest::maximumUiTimeout(), Qt::ConnectionType = Qt::QueuedConnection); + + QTUITEST_EXPORT char keyToAscii(Qt::Key key); +}; + +template<class T> inline +T qtuitest_cast(const QObject* object) +{ + return QtUiTest::qtuitest_cast_helper<T>(const_cast<QObject*>(object),0); +} + +#include "qtuitestwidgetinterface.h" + +#endif + diff --git a/src/remote/slave/lib/qtuitestwidgetinterface.cpp b/src/remote/slave/lib/qtuitestwidgetinterface.cpp new file mode 100644 index 0000000..126efcd --- /dev/null +++ b/src/remote/slave/lib/qtuitestwidgetinterface.cpp @@ -0,0 +1,398 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qtuitestwidgetinterface.h" +#include "qtuitestnamespace.h" + +#include <QRect> +#include <QRegion> +#include <QVariant> + +/*! + \preliminary + \class QtUiTest::WidgetFactory + \inpublicgroup QtUiTestModule + \brief The WidgetFactory class provides a factory interface + for QtUiTest widget wrapper classes. + + QtUiTest::WidgetFactory is an abstract base class which enables the + creation of QtUiTest wrapper objects around Qt widgets. + + Customizing QtUiTest behaviour for particular widgets is achieved by + implementing one or more test widget classes which inherit from + one or more QtUiTest widget interfaces, + subclassing QtUiTest::WidgetFactory, reimplementing the pure virtual + keys() and create() functions to create instances of the custom test + widget classes, and exporting the factory class using the + Q_EXPORT_PLUGIN2() macro. +*/ + +/*! + \fn QtUiTest::WidgetFactory::create(QObject* object) + + Attempts to create a test widget to wrap \a object. Returns the created + test widget. Returns 0 if this factory does not support wrapping + \a object. + + The returned object is suitable for use with + \l{QtUiTest}{qtuitest_cast}. + + This function will only be called for objects which inherit one of the + classes returned by keys(). +*/ + +/*! + \fn QtUiTest::WidgetFactory::keys() const + + Returns the list of C++ class names this factory can generate test widgets + for. + + Note that returning a class from this function does not guarantee that the + factory will always be able to generate a test widget for that class. +*/ + +/*! + \preliminary + \class QtUiTest::Widget + \inpublicgroup QtUiTestModule + \brief The Widget class provides an abstract base class + for all test widgets. + + QtUiTest::Widget encapsulates important information + and functionality related to two-dimensional GUI elements. + + All test widgets should implement the QtUiTest::Widget interface, + using multiple inheritance to implement other QtUiTest interfaces + where suitable. +*/ + +/*! + \fn const QRect& QtUiTest::Widget::geometry() const + + Returns the geometry of this widget in parent coordinates. +*/ + +/*! + Returns the left of the widget, in global coordinates. + + \sa mapToGlobal() +*/ +int QtUiTest::Widget::x() const +{ + return mapToGlobal(QPoint()).x(); +} + +/*! + Returns the top of the widget, in global coordinates. + + \sa mapToGlobal() +*/ +int QtUiTest::Widget::y() const +{ + return mapToGlobal(QPoint()).y(); +} + +/*! + Returns the width of the widget. + + \sa geometry() +*/ +int QtUiTest::Widget::width() const +{ + return geometry().width(); +} + +/*! + Returns the height of the widget. + + \sa geometry() +*/ +int QtUiTest::Widget::height() const +{ + return geometry().height(); +} + +/*! + \fn bool QtUiTest::Widget::isVisible() const + + Returns true if this widget is currently visible. +*/ + +/*! + \fn QObject* QtUiTest::Widget::parent() const + + Returns the parent of this widget, or 0 if this widget has no parent. + + The returned object may be an actual widget, or may be a wrapping + test widget. Therefore, the only safe way to use the returned value + of this function is to cast it to the desired QtUiTest interface + using \l{QtUiTest}{qtuitest_cast}. + + \sa QObject::parent(), children() +*/ + +/*! + \fn const QObjectList& QtUiTest::Widget::children() const + + Returns all children of this widget. + + The returned objects may be actual widget instances, or may be wrapping + test widgets. Therefore, the only safe way to use the returned objects + are to cast them to the desired QtUiTest interface using + \l{QtUiTest}{qtuitest_cast}. + + Reimplementing this function allows widgets which are conceptually + widgets but are not QObject subclasses to be wrapped. This can be + achieved by returning a list of test widgets which do not necessarily + have underlying widget instances. + + \sa QObject::children(), parent() +*/ + +/*! + \internal + + Returns all ancestors of this widget. + + \sa children(), parent() +*/ +QObjectList QtUiTest::Object::ancestors() const +{ + QObjectList found; + QObject *p = parent(); + if (p) { + QtUiTest::Object* qw = qtuitest_cast<QtUiTest::Object*>(p); + found << p << qw->ancestors(); + } + return found; +} + +/*! + \internal + + Returns all descendants of this widget. The results are appended to \a descendants. + + \sa children(), parent() +*/ +void QtUiTest::Object::descendants(QSet<QObject*> &descendants) const +{ + foreach (QObject *child, children()) { + if (!descendants.contains(child)) { + descendants.insert(child); + QtUiTest::Object* qw = qtuitest_cast<QtUiTest::Object*>(child); + if (qw) + qw->descendants(descendants); + } + } +} + +/*! + \internal + + Convenience function to return descendants as QObjectList. + + \sa ancestors() +*/ +QObjectList QtUiTest::Object::descendants() const +{ + QSet<QObject*> found; + descendants(found); + return QObjectList::fromSet(found); +} + +/*! + \fn QPoint QtUiTest::Widget::mapToGlobal(const QPoint& pos) const + + Maps \a pos from widget coordinates to global screen coordinates and + returns the result. +*/ + +/*! + \fn QPoint QtUiTest::Widget::mapFromGlobal(const QPoint& pos) const + + Maps \a pos from global screen coordinates to widget coordinates and + returns the result. +*/ + +/*! + Returns the center point of the widget. The base implementation + returns geometry().center(). + + \sa QtUiTest::Widget::geometry() +*/ +QPoint QtUiTest::Widget::center() const +{ + QPoint ret; + ret = mapToGlobal( geometry().center() ); + return ret; +} + +/*! + \fn bool QtUiTest::Widget::hasFocus() const + Returns true if this widget currently has keyboard focus. +*/ + +/*! + Returns the focus proxy of this widget, or 0 if this widget has no focus proxy. + A widget may "have focus", but have a child widget that actually handles the + focus. + + The returned object may be an actual widget, or may be a wrapping + test widget. Therefore, the only safe way to use the returned value + of this function is to cast it to the desired QtUiTest interface + using \l{QtUiTest}{qtuitest_cast}. + +*/ +QObject* QtUiTest::Widget::focusProxy() const +{ + return 0; +} + +/*! + Sets \a img to image of the widget. Returns true on success. + + The base implementation always returns false. +*/ +bool QtUiTest::Widget::grabImage(QImage &img) const +{ Q_UNUSED(img); return false; } + +/*! + Returns true if this widget should be ignored by QtUiTest. If + a widget is ignored, any child widgets will still be processed. + + The base implementation always returns false. + + \sa {Widget Specifiers}, {Querying Objects} +*/ +bool QtUiTest::Widget::ignoreScan() const +{ return false; } + +/*! + Returns the widget's window. +*/ +QObject* QtUiTest::Widget::window() const +{ + return 0; +} +/*! + Returns the value of this widget's property specified by \a property. + + \sa setProperty() +*/ +QVariant QtUiTest::Object::getProperty(const QString& property) const +{ + Q_UNUSED(property) + return QVariant(); +} + +/*! + Sets the value of this widget's property specified by \a property to \a value. + Returns true on success, and false if the property could not be set. + + \sa getProperty() +*/ +bool QtUiTest::Object::setProperty(const QString &property, const QVariant &value) +{ + Q_UNUSED(property) + Q_UNUSED(value) + return false; +} + +/*! + Return true if this widget matches the \a value of pseudo-property \a property. + + \sa getProperty() +*/ +bool QtUiTest::Object::matchProperty(const QString &property, const QVariant &value) const +{ + Q_UNUSED(property) + Q_UNUSED(value) + return false; +} + +/*! + Returns a map containing all the widget's properties. + + \sa getProperty() +*/ +QVariantMap QtUiTest::Object::getProperties() const +{ + return QVariantMap(); +} + +QVariantList QtUiTest::Object::resources() const +{ + QVariantList ret; + return ret; +} + +/*! + Returns the type of widget. +*/ +QString QtUiTest::Object::typeOf() const +{ + return QString(); +} + +/*! + Returns the widget's list of superclasses. +*/ +QStringList QtUiTest::Object::inheritance() const +{ + return QStringList(); +} + +/*! + Returns true if the item has displayable contents. +*/ +bool QtUiTest::Object::hasContents() const +{ + return false; +} + +/*! + Returns a string value for debugging purposes. +*/ +QString QtUiTest::Object::debugString() const +{ + return QString(); +} diff --git a/src/remote/slave/lib/qtuitestwidgetinterface.h b/src/remote/slave/lib/qtuitestwidgetinterface.h new file mode 100644 index 0000000..1e5e5b9 --- /dev/null +++ b/src/remote/slave/lib/qtuitestwidgetinterface.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITESTWIDGETINTERFACE_H +#define QTUITESTWIDGETINTERFACE_H + +#include <QStringList> +#include <QVariantList> +#include <QSet> +#include <QtGlobal> + +#include <QtSystemTest/qstglobal.h> + +#include "qtuitestnamespace.h" + +class QRect; +class QRegion; +class QPoint; +class QWindow; + +namespace QtUiTest +{ + template<class T> T qtuitest_cast_helper(QObject*,T); + +#define QTUITEST_INTERFACE(Klass) \ + public: \ + virtual ~Klass() {} \ + static const char* _q_interfaceName() { return #Klass; } \ + private: \ + template<class T> friend T qtuitest_cast_helper(QObject*,T); + + class QTUITEST_EXPORT WidgetFactory + { + QTUITEST_INTERFACE(WidgetFactory) + public: + virtual QObject* create(QObject*) = 0; + virtual QStringList keys() const = 0; + }; + + class QTUITEST_EXPORT Object + { + QTUITEST_INTERFACE(Object) + public: + virtual QObject* parent() const = 0; + virtual const QObjectList children() const = 0; + QObjectList ancestors() const; + virtual void descendants(QSet<QObject*> &descendants) const; + QObjectList descendants() const; + virtual QVariant getProperty(const QString&) const; + virtual bool setProperty(const QString&, const QVariant&); + virtual bool matchProperty(const QString&, const QVariant&) const; + virtual QVariantMap getProperties() const; + virtual QString typeOf() const; + virtual QStringList inheritance() const; + virtual QVariantList resources() const; + virtual bool hasContents() const; + virtual QString debugString() const; + }; + + class QTUITEST_EXPORT Widget + { + QTUITEST_INTERFACE(Widget) + public: + virtual QRect geometry() const = 0; + virtual int x() const; + virtual int y() const; + virtual int width() const; + virtual int height() const; + virtual bool isVisible() const = 0; + virtual QPoint mapToGlobal(const QPoint&) const = 0; + virtual QPoint mapFromGlobal(const QPoint&) const = 0; + virtual QRect mapToGlobal(const QRect&) const = 0; + virtual QRect mapFromGlobal(const QRect&) const = 0; + virtual QPoint center() const; + virtual bool hasFocus() const = 0; + virtual QObject* focusProxy() const; + virtual bool grabImage(QImage &img) const; + virtual bool ignoreScan() const; + virtual QObject* window() const; + }; + +}; + +Q_DECLARE_INTERFACE( + QtUiTest::WidgetFactory, + "com.nokia.qt.QtUiTest.WidgetFactory/1.0") +Q_DECLARE_INTERFACE( + QtUiTest::Object, + "com.nokia.qt.QtUiTest.Object/1.0") +Q_DECLARE_INTERFACE( + QtUiTest::Widget, + "com.nokia.qt.QtUiTest.Widget/1.0") +#endif + diff --git a/src/remote/slave/lib/qtuitestwidgets.cpp b/src/remote/slave/lib/qtuitestwidgets.cpp new file mode 100644 index 0000000..b27e6f5 --- /dev/null +++ b/src/remote/slave/lib/qtuitestwidgets.cpp @@ -0,0 +1,648 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qinputgenerator_p.h" +#include "qtuitestwidgetinterface.h" +#include "qtuitestwidgets_p.h" +#include "testquickfactory.h" + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + #include "qinputgenerator_qwindow_p.h" +#else + #include "qinputgenerator_generic_p.h" +#endif + +#include <QtSystemTest/QstDebug> + +/* + If the QTUITEST_INPUT_DELAY environment variable is set, all calls to keyClick etc will + immediately return but the resulting event won't be generated until QTUITEST_INPUT_DELAY + milliseconds have passed. + This can be used to simulate a slow system to catch race conditions. + For example, setting QTUITEST_INPUT_DELAY to 500 roughly simulates running with a remote X + server over a link with a round trip time of 250ms. +*/ + +#include <QDir> +#include <QPluginLoader> +#include <QPointer> +#include <QStringList> +#include <QTimer> +#include <QPoint> + +/*! + \internal + \class QtUiTestWidgets + \brief The QtUiTestWidgets class provides an interface for creating and managing QtUiTest widgets. + + QtUiTestWidgets manages the lifetime of all test widgets and allows + test widgets to simulate user interaction with the application. +*/ + +enum QtUiTestInputType { QtUiTestPress, QtUiTestRelease, QtUiTestClick, QtUiTestDClick, QtUiTestMove }; +struct QtUiTestKeyEvent +{ + QtUiTestInputType type; + Qt::Key key; + Qt::KeyboardModifiers mod; + QtUiTest::InputOption opt; +}; +struct QtUiTestMouseEvent +{ + QtUiTestInputType type; + QPoint pos; + Qt::MouseButtons state; + QtUiTest::InputOption opt; +}; +struct QtUiTestTouchEvent +{ + QtUiTestInputType type; + QVariantList points; +}; +static int qtUiTestGetInputDelay() +{ + bool ok; + QByteArray value(qgetenv("QTUITEST_INPUT_DELAY")); + int ret = value.toInt(&ok); + if (!ok || ret < 0) ret = 0;//-1; + return ret; +} +static int qtUiTestInputDelay() +{ static int ret = qtUiTestGetInputDelay(); return ret; } + + +class QtUiTestWidgetsPrivate +{ +public: + QtUiTestWidgetsPrivate(QtUiTestWidgets* parent); + + static QList<QByteArray> allImplementedInterfaces(QObject *o); + + void _q_objectDestroyed(); + + QString currentInputMethod() const; + + QtUiTestWidgets* q; + + QHash< QByteArray, QSet<QtUiTest::WidgetFactory*> > factories; + QHash< QObject*, QHash<QByteArray, QPointer<QObject> > > testWidgets; + QSet< QtUiTest::WidgetFactory* > factorySet; + + int inputOptions; + + QString errorString; + QString debugBuffer; + + QInputGenerator *input; + + QList<QtUiTestKeyEvent> pendingKeyEvents; + QList<QtUiTestMouseEvent> pendingMouseEvents; + QList<QtUiTestTouchEvent> pendingTouchEvents; + void _q_postNextKeyEvent(); + void _q_postNextMouseEvent(); + void _q_postNextTouchEvent(); +}; + +class QTWOptStack +{ +public: + QTWOptStack(QtUiTestWidgetsPrivate* obj, + QtUiTest::InputOption opt) + : d(obj), option(opt) + { + if (opt && (!(d->inputOptions & opt))) { + d->inputOptions |= opt; + } else { + d = 0; + } + } + + ~QTWOptStack() + { + if (d) { + d->inputOptions &= ~option; + } + } + + QtUiTestWidgetsPrivate *d; + QtUiTest::InputOption option; +}; + +QtUiTestWidgetsPrivate::QtUiTestWidgetsPrivate(QtUiTestWidgets* parent) + : q(parent),input(0), + inputOptions(QtUiTest::NoOptions) +{ + QTT_TRACE_FUNCTION(); +} + +QtUiTestWidgets::QtUiTestWidgets() + : QObject(), + d(new QtUiTestWidgetsPrivate(this)) +{ + QTT_TRACE_FUNCTION(); + d->input = new QInputGeneratorGeneric(); + refreshPlugins(); +} + +QtUiTestWidgets::~QtUiTestWidgets() +{ + QTT_TRACE_FUNCTION(); + delete d->input; + delete d; + d = 0; +} + +/*! + Returns a static instance of QtUiTestWidgets. +*/ +QtUiTestWidgets* QtUiTestWidgets::instance() +{ + static QtUiTestWidgets instance; + return &instance; +} + +/*! + When an object is destroyed, deletes all test widgets pointing + to that object. +*/ +void QtUiTestWidgetsPrivate::_q_objectDestroyed() +{ + QTT_TRACE_FUNCTION(); + QHash< QByteArray, QPointer<QObject> > toDestroy + = testWidgets.take(q->sender()); + + foreach (QPointer<QObject> tw, toDestroy.values()) { + if (tw) delete tw; + } +} + +/*! + \internal + Destroy all test widgets and unregister all factories. + After calling this, refreshPlugins() must be called to be able to + construct testwidgets from factories. + + For testing purposes only. +*/ +void QtUiTestWidgets::clear() +{ + QTT_TRACE_FUNCTION(); + d->factories.clear(); + d->factorySet.clear(); + + foreach (QObject *o, d->testWidgets.keys()) { + foreach (QPointer<QObject> tw, d->testWidgets[o].values()) { + if (tw && tw != o) delete tw; + } + } + d->testWidgets.clear(); +} + +void QtUiTestWidgets::refreshPlugins() +{ + registerFactory(new TestQuickFactory()); +} + +/*! + Registers \a factory as a factory class for constructing test widgets. + + It is not necessary to explicitly call this from QtUiTest widget plugins. + This function should only be called if a QtUiTest::WidgetFactory has been + created without using the standard plugin interface. +*/ +void +QtUiTestWidgets::registerFactory(QtUiTest::WidgetFactory* factory) +{ + QTT_TRACE_FUNCTION(); + if (!factory) return; + + d->factorySet << factory; + foreach(QString k, factory->keys()) { + d->factories[k.toLatin1()].insert(factory); + } +} + +/*! + Returns a human-readable error string describing the last error which + occurred while accessing a testwidget. + + The error string is used to report directly to a tester any unexpected + errors. The string will typically be used as a test failure message. + + \sa setErrorString() +*/ +QString QtUiTestWidgets::errorString() const +{ return d->errorString; } + +/*! + Sets the human-readable \a error string describing the last error which + occurred while accessing a testwidget. + + \sa errorString() +*/ +void QtUiTestWidgets::setErrorString(const QString& error) +{ + if (error == d->errorString) return; + d->errorString = error; +} + +/*! + Returns a QDebug object which can be used as an output stream for debugging + information. The debug information is sent to the test runner for output. + This ensures a consistent handling of debugging information on different + test platforms. +*/ +QDebug QtUiTestWidgets::debug() const +{ + return QDebug(&d->debugBuffer) << '\n'; +} + +/*! + \internal +*/ +QString QtUiTestWidgets::debugOutput() +{ + QString ret = d->debugBuffer; + d->debugBuffer.clear(); + return ret; +} + +/*! + Returns a list of all QtUiTest widget interfaces implemented by \a o . +*/ +QList<QByteArray> QtUiTestWidgetsPrivate::allImplementedInterfaces(QObject *o) +{ + QTT_TRACE_FUNCTION(); + // FIXME this function should not have to be explicitly implemented. + // Find some way to automatically handle all interfaces. + QList<QByteArray> ret; + if (qobject_cast<QtUiTest::Object*>(o)) ret << "Object"; + if (qobject_cast<QtUiTest::Widget*>(o)) ret << "Widget"; + return ret; +} + +/*! + Returns a test widget wrapper for \a object implementing the given + \a interface. If a test widget implementing \a interface is already + wrapping \a object, that test widget will be returned. Otherwise, + a new test widget may be constructed using registered factories. + + Returns 0 if the given \a interface is not implemented on \a object + or on any test widget which wraps \a object. + + The returned object should not be deleted by the caller. QtUiTestWidgets + retains ownership of the returned test widget and deletes it when \a object + is destroyed. + + \sa registerFactory() +*/ +QObject* QtUiTestWidgets::testWidget(QObject* object, const QByteArray &interface) +{ + if (!object) return 0; + + QMetaObject const *mo = object->metaObject(); + QObject *ret = d->testWidgets.value( object ).value( interface ); + + bool watchingDestroyed = false; + + if (!ret) { + QSet<QtUiTest::WidgetFactory*> usedFactories; + while (mo) { + foreach (QtUiTest::WidgetFactory *factory, + d->factories.value(mo->className()) - usedFactories) { + + QObject *testWidget = factory->create(object); + usedFactories.insert(factory); + if (testWidget) { + bool isValuable = false; + foreach (const QByteArray& thisIface, + d->allImplementedInterfaces(testWidget)) { + QHash<QByteArray, QPointer<QObject> > &subhash + = d->testWidgets[object]; + if (!subhash[thisIface]) { + isValuable = true; + subhash.insert( thisIface, testWidget ); + watchingDestroyed = watchingDestroyed + || connect(object, SIGNAL(destroyed()), + this, SLOT(_q_objectDestroyed())); + } + } + if (!isValuable) { + delete testWidget; + } + } + } + mo = mo->superClass(); + } + ret = d->testWidgets.value( object ).value( interface ); + } + return ret; +} + +/*! + Simulate a mouse press event at the global co-ordinates given by \a pos, + for the buttons in \a state. \a opt is applied to the simulated event. +*/ +void QtUiTestWidgets::mousePress(const QPoint &pos, Qt::MouseButtons state, + QtUiTest::InputOption opt) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestMouseEvent event = {QtUiTestPress, pos, state, opt}; + d->pendingMouseEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextMouseEvent())); + return; + } + + QTWOptStack st(d, opt); + d->input->mousePress(pos, state); +} + +void QtUiTestWidgets::touchPress(const QVariantList &points) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestTouchEvent event = {QtUiTestPress, points }; + d->pendingTouchEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextTouchEvent())); + return; + } + + d->input->touchPress(points); +} + +void QtUiTestWidgets::touchUpdate(const QVariantList &points) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestTouchEvent event = {QtUiTestMove, points}; + d->pendingTouchEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextTouchEvent())); + return; + } + + d->input->touchUpdate(points); +} + +void QtUiTestWidgets::touchRelease(const QVariantList &points) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestTouchEvent event = {QtUiTestRelease, points}; + d->pendingTouchEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextTouchEvent())); + return; + } + + d->input->touchRelease(points); +} + +/*! + Simulate a mouse release event at the global co-ordinates given by \a pos, + for the buttons in \a state. \a opt is applied to the simulated event. +*/ +void QtUiTestWidgets::mouseRelease(const QPoint &pos, Qt::MouseButtons state, + QtUiTest::InputOption opt) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestMouseEvent event = {QtUiTestRelease, pos, state, opt}; + d->pendingMouseEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextMouseEvent())); + return; + } + + QTWOptStack st(d, opt); + d->input->mouseRelease(pos, state); +} + +/*! + Simulate a mouse click event at the global co-ordinates given by \a pos, + for the buttons in \a state. \a opt is applied to the simulated event. +*/ +void QtUiTestWidgets::mouseClick(const QPoint &pos, Qt::MouseButtons state, + QtUiTest::InputOption opt) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestMouseEvent event = {QtUiTestClick, pos, state, opt}; + d->pendingMouseEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextMouseEvent())); + return; + } + + QTWOptStack st(d, opt); + d->input->mouseClick(pos, state); +} + +/*! + Simulate a mouse double-click event at the global co-ordinates given by \a pos, + for the buttons in \a state. \a opt is applied to the simulated event. +*/ +void QtUiTestWidgets::mouseDClick(const QPoint &pos, Qt::MouseButtons state, + QtUiTest::InputOption opt) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestMouseEvent event = {QtUiTestDClick, pos, state, opt}; + d->pendingMouseEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextMouseEvent())); + return; + } + + QTWOptStack st(d, opt); + d->input->mouseDClick(pos, state); +} + +/*! + Simulate moving the mouse pointer to global co-ordinates given by \a pos, + \a opt is applied to the simulated event. +*/ +void QtUiTestWidgets::mouseMove(const QPoint &pos, QtUiTest::InputOption opt) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestMouseEvent event = {QtUiTestMove, pos, 0, opt}; + d->pendingMouseEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextMouseEvent())); + return; + } + + QTWOptStack st(d, opt); + d->input->mouseMove(pos); +} + +/*! + Simulate a key press event, using the given \a key and \a mod. + \a opt is applied to the simulated event. +*/ +void QtUiTestWidgets::keyPress(Qt::Key key, Qt::KeyboardModifiers mod, + QtUiTest::InputOption opt) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestKeyEvent event = {QtUiTestPress, key, mod, opt}; + d->pendingKeyEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextKeyEvent())); + return; + } + + QTWOptStack st(d, opt); + d->input->keyPress(key, mod, opt & QtUiTest::KeyRepeat); +} + +/*! + Simulate a key release event, using the given \a key and \a mod. + \a opt is applied to the simulated event. +*/ +void QtUiTestWidgets::keyRelease(Qt::Key key, Qt::KeyboardModifiers mod, + QtUiTest::InputOption opt) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestKeyEvent event = {QtUiTestRelease, key, mod, opt}; + d->pendingKeyEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextKeyEvent())); + return; + } + + QTWOptStack st(d, opt); + d->input->keyRelease(key, mod); +} + +/*! + Simulate a key click event, using the given \a key and \a mod. + \a opt is applied to the simulated event. +*/ +void QtUiTestWidgets::keyClick(Qt::Key key, Qt::KeyboardModifiers mod, + QtUiTest::InputOption opt) +{ + QTT_TRACE_FUNCTION(); + int delay; + if ((delay = qtUiTestInputDelay()) != -1) { + QtUiTestKeyEvent event = {QtUiTestClick, key, mod, opt}; + d->pendingKeyEvents << event; + QTimer::singleShot(delay, this, SLOT(_q_postNextKeyEvent())); + return; + } + + QTWOptStack st(d, opt); + d->input->keyClick(key, mod); +} + +void QtUiTestWidgetsPrivate::_q_postNextMouseEvent() +{ + QTT_TRACE_FUNCTION(); + QtUiTestMouseEvent const event = pendingMouseEvents.takeAt(0); + QTWOptStack st(this, event.opt); + if (event.type == QtUiTestPress) + input->mousePress(event.pos, event.state); + else if (event.type == QtUiTestRelease) + input->mouseRelease(event.pos, event.state); + else if (event.type == QtUiTestClick) + input->mouseClick(event.pos, event.state); + else if (event.type == QtUiTestDClick) + input->mouseDClick(event.pos, event.state); + else if (event.type == QtUiTestMove) + input->mouseMove(event.pos); +} + +void QtUiTestWidgetsPrivate::_q_postNextTouchEvent() +{ + QTT_TRACE_FUNCTION(); + QtUiTestTouchEvent const event = pendingTouchEvents.takeAt(0); + if (event.type == QtUiTestPress) + input->touchPress(event.points); + else if (event.type == QtUiTestRelease) + input->touchRelease(event.points); + else if (event.type == QtUiTestMove) + input->touchUpdate(event.points); +} + +void QtUiTestWidgetsPrivate::_q_postNextKeyEvent() +{ + QTT_TRACE_FUNCTION(); + QtUiTestKeyEvent const event = pendingKeyEvents.takeAt(0); + QTWOptStack st(this, event.opt); + if (event.type == QtUiTestPress) + input->keyPress(event.key, event.mod); + else if (event.type == QtUiTestRelease) + input->keyRelease(event.key, event.mod); + else if (event.type == QtUiTestClick) + input->keyClick(event.key, event.mod); +} + +/*! + Set or clear the specified \a option for subsequent simulated input + events. The option is set if \a on is true, otherwise it is cleared. +*/ +void QtUiTestWidgets::setInputOption(QtUiTest::InputOption option, bool on) +{ + QTT_TRACE_FUNCTION(); + if (on) + d->inputOptions |= option; + else + d->inputOptions &= (~option); + qttDebug() << "Set input options to" << d->inputOptions; +} + +/*! + Returns true if \a option is currently set. +*/ +bool QtUiTestWidgets::testInputOption(QtUiTest::InputOption option) const +{ + QTT_TRACE_FUNCTION(); + return (option == d->inputOptions) + || (option & d->inputOptions); +} + +#include "moc_qtuitestwidgets_p.cpp" diff --git a/src/remote/slave/lib/qtuitestwidgets_p.h b/src/remote/slave/lib/qtuitestwidgets_p.h new file mode 100644 index 0000000..422f3aa --- /dev/null +++ b/src/remote/slave/lib/qtuitestwidgets_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTUITESTWIDGETS_P_H +#define QTUITESTWIDGETS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtUiTest API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QObject> +#include <QMetaType> +#include <QHash> +#include <Qt> + +#include "qtuitestnamespace.h" + +class QtUiTestWidgetsPrivate; +class QPoint; + +class QTUITEST_EXPORT QtUiTestWidgets : public QObject +{ + Q_OBJECT + +public: + static QtUiTestWidgets* instance(); + + virtual ~QtUiTestWidgets(); + + void setInputOption(QtUiTest::InputOption,bool = true); + bool testInputOption(QtUiTest::InputOption) const; + + QString errorString() const; + void setErrorString(const QString&); + QDebug debug() const; + QString debugOutput(); + + void registerFactory(QtUiTest::WidgetFactory*); + + void touchPress(const QVariantList &); + void touchUpdate(const QVariantList &); + void touchRelease(const QVariantList &); + + void mousePress (const QPoint&,Qt::MouseButtons = Qt::LeftButton, + QtUiTest::InputOption = QtUiTest::NoOptions); + void mouseRelease(const QPoint&,Qt::MouseButtons = Qt::LeftButton, + QtUiTest::InputOption = QtUiTest::NoOptions); + void mouseClick (const QPoint&,Qt::MouseButtons = Qt::LeftButton, + QtUiTest::InputOption = QtUiTest::NoOptions); + void mouseDClick (const QPoint&,Qt::MouseButtons = Qt::LeftButton, + QtUiTest::InputOption = QtUiTest::NoOptions); + void mouseMove (const QPoint&, QtUiTest::InputOption = QtUiTest::NoOptions); + + void keyPress (Qt::Key,Qt::KeyboardModifiers = 0,QtUiTest::InputOption = QtUiTest::NoOptions); + void keyRelease(Qt::Key,Qt::KeyboardModifiers = 0,QtUiTest::InputOption = QtUiTest::NoOptions); + void keyClick (Qt::Key,Qt::KeyboardModifiers = 0,QtUiTest::InputOption = QtUiTest::NoOptions); + +private: + Q_DISABLE_COPY(QtUiTestWidgets) + + friend class QtUiTestWidgetsPrivate; + + QtUiTestWidgetsPrivate* d; + + QtUiTestWidgets(); + QObject* testWidget(QObject*,const QByteArray&); + + void refreshPlugins(); + void clear(); + + Q_PRIVATE_SLOT(d, void _q_objectDestroyed()) + Q_PRIVATE_SLOT(d, void _q_postNextKeyEvent()) + Q_PRIVATE_SLOT(d, void _q_postNextMouseEvent()) + Q_PRIVATE_SLOT(d, void _q_postNextTouchEvent()) + + friend QObject* QtUiTest::testWidget(QObject*,const char*); +}; + +#endif + diff --git a/src/remote/slave/lib/testapplication.cpp b/src/remote/slave/lib/testapplication.cpp new file mode 100644 index 0000000..c179da5 --- /dev/null +++ b/src/remote/slave/lib/testapplication.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testapplication.h" + +#include <QDebug> +#include <QApplication> +#include <QWidget> +#include <QScreen> + +TestApplication::TestApplication(QApplication* _q) + : TestObject(_q) +{} + +TestApplication::~TestApplication() +{ +} + +const QObjectList TestApplication::children() const +{ + QObjectList ret; + + foreach (QWidget *w, qApp->topLevelWidgets()) { + if (!w->parent()) + ret << w; + } + + return ret; +} diff --git a/src/remote/slave/lib/testapplication.h b/src/remote/slave/lib/testapplication.h new file mode 100644 index 0000000..4d50da7 --- /dev/null +++ b/src/remote/slave/lib/testapplication.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef TEST_APPLICATION_H +#define TEST_APPLICATION_H + +#include "testobject.h" +#include "qtuitestwidgetinterface.h" + +class QApplication; + +class TestApplication : public TestObject +{ + Q_OBJECT + Q_INTERFACES(QtUiTest::Object) + +public: + TestApplication(QApplication*); + ~TestApplication(); + + virtual const QObjectList children() const; + virtual QObject* parent() const { return 0; } + +protected: + QApplication *q; + +}; + +#endif + diff --git a/src/remote/slave/lib/testobject.cpp b/src/remote/slave/lib/testobject.cpp new file mode 100644 index 0000000..6aef76d --- /dev/null +++ b/src/remote/slave/lib/testobject.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testobject.h" + +#include <QMetaObject> +#include <QMetaProperty> + +const QLatin1String TestObject::classNameProperty("CLASSNAME"); +const QLatin1String TestObject::hasContentsProperty("HAS_CONTENTS"); +const QLatin1String TestObject::inheritsProperty("INHERITS"); +const QLatin1String TestObject::propertyProperty("PROPERTY"); + +TestObject::TestObject(QObject* _q) + : q(_q) +{ +} + +QObject* TestObject::parent() const +{ + return 0; +} + +QVariant TestObject::getProperty(const QString& name) const +{ + return q->property(name.toLocal8Bit()); +} + +bool TestObject::setProperty(const QString& name, const QVariant& value) +{ + return q->setProperty(name.toAscii(), value); +} + +bool TestObject::matchProperty(const QString& propertyUpper, const QVariant &value) const +{ + return (propertyUpper == propertyProperty && getProperty(value.toString()).isValid()) + || (propertyUpper == classNameProperty && q->metaObject()->className() == value) + || (propertyUpper == inheritsProperty && q->inherits(value.toString().toLatin1())); +} + +QVariantMap TestObject::getProperties() const +{ + QVariantMap map; + const QMetaObject *mo = q->metaObject(); + for (int i=0; i<mo->propertyCount(); i++) { + map[mo->property(i).name()] = getProperty(mo->property(i).name()); + } + foreach (const QByteArray &prop, q->dynamicPropertyNames()) { + map[prop] = getProperty(prop); + } + return map; +} + +QString TestObject::typeOf() const +{ + return q->metaObject()->className(); +} + +QStringList TestObject::inheritance() const +{ + QStringList ret; + + const QMetaObject *mo = q->metaObject(); + + while (mo) { + ret << mo->className(); + mo = mo->superClass(); + } + + return ret; +}
\ No newline at end of file diff --git a/src/remote/slave/lib/testobject.h b/src/remote/slave/lib/testobject.h new file mode 100644 index 0000000..4c909c3 --- /dev/null +++ b/src/remote/slave/lib/testobject.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef TEST_OBJECT_H +#define TEST_OBJECT_H + +#include "qtuitestwidgetinterface.h" + +class TestObject : public QObject, + public QtUiTest::Object +{ + Q_OBJECT + Q_INTERFACES(QtUiTest::Object) + +public: + + TestObject(QObject*); + + virtual QObject* parent() const; + virtual QVariant getProperty(const QString&) const; + virtual bool setProperty(const QString&, const QVariant&); + virtual bool matchProperty(const QString&, const QVariant&) const; + virtual QVariantMap getProperties() const; + virtual QString typeOf() const; + virtual QStringList inheritance() const; + +protected: + static const QLatin1String classNameProperty; + static const QLatin1String hasContentsProperty; + static const QLatin1String inheritsProperty; + static const QLatin1String propertyProperty; + + QObject* q; +}; + +#endif diff --git a/src/remote/slave/lib/testquickfactory.cpp b/src/remote/slave/lib/testquickfactory.cpp new file mode 100644 index 0000000..b4dd2a5 --- /dev/null +++ b/src/remote/slave/lib/testquickfactory.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testapplication.h" +#include "testquickfactory.h" + +#include "testwidget.h" +#include <QWidget> +#include <QApplication> + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + #include "testquickitem.h" + #include "testquickobject.h" + #include "testquickview.h" + #include "testwindow.h" + #include <QQuickView> + #include <QQuickItem> + #include <QWindow> +#endif + +TestQuickFactory::TestQuickFactory() +{ +} + +QObject* TestQuickFactory::create(QObject* o) +{ + if (o->isWidgetType()) return new TestWidget(qobject_cast<QWidget*>(o)); + + QApplication *app = qobject_cast<QApplication*>(o); + if (app) return new TestApplication(app); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + QQuickView *view = qobject_cast<QQuickView*>(o); + if (view) return new TestQuickView(view); + + QQuickItem *item = qobject_cast<QQuickItem*>(o); + if (item) return new TestQuickItem(item); + + QWindow *window = qobject_cast<QWindow*>(o); + if (window) return new TestWindow(window); + + return new TestQuickObject(o); +#else + // FIXME: Need support for Quick 1! + return 0; +#endif +} + +QStringList TestQuickFactory::keys() const +{ + return QStringList() + << "QQuickItem" + << "QQuickView" + << "QWindow" + << "QGuiApplication" + << "QObject" + ; +} diff --git a/src/remote/slave/lib/testquickfactory.h b/src/remote/slave/lib/testquickfactory.h new file mode 100644 index 0000000..7bc5286 --- /dev/null +++ b/src/remote/slave/lib/testquickfactory.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef TEST_QUICK_FACTORY_H +#define TEST_QUICK_FACTORY_H + +#include <QObject> + +#include "qtuitestwidgetinterface.h" + +class TestQuickFactory : public QObject, public QtUiTest::WidgetFactory +{ + Q_OBJECT + Q_INTERFACES(QtUiTest::WidgetFactory) + +public: + TestQuickFactory(); + + virtual QObject* create(QObject*); + virtual QStringList keys() const; +}; + +#endif + diff --git a/src/remote/slave/lib/testquickitem.cpp b/src/remote/slave/lib/testquickitem.cpp new file mode 100644 index 0000000..844efbc --- /dev/null +++ b/src/remote/slave/lib/testquickitem.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testquickitem.h" + +#include <QQuickItem> +#include <QQuickCanvas> +#include <QMetaObject> +#include <QImage> +#include <QMetaProperty> +#include <private/qqmlmetatype_p.h> +#include <designersupport.h> +#include <QDebug> +#include <QQmlProperty> + +TestQuickItem::TestQuickItem(QQuickItem* _q) + : TestQuickObject(_q) +{ +} + +QRect TestQuickItem::geometry() const +{ + return mapToGlobal(quickItem()->boundingRect().toRect()); +} + +QPoint TestQuickItem::mapToGlobal(const QPoint& pos) const +{ + return quickItem()->canvas()->mapToGlobal(quickItem()->mapToScene(pos).toPoint()); +} + +QPoint TestQuickItem::mapFromGlobal(const QPoint& pos) const +{ + return quickItem()->mapFromScene(quickItem()->canvas()->mapFromGlobal(pos)).toPoint(); +} + +QRect TestQuickItem::mapToGlobal(const QRect& local) const +{ + QRect result = quickItem()->mapRectToScene(local).toRect(); + result.moveTopLeft(quickItem()->canvas()->mapToGlobal(result.topLeft())); + return result; +} + +QRect TestQuickItem::mapFromGlobal(const QRect& global) const +{ + QRect result = global; + result.moveTopLeft(quickItem()->canvas()->mapFromGlobal(result.topLeft())); + return quickItem()->mapRectFromScene(result).toRect(); +} + +bool TestQuickItem::grabImage(QImage &img) const +{ + if (quickItem()->width() <= 0 || quickItem()->height() <= 0 + || !quickItem()->canvas()) + return false; + + QRect geo(geometry()); + geo.moveTopLeft(geo.topLeft() - quickItem()->canvas()->pos()); + + QImage fb = quickItem()->canvas()->grabFrameBuffer(); + img = fb.copy(geo); + return true; +} + +bool TestQuickItem::isVisible() const +{ + return quickItem()->isVisible() && (quickItem()->opacity() > 0); +} + +bool TestQuickItem::hasContents() const +{ + return quickItem()->flags() & QQuickItem::ItemHasContents; +} + +QObject* TestQuickItem::parent() const +{ + QObject *ret = quickItem()->parentItem(); + if (!ret) + ret = quickItem()->canvas(); + + return ret; +} + +bool TestQuickItem::hasFocus() const +{ + return quickItem()->hasFocus(); +} + +bool isValidAnchorName(const QString &name) +{ + static QStringList anchorNameList(QStringList() << QLatin1String("anchors.top") + << QLatin1String("anchors.left") + << QLatin1String("anchors.right") + << QLatin1String("anchors.bottom") + << QLatin1String("anchors.verticalCenter") + << QLatin1String("anchors.horizontalCenter") + << QLatin1String("anchors.fill") + << QLatin1String("anchors.centerIn") + << QLatin1String("anchors.baseline")); + + return anchorNameList.contains(name); +} + +QVariant TestQuickItem::objectProperty(const QString& name) const +{ + if (name.startsWith(QLatin1String("anchors."))) { + if (isValidAnchorName(name)) { + QQmlContext *context = qmlContext(q); + if (!context) { + return QVariant(); + } + + QPair<QString, QObject*> pair = DesignerSupport::anchorLineTarget(quickItem(), name, context); + if (pair.second) { + if (pair.first.isEmpty()) { + return nameForObject(pair.second); + } else { + return QString("%1.%2").arg(nameForObject(pair.second)).arg(pair.first); + } + } else { + return QVariant(); + } + } else { + QObject *anchors = QQmlMetaType::toQObject(quickItem()->property("anchors")); + if (anchors) { + return anchors->property(name.mid(8).toLatin1()); + } + } + } + + QQmlProperty qmlProperty(q, name); + QVariant ret = qmlProperty.read(); + + if (!ret.isValid()) { + ret = TestQuickObject::objectProperty(name); + } + + return ret; +} + +const QLatin1String TestQuickItem::containedInProperty("CONTAINED_IN"); +const QLatin1String TestQuickItem::containsProperty("CONTAINS"); +const QLatin1String TestQuickItem::intersectsProperty("INTERSECTS"); +const QLatin1String TestQuickItem::labelProperty("LABEL"); + +bool TestQuickItem::matchProperty(const QString& propertyUpper, const QVariant &value) const +{ + static QStringList rectProperties(QStringList() + << containedInProperty << containsProperty << intersectsProperty); + + if (rectProperties.contains(propertyUpper)) { + QRect rect = value.toRect(); + if (rect.isValid()) { + QRect geom = geometry(); + if ((propertyUpper == intersectsProperty && geom.intersects(rect)) || + (propertyUpper == containedInProperty && rect.contains(geom)) || + (propertyUpper == containsProperty && geom.contains(rect))) { + return true; + } + } else { + QtUiTest::setErrorString(QString("Invalid QRect specified for property '%1'").arg(propertyUpper)); + return false; + } + } else if (propertyUpper == labelProperty) { + // Slightly nasty logic to support legacy LABEL functionality + foreach (const QObject *child, children()) { + if (child->inherits("QQuickText") && child->property("text") == value) { + return true; + } else if (child->inherits("QQuickRow")) { + QtUiTest::Object *qo = qtuitest_cast<QtUiTest::Object*>(child); + if (qo) { + foreach (const QObject *gChild, qo->children()) { + if (gChild->inherits("QQuickText") && gChild->property("text") == value) { + return true; + } + } + } + } + } + } + + return TestQuickObject::matchProperty(propertyUpper, value); +} + +QVariantMap TestQuickItem::getProperties() const +{ + QVariantMap map = TestQuickObject::getProperties(); + + // Include attached anchors properties + QObject *anchors = QQmlMetaType::toQObject(quickItem()->property("anchors")); + if (anchors) { + const QMetaObject *amo = anchors->metaObject(); + for (int i=0; i<amo->propertyCount(); i++) { + QString anchorProperty = QString("anchors.%1").arg(amo->property(i).name()); + QVariant value = getProperty(anchorProperty); + if (value.isValid()) { + map[anchorProperty] = value; + } + } + } + + return map; +} + +bool TestQuickItem::ignoreScan() const +{ + return !(quickItem()->isEnabled()); +} + +QString TestQuickItem::nameForObject(QObject* object) const +{ + if (object == quickItem()->parentItem()) { + return QLatin1String("parent"); + } + return TestQuickObject::nameForObject(object); +} + +QObject *TestQuickItem::window() const +{ + return quickItem()->canvas(); +} + +QString TestQuickItem::debugString() const +{ + QRect g(geometry()); + QString name(nameForObject(q)); + QString text = getProperty("text").toString(); + + return QString("%1x:%2 y:%3 w:%4 h:%5%6%7").arg(name.isEmpty() ? QString() : QString("id:%1 ").arg(name)).arg(g.x()).arg(g.y()).arg(g.width()).arg(g.height()).arg(isVisible() ? QLatin1String(" visible") : QString()).arg(text.isEmpty() ? QString() : QString(" text('%1')").arg(text)); +} diff --git a/src/remote/slave/lib/testquickitem.h b/src/remote/slave/lib/testquickitem.h new file mode 100644 index 0000000..fb62504 --- /dev/null +++ b/src/remote/slave/lib/testquickitem.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef TEST_QUICK_ITEM_H +#define TEST_QUICK_ITEM_H + +#include "testquickobject.h" +#include "qtuitestwidgetinterface.h" +#include <QQuickItem> + +class QRect; + +class TestQuickItem : public TestQuickObject, + public QtUiTest::Widget +{ + Q_OBJECT + Q_INTERFACES(QtUiTest::Widget) + +public: + TestQuickItem(QQuickItem*); + + virtual QRect geometry() const; + virtual QPoint mapToGlobal(const QPoint&) const; + virtual QPoint mapFromGlobal(const QPoint&) const; + virtual QRect mapToGlobal(const QRect&) const; + virtual QRect mapFromGlobal(const QRect&) const; + virtual bool grabImage(QImage &img) const; + + virtual bool isVisible() const; + virtual bool hasContents() const; + virtual QObject* parent() const; + virtual bool hasFocus() const; + virtual bool matchProperty(const QString&, const QVariant&) const; + virtual QVariantMap getProperties() const; + + virtual bool ignoreScan() const; + virtual QObject* window() const; + virtual QString debugString() const; + +protected: + virtual QString nameForObject(QObject*) const; + + inline QQuickItem *quickItem() const { return static_cast<QQuickItem*>(q); } + + virtual QVariant objectProperty(const QString& name) const; + + static const QLatin1String containedInProperty; + static const QLatin1String containsProperty; + static const QLatin1String intersectsProperty; + static const QLatin1String labelProperty; +}; + +#endif diff --git a/src/remote/slave/lib/testquickobject.cpp b/src/remote/slave/lib/testquickobject.cpp new file mode 100644 index 0000000..cbf961c --- /dev/null +++ b/src/remote/slave/lib/testquickobject.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testquickobject.h" + +#include <QQuickItem> +#include <QQmlContext> +#include <QQmlListProperty> +#include <QMetaObject> +#include <QMetaProperty> +#include <private/qqmlmetatype_p.h> + +const QLatin1String TestQuickObject::classNameProperty("CLASSNAME"); +const QLatin1String TestQuickObject::hasContentsProperty("HAS_CONTENTS"); +const QLatin1String TestQuickObject::inheritsProperty("INHERITS"); +const QLatin1String TestQuickObject::propertyProperty("PROPERTY"); + +const QLatin1String TestQuickObject::qmlTypeProperty("QMLTYPE"); +const QLatin1String TestQuickObject::qmlIdProperty("QMLID"); +const QLatin1String TestQuickObject::qmlInheritsProperty("QMLINHERITS"); + +TestQuickObject::TestQuickObject(QObject* _q) + : q(_q) +{ +} + +const QObjectList TestQuickObject::children() const +{ + QObjectList ret; + QQuickItem *item = qobject_cast<QQuickItem*>(q); + if (item) { + foreach (QQuickItem *child, item->childItems()) { + ret << child; + } + } + + return ret; +} + +QObject* TestQuickObject::parent() const +{ + return 0; +} + +QVariant TestQuickObject::objectProperty(const QString& name) const +{ + return q->property(name.toLocal8Bit()); +} + +QVariant TestQuickObject::getProperty(const QString& name) const +{ + // Do QtUiTest property type check + if (name.toUpper() == qmlTypeProperty) { + return typeOf(); + } else if (name.toUpper() == qmlIdProperty) { + return nameForObject(q); + } + + // Get the property and convert it to QtUiTest compatible format + QVariant ret = objectProperty(name); + + if (!ret.isValid()) { + return ret; + } + + if (ret.canConvert<QQmlListReference>()) { + QQmlListReference ref = ret.value<QQmlListReference>(); + QVariantList list; + for (int i=0; i<ref.count(); ++i) { + list << QVariant::fromValue(ref.at(i)); + } + ret = list; + } else { + const QMetaObject *mo = q->metaObject(); + QMetaProperty mp = mo->property(mo->indexOfProperty(name.toLocal8Bit())); + if (mp.isEnumType()) + { + QVariantMap map; + int value = ret.toInt(); + map["_enum_"] = mp.enumerator().valueToKeys(value); + map["_value_"] = value; + ret = map; + } + } + + if (ret.type() == QVariant::UserType) { + bool ok; + QObject *obj = QQmlMetaType::toQObject(ret, &ok); + if (ok) { + return QVariant::fromValue(obj); + } + } + + return ret; +} + +bool TestQuickObject::setProperty(const QString& name, const QVariant& value) +{ + return q->setProperty(name.toAscii(), value); +} + +bool TestQuickObject::matchProperty(const QString& propertyUpper, const QVariant &value) const +{ + return (propertyUpper == propertyProperty && getProperty(value.toString()).isValid()) + || (propertyUpper == classNameProperty && q->metaObject()->className() == value) + || (propertyUpper == inheritsProperty && q->inherits(value.toString().toLatin1())) + || (propertyUpper == hasContentsProperty && hasContents() == value.toBool()) + || (propertyUpper == qmlInheritsProperty && inheritsQmlType(value.toString())); +} + +QVariantMap TestQuickObject::getProperties() const +{ + QVariantMap map; + const QMetaObject *mo = q->metaObject(); + for (int i=0; i<mo->propertyCount(); i++) { + map[mo->property(i).name()] = getProperty(mo->property(i).name()); + } + foreach (const QByteArray &prop, q->dynamicPropertyNames()) { + map[prop] = getProperty(prop); + } + return map; +} + +QVariantList TestQuickObject::resources() const +{ + return getProperty(QLatin1String("resources")).toList(); +} + +QString TestQuickObject::typeOf() const +{ + return getTypeName(); +} + +bool TestQuickObject::inheritsQmlType(const QString &typeName) const +{ + const QMetaObject *mo = q->metaObject(); + + while (mo) { + if (typeNameForMetaObject(mo) == typeName) { + return true; + } + if (mo == &QQuickItem::staticMetaObject) { + break; + } + mo = mo->superClass(); + } + + return false; +} + +QString TestQuickObject::getTypeName() const +{ + return typeNameForMetaObject(q->metaObject()); +} + +QString TestQuickObject::typeNameForMetaObject(const QMetaObject *mo) const +{ + QString typeName; + if (!mo) return typeName; + + QQmlType *type = QQmlMetaType::qmlType(mo); + + // This logic is copied from QQmlInfo + if (type) { + typeName = type->qmlTypeName(); + int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); + if (lastSlash != -1) + typeName = typeName.mid(lastSlash+1); + } else { + typeName = QString::fromUtf8(mo->className()); + int marker = typeName.indexOf(QLatin1String("_QMLTYPE_")); + if (marker != -1) + typeName = typeName.left(marker); + + marker = typeName.indexOf(QLatin1String("_QML_")); + if (marker != -1) { + typeName = typeName.left(marker); + typeName += QLatin1Char('*'); + type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1())); + if (type) { + typeName = type->qmlTypeName(); + int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); + if (lastSlash != -1) + typeName = typeName.mid(lastSlash+1); + } + } + } + + if (typeName.isNull()) { + return mo->className(); + } + + return typeName; +} + +QString TestQuickObject::nameForObject(QObject* object) const +{ + QQmlContext *context = qmlContext(q); + if (!object || !context) { + return QString(); + } + return context->nameForObject(object); +} + +QStringList TestQuickObject::inheritance() const +{ + QStringList ret; + + const QMetaObject *mo = q->metaObject(); + + while (mo) { + ret << typeNameForMetaObject(mo); + if (mo == &QQuickItem::staticMetaObject) { + break; + } + mo = mo->superClass(); + } + + return ret; +}
\ No newline at end of file diff --git a/src/remote/slave/lib/testquickobject.h b/src/remote/slave/lib/testquickobject.h new file mode 100644 index 0000000..dfc62cb --- /dev/null +++ b/src/remote/slave/lib/testquickobject.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef TEST_QUICK_OBJECT_H +#define TEST_QUICK_OBJECT_H + +#include "qtuitestwidgetinterface.h" + +class QQmlContext; + +class TestQuickObject : public QObject, + public QtUiTest::Object +{ + Q_OBJECT + Q_INTERFACES(QtUiTest::Object) + +public: + + TestQuickObject(QObject*); + + virtual const QObjectList children() const; + virtual QObject* parent() const; + virtual QVariant getProperty(const QString&) const; + virtual bool setProperty(const QString&, const QVariant&); + virtual bool matchProperty(const QString&, const QVariant&) const; + virtual QVariantMap getProperties() const; + virtual QVariantList resources() const; + virtual QString typeOf() const; + virtual QStringList inheritance() const; + +protected: + bool inheritsQmlType(const QString&) const; + virtual QString getTypeName() const; + QString typeNameForMetaObject(const QMetaObject *mo) const; + virtual QString nameForObject(QObject*) const; + virtual QVariant objectProperty(const QString& name) const; + + static const QLatin1String qmlTypeProperty; + static const QLatin1String qmlIdProperty; + static const QLatin1String qmlInheritsProperty; + + static const QLatin1String classNameProperty; + static const QLatin1String hasContentsProperty; + static const QLatin1String inheritsProperty; + static const QLatin1String propertyProperty; + + QObject* q; +}; + +#endif diff --git a/src/remote/slave/lib/testquickview.cpp b/src/remote/slave/lib/testquickview.cpp new file mode 100644 index 0000000..e8abde8 --- /dev/null +++ b/src/remote/slave/lib/testquickview.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testquickview.h" + +#include <QDebug> +#include <QQuickView> +#include <QQuickItem> +#include <QImage> + +TestQuickView::TestQuickView(QQuickView* _q) + : TestQuickObject(_q) +{} + +TestQuickView::~TestQuickView() +{ +} + +QRect TestQuickView::geometry() const +{ + return static_cast<QQuickView*>(q)->geometry(); +} + +bool TestQuickView::isVisible() const +{ + return true; +} + +bool TestQuickView::hasContents() const +{ + return true; +} + +QObject* TestQuickView::parent() const +{ + return static_cast<QQuickView*>(q)->parent(); +} + +QPoint TestQuickView::mapToGlobal(const QPoint &local) const +{ + return static_cast<QQuickView*>(q)->mapToGlobal(local); +} + +QPoint TestQuickView::mapFromGlobal(const QPoint &global) const +{ + return static_cast<QQuickView*>(q)->mapFromGlobal(global); +} + +QRect TestQuickView::mapToGlobal(const QRect &local) const +{ + QRect result = local; + result.moveTopLeft(mapToGlobal(result.topLeft())); + return result; +} + +QRect TestQuickView::mapFromGlobal(const QRect &global) const +{ + QRect result = global; + result.moveTopLeft(mapFromGlobal(result.topLeft())); + return result; +} + +bool TestQuickView::grabImage(QImage &img) const +{ + img = static_cast<QQuickView*>(q)->grabFrameBuffer(); + return !img.isNull(); +} + +const QObjectList TestQuickView::children() const +{ + QObjectList ret; + + QObject *rootObject = static_cast<QQuickView*>(q)->rootObject(); + if (rootObject) + ret << rootObject; + + return ret; +} + +bool TestQuickView::hasFocus() const +{ + return true; +} + +QString TestQuickView::debugString() const +{ + QRect g(geometry()); + QString name(nameForObject(q)); + + return QString("%1x:%2 y:%3 w:%4 h:%5%6").arg(name.isEmpty() ? QString() : QString("id:%1 ").arg(name)).arg(g.x()).arg(g.y()).arg(g.width()).arg(g.height()).arg(isVisible() ? QLatin1String(" visible") : QString()); +} diff --git a/src/remote/slave/lib/testquickview.h b/src/remote/slave/lib/testquickview.h new file mode 100644 index 0000000..32409c5 --- /dev/null +++ b/src/remote/slave/lib/testquickview.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef TEST_QUICK_VIEW_H +#define TEST_QUICK_VIEW_H + +#include "testquickobject.h" +#include "qtuitestwidgetinterface.h" +#include <QRect> + +class QQuickView; + +class TestQuickView : public TestQuickObject, + public QtUiTest::Widget +{ + Q_OBJECT + Q_INTERFACES(QtUiTest::Object) + Q_INTERFACES(QtUiTest::Widget) + +public: + TestQuickView(QQuickView*); + ~TestQuickView(); + + virtual QRect geometry() const; + virtual bool isVisible() const; + virtual bool hasContents() const; + virtual QObject* parent() const; + virtual QPoint mapToGlobal(const QPoint&) const; + virtual QPoint mapFromGlobal(const QPoint&) const; + virtual QRect mapToGlobal(const QRect&) const; + virtual QRect mapFromGlobal(const QRect&) const; + virtual bool grabImage(QImage &img) const; + virtual bool hasFocus() const; + virtual const QObjectList children() const; + virtual QString debugString() const; +}; + +#endif + diff --git a/src/remote/slave/lib/testslaveserver.cpp b/src/remote/slave/lib/testslaveserver.cpp new file mode 100644 index 0000000..90d1f2c --- /dev/null +++ b/src/remote/slave/lib/testslaveserver.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testslaveserver.h" +// #include "qsensorgenerator_p.h" +#include <qtestslave.h> +#include <QCoreApplication> +#include <QStringList> +#include <QLocalSocket> +#include <QtSystemTest/QstDebug> + +#ifdef Q_OS_SYMBIAN +# include <sys/socket.h> +# include <net/if.h> +#endif + +#if defined(Q_WS_WIN) || defined(Q_WS_MAC) +extern Q_GUI_EXPORT bool qt_use_native_dialogs; +#endif + +TestSlaveServer::TestSlaveServer() + : QTcpServer(), showDebug(false), started(false), m_useDaemon(false) +{ + QTT_TRACE_FUNCTION(); +} + +TestSlaveServer::~TestSlaveServer() +{ + QTT_TRACE_FUNCTION(); + close(); +} + +void TestSlaveServer::incomingConnection(int sd) +{ + QTT_TRACE_FUNCTION(); + slave.setSocket(sd); +} + +quint16 TestSlaveServer::queryDaemonForPort() const +{ + QTT_TRACE_FUNCTION(); + QLocalSocket socket; + socket.connectToServer(QString::fromLocal8Bit(QTUITEST_PORT_PATH)); + qDebug() << "qtuitest: Getting port..."; + if (!socket.waitForConnected(500)) { + return 0; + } + + char buf[32]; + qDebug() << "qtuitest: Got local socket..." << &socket; + if (!socket.waitForReadyRead(5000)) { + socket.close(); + return 0; + } + + qint64 length = socket.readLine(buf, sizeof(buf)); + socket.close(); + + if (length == -1) { + return 0; + } + + bool ok = false; + quint16 port = QString(buf).toUShort(&ok); + if (!ok) { + return 0; + } + + qDebug() << "qtuitest: Received Port" << port; + return port; +} + +void TestSlaveServer::initSlave(bool useDaemon) +{ + QTT_TRACE_FUNCTION(); + m_useDaemon = useDaemon; + +// QSensorGeneratorFactory *factory = new QSensorGeneratorFactory; +// factory->registerSensors(); + + QTimer::singleShot(100, this, SLOT(startService())); +} + +void TestSlaveServer::startService() +{ + QTT_TRACE_FUNCTION(); + bool parseOk; + QStringList args = QCoreApplication::arguments(); + QByteArray debugEnvBa = qgetenv("QTUITEST_DEBUG"); + QString debugEnv = QString(debugEnvBa); + +#ifndef QTUITEST_DEBUG + int debugValue = debugEnv.toInt(&parseOk); + if (parseOk && (debugValue > 0)) + showDebug = true; +#else + showDebug = true; +#endif + + if (showDebug) + qWarning("QtUiTest: Start service"); + + for (int index = 0; index < args.count(); index++){ + if (args[index].endsWith("qtuitestrunner")) { + if (showDebug) + qWarning() << "QtUiTest: Not starting TestSlaveServer::startService for qtuitestrunner"; + return; + } + } + + if (started) { + if (showDebug) + qWarning() << "QtUiTest: Closing TestSlaveServer connection"; + + close(); + } + + quint16 aut_port = DEFAULT_AUT_PORT; + + if (m_useDaemon) { + aut_port = queryDaemonForPort(); + if (!aut_port) { + qDebug() << "Not received port, will retry in 2000ms"; + QTimer::singleShot(2000, this, SLOT(startService())); + return; + } + } else { + QString autPortEnv = QString::fromLocal8Bit(qgetenv("QTUITEST_PORT")); + + if (!autPortEnv.isEmpty()) { + aut_port = autPortEnv.toUShort(&parseOk); + if (!parseOk) { + aut_port = DEFAULT_AUT_PORT; + qWarning() << "QtUiTest: Unable to parse QTUITEST_PORT" << autPortEnv; + } else { + if (showDebug) + qWarning() << "QtUiTest: Set port via QTUITEST_PORT to" << aut_port; + } + } + for (int index = 0; index < args.count(); index++) { + if ((args[index] == QLatin1String("-autport")) && (index + 1 < args.count())) { + aut_port = args[index + 1].toUShort(&parseOk); + if (!parseOk) { + aut_port = DEFAULT_AUT_PORT; + qWarning() << "QtUiTest: Unable to parse -autport" << args[index]; + } else { + if (showDebug) + qWarning() << "QtUiTest: Set port via -autport to" << aut_port; + } + } + } + } + + m_port = aut_port; + + QTimer::singleShot(0, this, SLOT(initConnection())); +} + +void TestSlaveServer::initConnection() +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) + if (!listen(QHostAddress::AnyIPv4, m_port)) { +#else + if (!listen(QHostAddress::Any, m_port)) { +#endif + qWarning() << "QtUiTest: couldn't listen for connections on " << m_port << ":" << errorString(); + return; + } + + started = true; + if (showDebug) + qWarning() << "QtUiTest: listening for connections on" << m_port; +} + +void TestSlaveServer::stopService() +{ + QTT_TRACE_FUNCTION(); + if (showDebug) + qWarning("QtUiTest : Stoping service"); + + close(); + started = false; +} diff --git a/src/remote/slave/lib/testslaveserver.h b/src/remote/slave/lib/testslaveserver.h new file mode 100644 index 0000000..1043b4b --- /dev/null +++ b/src/remote/slave/lib/testslaveserver.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QTESTSLAVESERVER_H +#define QTESTSLAVESERVER_H + +#include <QTcpServer> +#include "qtestslave.h" + +class TestSlaveServer : public QTcpServer +{ +Q_OBJECT + +public: + TestSlaveServer(); + ~TestSlaveServer(); + void incomingConnection(int); + void initSlave(bool useDaemon=false); + void stopService(); + +private slots: + void initConnection(); + void startService(); + +private: + quint16 queryDaemonForPort() const; + QTestSlave slave; + bool showDebug; + bool started; + bool m_useDaemon; + quint16 m_port; +}; + +#endif diff --git a/src/remote/slave/lib/testwidget.cpp b/src/remote/slave/lib/testwidget.cpp new file mode 100644 index 0000000..f2340f4 --- /dev/null +++ b/src/remote/slave/lib/testwidget.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testwidget.h" + +#include <QDebug> +#include <QWidget> +#include <QPixmap> +#include <QAction> +#include <QMetaProperty> + +const QLatin1String TestWidget::actionsProperty("QACTIONS"); +const QLatin1String TestWidget::classNameProperty("CLASSNAME"); +const QLatin1String TestWidget::hasContentsProperty("HAS_CONTENTS"); +const QLatin1String TestWidget::inheritsProperty("INHERITS"); +const QLatin1String TestWidget::propertyProperty("PROPERTY"); + +TestWidget::TestWidget(QWidget* _q) + : TestObject(_q) +{} + +TestWidget::~TestWidget() +{ +} + +QRect TestWidget::geometry() const +{ + QWidget *w = widget(); + QRect geo(w->geometry()); + geo.moveTopLeft(w->mapToGlobal(w->mapFromParent(geo.topLeft()))); + return geo; +} + +bool TestWidget::isVisible() const +{ + return widget()->isVisible(); +} + +bool TestWidget::hasContents() const +{ + return true; +} + +QObject* TestWidget::parent() const +{ + return q->parent(); +} + +QPoint TestWidget::mapToGlobal(const QPoint &local) const +{ + return widget()->mapToGlobal(local); +} + +QPoint TestWidget::mapFromGlobal(const QPoint &global) const +{ + return widget()->mapFromGlobal(global); +} + +QRect TestWidget::mapToGlobal(const QRect &local) const +{ + QRect result = local; + result.moveTopLeft(mapToGlobal(result.topLeft())); + return result; +} + +QRect TestWidget::mapFromGlobal(const QRect &global) const +{ + QRect result = global; + result.moveTopLeft(mapFromGlobal(result.topLeft())); + return result; +} + +bool TestWidget::grabImage(QImage &img) const +{ + img = QPixmap::grabWidget(widget()).toImage(); + return !img.isNull(); +} + +const QObjectList TestWidget::children() const +{ + QObjectList ret; + foreach (QObject *child, q->children()) { + if (child->isWidgetType()) { + ret << child; + } + } + + return ret; +} + +bool TestWidget::hasFocus() const +{ + return widget()->hasFocus(); +} + +QVariantList TestWidget::getActions() const +{ + QVariantList ret; + foreach (QAction *action, widget()->actions()) { + ret << QVariant::fromValue(static_cast<QObject*>(action)); + } + return ret; +} + +QVariant TestWidget::getProperty(const QString& name) const +{ + if (name.toUpper() == actionsProperty) { + return getActions(); + } else if (name.toUpper() == QLatin1String("INHERITANCE")) { + return inheritance(); + } + return q->property(name.toLocal8Bit()); +} + +bool TestWidget::matchProperty(const QString& propertyUpper, const QVariant &value) const +{ + return (propertyUpper == propertyProperty && getProperty(value.toString()).isValid()) + || (propertyUpper == classNameProperty && q->metaObject()->className() == value) + || (propertyUpper == inheritsProperty && q->inherits(value.toString().toLatin1())) + || (propertyUpper == hasContentsProperty); +} + + +QVariantList TestWidget::resources() const +{ + return getActions(); +} + +QObject* TestWidget::window() const +{ + return widget()->window(); +} + +QString TestWidget::debugString() const +{ + QRect g(geometry()); + QString name; + + return QString("%1x:%2 y:%3 w:%4 h:%5%6").arg(name.isEmpty() ? QString() : QString("id:%1 ").arg(name)).arg(g.x()).arg(g.y()).arg(g.width()).arg(g.height()).arg(isVisible() ? QLatin1String(" visible") : QString()); +} diff --git a/src/remote/slave/lib/testwidget.h b/src/remote/slave/lib/testwidget.h new file mode 100644 index 0000000..35e1269 --- /dev/null +++ b/src/remote/slave/lib/testwidget.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef TEST_WIDGET_H +#define TEST_WIDGET_H + +#include "testobject.h" +#include "qtuitestwidgetinterface.h" + +#include <QWidget> + +class TestWidget : public TestObject, + public QtUiTest::Widget +{ + Q_OBJECT + Q_INTERFACES(QtUiTest::Object) + Q_INTERFACES(QtUiTest::Widget) + +public: + TestWidget(QWidget*); + ~TestWidget(); + + virtual bool matchProperty(const QString&, const QVariant&) const; + virtual QRect geometry() const; + virtual bool isVisible() const; + virtual bool hasContents() const; + virtual QObject* parent() const; + virtual QPoint mapToGlobal(const QPoint&) const; + virtual QPoint mapFromGlobal(const QPoint&) const; + virtual QRect mapToGlobal(const QRect&) const; + virtual QRect mapFromGlobal(const QRect&) const; + virtual bool grabImage(QImage &img) const; + virtual bool hasFocus() const; + virtual const QObjectList children() const; + virtual QVariant getProperty(const QString&) const; + virtual QVariantList resources() const; + virtual QObject* window() const; + virtual QString debugString() const; + +protected: + inline QWidget *widget() const { return static_cast<QWidget*>(q); } + QVariantList getActions() const; + static const QLatin1String actionsProperty; + static const QLatin1String classNameProperty; + static const QLatin1String hasContentsProperty; + static const QLatin1String inheritsProperty; + static const QLatin1String propertyProperty; + +}; + +#endif + diff --git a/src/remote/slave/lib/testwindow.cpp b/src/remote/slave/lib/testwindow.cpp new file mode 100644 index 0000000..517c141 --- /dev/null +++ b/src/remote/slave/lib/testwindow.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "testwindow.h" + +#include <QDebug> +#include <QWindow> +#include <QScreen> + +TestWindow::TestWindow(QWindow* _q) + : TestQuickObject(_q) +{} + +TestWindow::~TestWindow() +{ +} + +QRect TestWindow::geometry() const +{ + return window()->geometry(); +} + +bool TestWindow::isVisible() const +{ + return window()->isExposed(); +} + +bool TestWindow::hasContents() const +{ + return true; +} + +QObject* TestWindow::parent() const +{ + return window()->parent(); +} + +QPoint TestWindow::mapToGlobal(const QPoint &local) const +{ + return window()->mapToGlobal(local); +} + +QPoint TestWindow::mapFromGlobal(const QPoint &global) const +{ + return window()->mapFromGlobal(global); +} + +QRect TestWindow::mapToGlobal(const QRect &local) const +{ + QRect result = local; + result.moveTopLeft(mapToGlobal(result.topLeft())); + return result; +} + +QRect TestWindow::mapFromGlobal(const QRect &global) const +{ + QRect result = global; + result.moveTopLeft(mapFromGlobal(result.topLeft())); + return result; +} + +bool TestWindow::grabImage(QImage &img) const +{ + Q_UNUSED(img); + return false; +} + +const QObjectList TestWindow::children() const +{ + QObjectList ret; + + foreach (QObject *child, q->children()) { + if (child->isWindowType() || child->isWidgetType()) { + ret << child; + } + } + + // This is all a bit nasty... + QObject *rootObject = window()->focusObject(); + while (rootObject) { + QObject *parent = rootObject->parent(); + if (!parent || parent == q || !parent->isWidgetType()) + break; + rootObject = parent; + } + if (rootObject) + ret << rootObject; + + return ret; +} + +bool TestWindow::hasFocus() const +{ + return true; +} + +QString TestWindow::debugString() const +{ + QRect g(geometry()); + QString name(nameForObject(q)); + + return QString("%1x:%2 y:%3 w:%4 h:%5%6").arg(name.isEmpty() ? QString() : QString("id:%1 ").arg(name)).arg(g.x()).arg(g.y()).arg(g.width()).arg(g.height()).arg(isVisible() ? QLatin1String(" visible") : QString()); +} diff --git a/src/remote/slave/lib/testwindow.h b/src/remote/slave/lib/testwindow.h new file mode 100644 index 0000000..890e9ae --- /dev/null +++ b/src/remote/slave/lib/testwindow.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef TEST_WINDOW_H +#define TEST_WINDOW_H + +#include "testquickobject.h" +#include "qtuitestwidgetinterface.h" + +#include <QWindow> + +class TestWindow : public TestQuickObject, + public QtUiTest::Widget +{ + Q_OBJECT + Q_INTERFACES(QtUiTest::Object) + Q_INTERFACES(QtUiTest::Widget) + +public: + TestWindow(QWindow*); + ~TestWindow(); + + virtual QRect geometry() const; + virtual bool isVisible() const; + virtual bool hasContents() const; + virtual QObject* parent() const; + virtual QPoint mapToGlobal(const QPoint&) const; + virtual QPoint mapFromGlobal(const QPoint&) const; + virtual QRect mapToGlobal(const QRect&) const; + virtual QRect mapFromGlobal(const QRect&) const; + virtual bool grabImage(QImage &img) const; + virtual bool hasFocus() const; + virtual const QObjectList children() const; + virtual QString debugString() const; + +protected: + inline QWindow *window() const { return static_cast<QWindow*>(q); } +}; + +#endif + diff --git a/src/remote/slave/slave.pro b/src/remote/slave/slave.pro new file mode 100644 index 0000000..6ea58af --- /dev/null +++ b/src/remote/slave/slave.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +CONFIG += ordered +SUBDIRS = lib styleplugin diff --git a/src/remote/slave/styleplugin/qtuiteststyleplugin.cpp b/src/remote/slave/styleplugin/qtuiteststyleplugin.cpp new file mode 100644 index 0000000..f277df7 --- /dev/null +++ b/src/remote/slave/styleplugin/qtuiteststyleplugin.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QApplication> +#include <QStylePlugin> + +#include <QtSystemTest/qtestslave.h> +#include <QtSystemTest/testslaveserver.h> + +#include <QtSystemTest/QstDebug> + +class QtUiTestStylePlugin : public QStylePlugin +{ + Q_OBJECT + +public: + QtUiTestStylePlugin(); + virtual ~QtUiTestStylePlugin(); + + QStringList keys() const; + QStyle *create(const QString &key); + +protected: + void initSlave(bool = false); + +private: + TestSlaveServer *m_testSlaveServer; +}; + +QtUiTestStylePlugin::QtUiTestStylePlugin() : + m_testSlaveServer(0) +{ +} + +QtUiTestStylePlugin::~QtUiTestStylePlugin() +{ + QTT_TRACE_FUNCTION(); + m_testSlaveServer->stopService(); + delete m_testSlaveServer; +} + +QStringList QtUiTestStylePlugin::keys() const +{ + QTT_TRACE_FUNCTION(); + return QStringList() << "QtUiTest_NoStyle" << QLatin1String("QtUiTest") << QLatin1String("QtUiTestD"); +} + +QStyle *QtUiTestStylePlugin::create(const QString &key) +{ + QTT_TRACE_FUNCTION(); + + static bool initialised = false; + + if (key.toLower() == "qtuitest_nostyle") { + // QApplication::style() has failed to initialise app style + // so is trying all styles. In this case we DO NOT want the + // QtUiTest style to be initialised unintentionally... + initialised = true; + } + + if (initialised) return 0; + if (key.toLower() == QLatin1String("qtuitest")) { + initSlave(false); + } else if (key.toLower() == QLatin1String("qtuitestd")) { + initSlave(true); + } + return 0; +} + +void QtUiTestStylePlugin::initSlave(bool useDaemon) +{ + m_testSlaveServer = new TestSlaveServer(); + m_testSlaveServer->initSlave(useDaemon); +} + +#include "qtuiteststyleplugin.moc" +#include <qplugin.h> +Q_EXPORT_PLUGIN2(QtUiTestStylePlugin, QtUiTestStylePlugin) diff --git a/src/remote/slave/styleplugin/styleplugin.pro b/src/remote/slave/styleplugin/styleplugin.pro new file mode 100644 index 0000000..ca35c8d --- /dev/null +++ b/src/remote/slave/styleplugin/styleplugin.pro @@ -0,0 +1,18 @@ +TEMPLATE=lib +CONFIG += plugin + +TARGET=qststyle +TARGET=$$qtLibraryTarget($$TARGET) + +QT+=network + +INCLUDEPATH += ../../../../include +LIBS += -L../../../../lib +LIBS += -lQstProtocol -lQstSlave + +DESTDIR=../../../../plugins + +SOURCES+=qtuiteststyleplugin.cpp + +target.path=$$[QT_INSTALL_PLUGINS]/styles +INSTALLS+=target diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..5a497e2 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,13 @@ +TEMPLATE = subdirs +CONFIG += ordered + +isEmpty(PARTS) { + SUBDIRS += protocol interpreter remote testapp objectBrowser +} else { + # done this way since order matters + contains(PARTS, protocol):SUBDIRS += protocol + contains(PARTS, interpreter):SUBDIRS += interpreter + contains(PARTS, remote):SUBDIRS += remote + contains(PARTS, testapp):SUBDIRS += testapp + contains(PARTS, objectBrowser):SUBDIRS += objectBrowser +} diff --git a/src/testapp/main.cpp b/src/testapp/main.cpp new file mode 100644 index 0000000..508d1e7 --- /dev/null +++ b/src/testapp/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/src/testapp/mainwindow.cpp b/src/testapp/mainwindow.cpp new file mode 100644 index 0000000..dc82522 --- /dev/null +++ b/src/testapp/mainwindow.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include <QStandardItemModel> + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + m_clicks(0) +{ + ui->setupUi(this); + connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(close())); + + connect(ui->lineEdit, SIGNAL(textChanged(QString)), ui->textEditDisplay, SLOT(setText(QString))); + connect(ui->textEdit, SIGNAL(textChanged()), this, SLOT(updateTextEditDisplay())); + + connect(ui->pushButton, SIGNAL(pressed()), this, SLOT(updatePushButtonDisplay())); + connect(ui->pushButton, SIGNAL(released()), this, SLOT(updatePushButtonDisplay())); + connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(updateClickCount())); + connect(ui->radioButton1, SIGNAL(toggled(bool)), this, SLOT(updateRadioButtonDisplay())); + connect(ui->radioButton2, SIGNAL(toggled(bool)), this, SLOT(updateRadioButtonDisplay())); + connect(ui->checkBox, SIGNAL(stateChanged(int)), this, SLOT(updateCheckBoxDisplay())); + connect(ui->comboBox, SIGNAL(activated(int)), this, SLOT(updateComboBoxDisplay())); + connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(updateHorizontalSliderDisplay())); + + QWidget *contents = new QWidget; + contents->setObjectName("contents"); + contents->setFixedSize(QSize(500, 500)); + QPushButton *topLeft = new QPushButton(contents); + topLeft->setObjectName("topLeft"); + topLeft->setFixedSize(QSize(20,20)); + topLeft->move(10, 10); + QPushButton *topRight = new QPushButton(contents); + topRight->setObjectName("topRight"); + topRight->setFixedSize(QSize(20,20)); + topRight->move(470, 10); + QPushButton *bottomLeft = new QPushButton(contents); + bottomLeft->setObjectName("bottomLeft"); + bottomLeft->setFixedSize(QSize(20,20)); + bottomLeft->move(10, 470); + QPushButton *bottomRight = new QPushButton(contents); + bottomRight->setObjectName("bottomRight"); + bottomRight->setFixedSize(QSize(20,20)); + bottomRight->move(470, 470); + + ui->scrollArea->setWidget(contents); + + QStandardItemModel *model = new QStandardItemModel(this); + model->setHorizontalHeaderLabels(QStringList() << tr("items")); + QStandardItem *parentItem; + for (int j = 0; j < 3; ++j) { + parentItem = model->invisibleRootItem(); + for (int i = 0; i < 4; ++i) { + QStandardItem *item = new QStandardItem(QString("item %0").arg(i)); + parentItem->appendRow(item); + parentItem = item; + } + } + + ui->treeView->setModel(model); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::updateClickCount() +{ + m_clicks++; + updatePushButtonDisplay(); +} + +void MainWindow::updateTextEditDisplay() +{ + ui->textEditDisplay->setText(ui->textEdit->document()->toHtml()); +} + +void MainWindow::updatePushButtonDisplay() +{ + ui->pushButtonDisplay->setText( + tr("clicks: %1 isPressed: %2") + .arg(m_clicks) + .arg(ui->pushButton->isDown())); +} + +void MainWindow::updateRadioButtonDisplay() +{ + ui->radioButtonDisplay->setText( + tr("1: %1 2: %2") + .arg(ui->radioButton1->isChecked()) + .arg(ui->radioButton2->isChecked())); +} + +void MainWindow::updateCheckBoxDisplay() +{ + ui->checkBoxDisplay->setText( + tr("state: %1") + .arg(ui->checkBox->checkState())); +} + +void MainWindow::updateComboBoxDisplay() +{ + ui->checkBoxDisplay->setText( + tr("option: %1") + .arg(ui->comboBox->currentText())); +} + +void MainWindow::updateHorizontalSliderDisplay() +{ + ui->horizontalSliderDisplay->setText( + tr("position: %1") + .arg(ui->horizontalSlider->value())); +} diff --git a/src/testapp/mainwindow.h b/src/testapp/mainwindow.h new file mode 100644 index 0000000..98bb02a --- /dev/null +++ b/src/testapp/mainwindow.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private slots: + void updateClickCount(); + + void updateTextEditDisplay(); + void updatePushButtonDisplay(); + void updateRadioButtonDisplay(); + void updateCheckBoxDisplay(); + void updateComboBoxDisplay(); + void updateHorizontalSliderDisplay(); + +private: + Ui::MainWindow *ui; + + int m_clicks; +}; + +#endif // MAINWINDOW_H diff --git a/src/testapp/mainwindow.ui b/src/testapp/mainwindow.ui new file mode 100644 index 0000000..d53c7e5 --- /dev/null +++ b/src/testapp/mainwindow.ui @@ -0,0 +1,291 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>562</width> + <height>576</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralWidget"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="core"> + <attribute name="title"> + <string>Core</string> + </attribute> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QGroupBox" name="textGroup"> + <property name="title"> + <string>Text</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLineEdit" name="lineEdit"/> + </item> + <item> + <widget class="QLabel" name="lineEditDisplay"> + <property name="text"> + <string>initial</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QTextEdit" name="textEdit"/> + </item> + <item> + <widget class="QLabel" name="textEditDisplay"> + <property name="text"> + <string>initial</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="controlsGroup"> + <property name="title"> + <string>Controls</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QPushButton" name="pushButton"> + <property name="text"> + <string>PushButton</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="pushButtonDisplay"> + <property name="text"> + <string>initial</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton1"> + <property name="text"> + <string>RadioButton</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton2"> + <property name="text"> + <string>RadioButton</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="radioButtonDisplay"> + <property name="text"> + <string>initial</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox"> + <property name="text"> + <string>CheckBox</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="checkBoxDisplay"> + <property name="text"> + <string>initial</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboBox"> + <item> + <property name="text"> + <string>one</string> + </property> + </item> + <item> + <property name="text"> + <string>two</string> + </property> + </item> + <item> + <property name="text"> + <string>three</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QLabel" name="comboBoxDisplay"> + <property name="text"> + <string>initial</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="horizontalSlider"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="horizontalSliderDisplay"> + <property name="text"> + <string>initial</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="scrollingGroup"> + <property name="title"> + <string>Scrolling</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>167</width> + <height>233</height> + </rect> + </property> + </widget> + </widget> + </item> + <item> + <widget class="QTreeView" name="treeView"/> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <action name="actionNew"> + <property name="text"> + <string>&New</string> + </property> + </action> + <action name="actionClose"> + <property name="text"> + <string>&Close</string> + </property> + </action> + <action name="actionExit"> + <property name="text"> + <string>E&xit</string> + </property> + </action> + <action name="actionCopy"> + <property name="text"> + <string>&Copy</string> + </property> + </action> + <action name="actionPaste"> + <property name="text"> + <string>&Paste</string> + </property> + </action> + </widget> + <layoutdefault spacing="6" margin="11"/> + <tabstops> + <tabstop>lineEdit</tabstop> + <tabstop>textEdit</tabstop> + <tabstop>pushButton</tabstop> + <tabstop>radioButton1</tabstop> + <tabstop>checkBox</tabstop> + <tabstop>comboBox</tabstop> + <tabstop>horizontalSlider</tabstop> + <tabstop>scrollArea</tabstop> + <tabstop>treeView</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/src/testapp/testapp.pro b/src/testapp/testapp.pro new file mode 100644 index 0000000..59ae3d0 --- /dev/null +++ b/src/testapp/testapp.pro @@ -0,0 +1,10 @@ +TARGET = testapp_widgets +TEMPLATE = app +DESTDIR = ../../bin + +SOURCES += main.cpp\ + mainwindow.cpp + +HEADERS += mainwindow.h + +FORMS += mainwindow.ui diff --git a/tests/AllTests.qml b/tests/AllTests.qml new file mode 100644 index 0000000..cdae596 --- /dev/null +++ b/tests/AllTests.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +TestCollection { + id: suite + name: 'All tests' + description: 'Tests all the cases' + + InterpreterTests {} + RemoteTests {} + +} diff --git a/tests/InterpreterTests.qml b/tests/InterpreterTests.qml new file mode 100644 index 0000000..db3ab8c --- /dev/null +++ b/tests/InterpreterTests.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +import "interpreter" + +TestCollection { + name: 'interpreter only tests' + description: name + + CoreTests {} + RunnerTests {} +} diff --git a/tests/MyConfig.qml b/tests/MyConfig.qml new file mode 100644 index 0000000..905d8a4 --- /dev/null +++ b/tests/MyConfig.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtSystemTest 1.0 + +Config { + Remote { + id: sut + host: 'localhost' + port: 5656 + } +} + + diff --git a/tests/RemoteTests.qml b/tests/RemoteTests.qml new file mode 100644 index 0000000..094b5bc --- /dev/null +++ b/tests/RemoteTests.qml @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +import "remote" + +TestCollection { + name: 'remote (qtuitestd) tests' + description: name + + RunProcessTests {} + RemoteApiTests{} + AssistantTest{} + TestAppWidgetTest{} + QstObjectApiTests{} +} diff --git a/tests/interpreter/CoreTests.qml b/tests/interpreter/CoreTests.qml new file mode 100644 index 0000000..108f50f --- /dev/null +++ b/tests/interpreter/CoreTests.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import "core" + +TestCollection { + name: 'core api test' + description: name + Test { + name: 'Js api: currentFile'; description: name + + property string expectedFileName: 'CoreTests.qml' + function run() { + var path = core().Js.Engine.currentFile(); + var fileName = path.substring(path.lastIndexOf('/')+1); + expect(fileName).toBe(expectedFileName); + } + } + + ExpectApiTests{} + SleepTest{} + ClassTest{} + FailApiTest{} + ItemHandlerTests{} + ApplicationRegistryTests{} +} diff --git a/tests/interpreter/RunnerTests.qml b/tests/interpreter/RunnerTests.qml new file mode 100644 index 0000000..6046ca2 --- /dev/null +++ b/tests/interpreter/RunnerTests.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +import "runner" + +TestCollection { + name: 'runner logic tests'; description: name + + EmptyTest{} + EmptyTests{} + SkipTest{} + FailTest{} + UntestedTest{} + UntestedTests{} + DefaultConfigTest{} +} + diff --git a/tests/interpreter/core/ApplicationRegistryTests.qml b/tests/interpreter/core/ApplicationRegistryTests.qml new file mode 100644 index 0000000..67c215b --- /dev/null +++ b/tests/interpreter/core/ApplicationRegistryTests.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import "application" + +TestCollection { + name: 'Application object test'; description: name + + RegisterUnregisterAppTest{} + DefaultApplicationTest{} + CustomApplicationTest{} +} diff --git a/tests/interpreter/core/ClassTest.qml b/tests/interpreter/core/ClassTest.qml new file mode 100644 index 0000000..56f3c86 --- /dev/null +++ b/tests/interpreter/core/ClassTest.qml @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +TestCollection { + id: root + name: 'Javascript Class api test' + description: name + + function _() { + // dummy + // used instead of property var in Qt5 + } + + function setup() { + var Class = core().Class; + var Shape = Class.create(function(name) { + return { + name: function(){ return name; }, + + setName: function setName(value) { name = value; } + }; + }); + _.Class = Class; + _.Shape = Shape; + } + + Test { + name: 'construct objects'; description: name + function run() { + var Shape = _.Shape; + + var x = null; + expect(x).toBe(null); + + x = new Shape('x'); + expect(x).not.toBe(null); + expect(x).instanceOf(Shape); + } + } + + Test { + name: 'invoke methods'; description: name + function run() { + var x = new _.Shape('x'); + expect(x.name()).toBe('x'); + x.setName('y'); + expect(x.name()).toBe('y'); + } + + } + + Test { + name: 'extend objects'; description: name + function run() { + var Circle = _.Shape.extend(function(r) { + this._super('Circle'); + return { + radius: function(){ return r; } + }; + }); + + var c = new Circle(10); + expect(c).instanceOf(_.Shape); + expect(c).instanceOf(Circle); + expect(c.name()).toBe('Circle'); + expect(c.radius()).toBe(10); + } + } + + Test { + name: 'private calls public'; description: name + + function setup() { + var Class = _.Class; + var Base = Class.create(function() { + + function bar() { + return this.overrideMe(); + } + function foo() { + return bar.call(this); + } + return { + overrideMe: function() { return 'Base'}, + foo: foo + }; + }); + _.base = new Base(); + } + function run() { + expect(_.base.foo()).toBe('Base'); + } + } +} diff --git a/tests/interpreter/core/ExpectApiTests.qml b/tests/interpreter/core/ExpectApiTests.qml new file mode 100644 index 0000000..488d14f --- /dev/null +++ b/tests/interpreter/core/ExpectApiTests.qml @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +TestCollection { + name: 'expect api tests'; description: name + + Test { + name: 'expect.not'; description: name; + function run() { + expect(undefined).toBe(undefined); + expect(null).not.toBe(undefined); + } + } +} + + diff --git a/tests/interpreter/core/FailApiTest.qml b/tests/interpreter/core/FailApiTest.qml new file mode 100644 index 0000000..a9eba0f --- /dev/null +++ b/tests/interpreter/core/FailApiTest.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: 'fail api test'; description: name + + function run() { + var error, + topOfStack, + msg = 'A fail message'; + + var Core = core(); + var Engine = Core.Js.Engine; + var currentFile = Core.Js.Engine.currentFile(); + + try { + var beforeFail = Engine.currentLine(); + throw new Core.Qtt.Fail(msg); + } catch(e) { + error = e; + topOfStack = e.stack.first(); + } + + expect(error).instanceOf(Core.Qtt.Error); + expect(error).instanceOf(Core.Qtt.Fail); + + expect(error.message).toBe(msg); + expect(error.type).toBe('Fail'); + expect(error.status).toBe(Core.Qtt.Status.Failed); + + expect(topOfStack.fileName).toBe(currentFile); + expect(topOfStack.lineNumber).toBe(beforeFail+1); + } + +} + diff --git a/tests/interpreter/core/ItemHandlerTests.qml b/tests/interpreter/core/ItemHandlerTests.qml new file mode 100644 index 0000000..f904d4b --- /dev/null +++ b/tests/interpreter/core/ItemHandlerTests.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import "itemhandlers" + +TestCollection { + name: 'item handler tests'; description: name + + RegisterUnregisterHandlerTest{} + DefaultItemHandlerTest{} + CustomItemHandlerTest{} +} diff --git a/tests/interpreter/core/LocalProcessTest.qml b/tests/interpreter/core/LocalProcessTest.qml new file mode 100644 index 0000000..f324d44 --- /dev/null +++ b/tests/interpreter/core/LocalProcessTest.qml @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtSystemTest 1.0 + +Test { + name: 'process'; description: name + property int timeout: 3000 + property LocalProcess process: LocalProcess { + outputMode: LocalProcess.PropertyOutput + } + + function run() { + process.start("bc"); + process.write("p = 3 + 4\n"); + process.write("p\n"); + expect(process.waitForReadyRead(timeout)).toBe(true); + expect(process.standardOutput).toBe('7\n') + process.write("2 * p\n") + process.closeWriteChannel(); + expect(process.waitForFinished(timeout)).toBe(true); + + expect(process.standardOutput).toBe('7\n14\n') + expect(process.exitCode).toBe(0); + } +} diff --git a/tests/interpreter/core/SleepTest.qml b/tests/interpreter/core/SleepTest.qml new file mode 100644 index 0000000..0483061 --- /dev/null +++ b/tests/interpreter/core/SleepTest.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: 'sleep'; description: name + property int interval: 50 + + function run() { + var beforeSleep = +(new Date()); + sleep(interval); + var afterSleep = +(new Date()); + expect(afterSleep - beforeSleep).toBeBetween(interval*0.95, interval*1.05); + } +} diff --git a/tests/interpreter/core/application/CustomApplicationTest.qml b/tests/interpreter/core/application/CustomApplicationTest.qml new file mode 100644 index 0000000..177f261 --- /dev/null +++ b/tests/interpreter/core/application/CustomApplicationTest.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + id: root + name: 'custom app handler'; description: name + + function _() {} + + property string appId: 'MyApp' + property string filePath: className + '.qml' + property string className: 'MyApplication' + + + function setup() { + var registry = core().ApplicationRegistry; + registry.register(appId, filePath); + var p = registry.applicationForKey(appId); + expect(p).not.toBe(undefined); + _.registry = registry; + } + + function run() { + var registry = _.registry; + var component = registry.applicationForKey(appId); + var app = component.createObject(root); + var handler = app.toString().split('_').first(); + expect(handler).toBe(className); + + expect(app.name).toBe(className); + expect(app.item()).toBe(className); + } + + function cleanup() { + var registry = _.registry; + registry.unregister(appId); + } +} diff --git a/tests/interpreter/core/application/DefaultApplicationTest.qml b/tests/interpreter/core/application/DefaultApplicationTest.qml new file mode 100644 index 0000000..277765b --- /dev/null +++ b/tests/interpreter/core/application/DefaultApplicationTest.qml @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + id: root + name: 'Default application handler'; description: name + + function _() {} + property string defaultHandler: 'Application' + + function setup() { + var factory = core().ApplicationRegistry; + expect(factory).not.toBe(undefined); + _.factory = factory; + } + + function run() { + var + key = 'foobar', + factory = _.factory, + file, + component, + appObject, + className + ; + + file = factory.fileForKey(key); + expect(file.endsWith('/'+ defaultHandler + '.qml')).toBe(true); + + component = factory.applicationForKey(key); + expect(component).not.toBe(undefined); + expect(component).not.toBe(null); + + + appObject = component.createObject(root); + expect(appObject).not.toBe(undefined); + expect(appObject).not.toBe(null); + + className = appObject.toString().split('_').first(); + expect(className).toBe(defaultHandler); + } +} diff --git a/tests/interpreter/core/application/MyApplication.js b/tests/interpreter/core/application/MyApplication.js new file mode 100644 index 0000000..07aa821 --- /dev/null +++ b/tests/interpreter/core/application/MyApplication.js @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library +.import QtSystemTest 1.0 as Qst + +(function() { + var Apps = Qst.Core.ApplicationRegistry; + Apps.register('myapp', 'MyApplication.qml'); +})(); diff --git a/tests/interpreter/core/application/MyApplication.qml b/tests/interpreter/core/application/MyApplication.qml new file mode 100644 index 0000000..befd0b7 --- /dev/null +++ b/tests/interpreter/core/application/MyApplication.qml @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Application { + property string name: 'MyApplication' + function item() { + return name; + } +} diff --git a/tests/interpreter/core/application/RegisterUnregisterAppTest.qml b/tests/interpreter/core/application/RegisterUnregisterAppTest.qml new file mode 100644 index 0000000..e3771e9 --- /dev/null +++ b/tests/interpreter/core/application/RegisterUnregisterAppTest.qml @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + id: root + name: 'register and unregister item handler'; description: name + + function _() {} + property string defaultHandler: 'Application' + + property string key: 'myapp' + property string className: 'MyApplication' + property string filePath: className + '.qml' + + + function setup() { + var factory = core().ApplicationRegistry; + expect(factory).not.toBe(undefined); + _.factory = factory; + } + + function expectAppHandler(handlerClassName) { + var + factory = _.factory, + file, + component, + appObject, + className + ; + + file = factory.fileForKey(key); + expect(file.endsWith('/'+ handlerClassName + '.qml')).toBe(true); + + component = factory.applicationForKey(key); + expect(component).not.toBe(undefined); + expect(component).not.toBe(null); + + + appObject = component.createObject(root); + expect(appObject).not.toBe(undefined); + expect(appObject).not.toBe(null); + + className = appObject.toString().split('_').first(); + expect(className).toBe(handlerClassName); + } + + function run() { + var factory = _.factory; + expectAppHandler(defaultHandler); + factory.register(key, filePath); + expectAppHandler(className); + factory.unregister(key); + expectAppHandler(defaultHandler); + } +} diff --git a/tests/interpreter/core/itemhandlers/CustomItemHandlerTest.qml b/tests/interpreter/core/itemhandlers/CustomItemHandlerTest.qml new file mode 100644 index 0000000..8daae69 --- /dev/null +++ b/tests/interpreter/core/itemhandlers/CustomItemHandlerTest.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + id: root + name: 'custom item handler'; description: name + + property string className: 'QstPushButton' + property string filePath: className + '.qml' + + function _() {} + + property Application app: Application { + function __inheritanceTree() { return [className, 'QObject']; } + } + + function setup() { + _.factory = core().ItemFactory + _.factory.register(className, filePath); + } + + function run() { + var pushButton = app.__handlerForObject({_type_: className}); + + var handler = pushButton.toString().split('_').first(); + expect(handler).toBe(className); + + expect(pushButton.name).toBe(className); + expect(pushButton.reallyAButton).toBe(true); + } + + function cleanup() { + _.factory.unregister(className); + } +} diff --git a/tests/interpreter/core/itemhandlers/DefaultItemHandlerTest.qml b/tests/interpreter/core/itemhandlers/DefaultItemHandlerTest.qml new file mode 100644 index 0000000..d33947d --- /dev/null +++ b/tests/interpreter/core/itemhandlers/DefaultItemHandlerTest.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + id: root + name: 'default item handler'; description: name + + property string className: 'foo' + function _() {} + + property Application app: Application { + function __inheritanceTree() { return [className, 'QObject']; } + } + + function setup() { + } + + + function run() { + var component = _.component; + var handler = app.__handlerForObject({_type_: className}); + expect(handler).not.toBe(undefined); + expect(handler.__internals._type_).toBe(className); + var qmlType = handler.toString().split('_').first(); + expect(qmlType).toBe('QstObject'); + } +} diff --git a/tests/interpreter/core/itemhandlers/QstPushButton.qml b/tests/interpreter/core/itemhandlers/QstPushButton.qml new file mode 100644 index 0000000..fd38271 --- /dev/null +++ b/tests/interpreter/core/itemhandlers/QstPushButton.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +QstObject { + handles: 'QstPushButton' + property string name: 'QstPushButton' + property bool reallyAButton: true + + function press() { + } +} diff --git a/tests/interpreter/core/itemhandlers/RegisterUnregisterHandlerTest.qml b/tests/interpreter/core/itemhandlers/RegisterUnregisterHandlerTest.qml new file mode 100644 index 0000000..85c1618 --- /dev/null +++ b/tests/interpreter/core/itemhandlers/RegisterUnregisterHandlerTest.qml @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + id: root + name: 'register and unregister item handler'; description: name + + function _() {} + property string className: 'QstPushButton' + property string filePath: className + '.qml' + + + property Application app: Application { + function __inheritanceTree() { return [className, 'QObject']; } + } + + function setup() { + _.factory = core().ItemFactory; + expect(_.factory).not.toBe(undefined); + } + + function expectItemHandler( handlerClassName) { + var factory = _.factory; + var handler, handlerClass; + + handler = app.__handlerForObject({ _type_: className }); + expect(handler).not.toBe(undefined); + expect(handler.__internals._type_).toBe(className); + + handlerClass = handler.toString().split('_').first(); + expect(handlerClass).toBe(handlerClassName); + } + + function run() { + var factory = _.factory; + expectItemHandler('QstObject'); + factory.register(className, filePath); + expectItemHandler(className); + factory.unregister(className); + expectItemHandler('QstObject'); + } +} diff --git a/tests/interpreter/loggers/data/ExpectTests.qml b/tests/interpreter/loggers/data/ExpectTests.qml new file mode 100644 index 0000000..d854e5f --- /dev/null +++ b/tests/interpreter/loggers/data/ExpectTests.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtSystemTest 1.0 + +TestCollection { + name: 'expect tests'; description: 'A expectation tests' + + Test { + name: 'toBe'; description: 'to be' + + function run() { + expect(3).toBe(3); + expect(2 + 2).toBe(3); // for large values of 3 + } + } + + Test { + name: 'not.toBe'; description: 'not to be' + + function run() { + expect('Claudius').not.toBe('Polonius'); + expect('Claudius').not.toBe('Claudius'); + } + } + + Test { + name: 'instanceof'; description: 'expect to be instance of' + + function run() { + var message = new String('Hello World'); + expect(message).instanceOf(String); + expect(message).not.instanceOf(Number); + expect(message).instanceOf(Number); + } + } + + Test { + name: 'between'; description: 'expect to be between' + + function run() { + expect(2 + 2).toBeBetween(3,5); + expect(2 + 2).toBeBetween(4,6); + } + } + +} diff --git a/tests/interpreter/loggers/data/FailTest.qml b/tests/interpreter/loggers/data/FailTest.qml new file mode 100644 index 0000000..fee4713 --- /dev/null +++ b/tests/interpreter/loggers/data/FailTest.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtSystemTest 1.0 + +Test { + name: 'fail'; description: 'failure test' + + function run() { + fail('reason for failure'); + } +} + diff --git a/tests/interpreter/loggers/data/PassTest.qml b/tests/interpreter/loggers/data/PassTest.qml new file mode 100644 index 0000000..352efb1 --- /dev/null +++ b/tests/interpreter/loggers/data/PassTest.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtSystemTest 1.0 + +Test { + name: 'pass'; description: 'pass test' + + function run() { + log('need to actually test something to be a pass'); + expect(3).toBe(3); + } +} diff --git a/tests/interpreter/loggers/data/SkipTest.qml b/tests/interpreter/loggers/data/SkipTest.qml new file mode 100644 index 0000000..732e4b6 --- /dev/null +++ b/tests/interpreter/loggers/data/SkipTest.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtSystemTest 1.0 + +Test { + name: 'skip'; description: 'skip test' + + function run() { + skip('Skip this test'); + fail('reason for failure'); + } +} + diff --git a/tests/interpreter/loggers/data/SubTests.qml b/tests/interpreter/loggers/data/SubTests.qml new file mode 100644 index 0000000..fed8ba6 --- /dev/null +++ b/tests/interpreter/loggers/data/SubTests.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtSystemTest 1.0 + +TestCollection { + name: 'subcollection'; description: 'A sub collection of tests' + + PassTest {} + SkipTest {} + FailTest {} + ExpectTests {} +} diff --git a/tests/interpreter/loggers/data/Tests.qml b/tests/interpreter/loggers/data/Tests.qml new file mode 100644 index 0000000..016f255 --- /dev/null +++ b/tests/interpreter/loggers/data/Tests.qml @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtSystemTest 1.0 + +TestCollection { + name: 'collection'; description: 'A collection of tests' + + SubTests { + name: 'collection 1' + } + SubTests { + name: 'collection 2' + } + SubTests { + name: 'collection 3' + } +} diff --git a/tests/interpreter/loggers/data/qsystemtest.xsd b/tests/interpreter/loggers/data/qsystemtest.xsd new file mode 100644 index 0000000..35b852a --- /dev/null +++ b/tests/interpreter/loggers/data/qsystemtest.xsd @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" + elementFormDefault="qualified" + attributeFormDefault="unqualified"> + <xs:annotation> + <xs:documentation xml:lang="en">QtSystemTest xml test result schema. + </xs:documentation> + </xs:annotation> + <xs:element name="systemtestrun"> + <xs:annotation> + <xs:documentation xml:lang="en">Instance of running the test interpreter over a test file + </xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element name="collection" type="collection"/> + <xs:element name="report"> + <xs:complexType> + <xs:sequence> + <xs:element name="status" type="Status" minOccurs="0" maxOccurs="1"/> + <xs:element name="passed" type="xs:decimal"/> + <xs:element name="skipped" type="xs:decimal"/> + <xs:element name="untested" type="xs:decimal"/> + <xs:element name="failed" type="xs:decimal"/> + <xs:element name="error" type="xs:decimal"/> + <xs:element name="total" type="xs:decimal"/> + <xs:element name="duration" type="xs:decimal" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:complexType name="collection"> + <xs:annotation> + <xs:documentation xml:lang="en">A collection of test and test collections + </xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="collection" type="collection"/> + <xs:element name="test" type="test"/> + </xs:choice> + <xs:element name="report" type="report"/> + </xs:sequence> + <xs:attribute name="name" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Name of the collection</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="file" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">File which defines the collection</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="line" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Line in the file where the collection is defined</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="timestamp" type="xs:dateTime" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">When the collection was executed in UTC time</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + <xs:complexType name="test"> + <xs:sequence> + <xs:element name="method" type="method" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="report" type="report"/> + </xs:sequence> + <xs:attribute name="name" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Name of the collection</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="file" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">File which defines the collection</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="line" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Line in the file where the collection is defined</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="timestamp" type="xs:dateTime" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">When the collection was executed in UTC time</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + <xs:complexType name="method"> + <xs:sequence> + <xs:choice> + <xs:element name="method" type="method"/> + <xs:element name="failed" type="event"/> + <xs:element name="passed" type="event"/> + <xs:element name="skipped" type="event"/> + <xs:element name="error" type="event"/> + <xs:element name="untested" type="event"/> + <xs:element name="note"> + <xs:complexType> + <xs:complexContent> + <xs:extension base="event"> + <xs:attribute name="type" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">The type of noted event</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:complexContent> + </xs:complexType> + </xs:element> + </xs:choice> + </xs:sequence> + <xs:attribute name="name" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Name of the method</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + <xs:complexType name="event"> + <xs:sequence> + <xs:element name="reason" type="pre-string"/> + <xs:element name="stack" minOccurs="0" maxOccurs="1"> + <xs:complexType> + <xs:sequence> + <xs:element name="frame" minOccurs="1" maxOccurs="unbounded"> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="pre-string"> + <xs:attribute name="file" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">File for the frame content</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="line" type="xs:token" use="required"> + <xs:annotation> + <xs:documentation xml:lang="en">Line for the frame content</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="meta" minOccurs="0" maxOccurs="1"> + <xs:complexType> + <xs:sequence> + <xs:element name="property" minOccurs="0" maxOccurs="unbounded"> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="pre-string"> + <xs:attribute name="name" type="xs:token" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:complexType name="report"> + <xs:sequence> + <xs:element name="status" type="Status" minOccurs="0" maxOccurs="1"/> + <xs:element name="duration" type="xs:decimal" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="pre-string"> + <xs:restriction base="xs:string"> + <xs:whiteSpace value="preserve"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="Status"> + <xs:restriction base="xs:string"> + <xs:enumeration value="passed"/> + <xs:enumeration value="failed"/> + <xs:enumeration value="untested"/> + <xs:enumeration value="error"/> + <xs:enumeration value="skipped"/> + </xs:restriction> + </xs:simpleType> +</xs:schema> diff --git a/tests/interpreter/runner/DefaultConfigTest.qml b/tests/interpreter/runner/DefaultConfigTest.qml new file mode 100644 index 0000000..c64e055 --- /dev/null +++ b/tests/interpreter/runner/DefaultConfigTest.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: 'default config test'; description: name + + function run() { + expect(config.remotes).not.toBe(undefined); + expect(config.remotes.localhost).not.toBe(undefined); + expect(config.remotes.localhost.address).not.toBe(''); + } +} diff --git a/tests/interpreter/runner/EmptyTest.qml b/tests/interpreter/runner/EmptyTest.qml new file mode 100644 index 0000000..360a78f --- /dev/null +++ b/tests/interpreter/runner/EmptyTest.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: 'an empty teststep'; description: name + + function setup() { } + function run() { } + function cleanup() { } +} diff --git a/tests/interpreter/runner/EmptyTests.qml b/tests/interpreter/runner/EmptyTests.qml new file mode 100644 index 0000000..26a556e --- /dev/null +++ b/tests/interpreter/runner/EmptyTests.qml @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +TestCollection { + name: 'an empty test collection'; description: name + + function setup() { } + EmptyTest {} + EmptyTest {} + EmptyTest {} + function cleanup() { } +} + diff --git a/tests/interpreter/runner/FailTest.qml b/tests/interpreter/runner/FailTest.qml new file mode 100644 index 0000000..76ad7fd --- /dev/null +++ b/tests/interpreter/runner/FailTest.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import 'RunnerInternals.js' as Internals +Test { + id: root + name: 'fail test'; description: name + + function setup() { + Internals.setItem(root); + Internals.setRunner(__runner); + } + + function run() { + fail('Generate a failure'); + } + + function cleanup() { + /// HACK should not be done + /// DO NOT screw around with the internals + /// it is your fault if things break done + var Core = core(); + if (__status !== Core.Qtt.Status.Failed) { + log('Status is not set to Failed ...'); + Internals.changeReport(Core.Qtt.Status.Failed); + } else { + Internals.changeReport(Core.Qtt.Status.Passed); + } + } + +} diff --git a/tests/interpreter/runner/MyUtils.js b/tests/interpreter/runner/MyUtils.js new file mode 100644 index 0000000..aadb36f --- /dev/null +++ b/tests/interpreter/runner/MyUtils.js @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library +.import QtUiTest 1.0 as QtUiTest + +function func() { + var tt = QtUiTest.Core.api(); + tt.fail("hello"); +} diff --git a/tests/interpreter/runner/RunnerInternals.js b/tests/interpreter/runner/RunnerInternals.js new file mode 100644 index 0000000..0fedc54 --- /dev/null +++ b/tests/interpreter/runner/RunnerInternals.js @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +.pragma library + +var runner; +var item; + +function changeReport(to, from) { + from = from || item.__status; + + var report = runner.report; + report[from] --; + report[to] ++; + runner.report = report; + item.__status = to; +} + +function setRunner(r) { + runner = r; +} + +function setItem(i) { + item = i; +} diff --git a/tests/interpreter/runner/SkipTest.qml b/tests/interpreter/runner/SkipTest.qml new file mode 100644 index 0000000..baffea9 --- /dev/null +++ b/tests/interpreter/runner/SkipTest.qml @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import 'RunnerInternals.js' as Internals + +Test { + id: root + name: 'skip'; + description: 'calls skip in run' + + function setup() { + Internals.setItem(root); + Internals.setRunner(__runner); + } + + function run() { + skip('Skip this test'); + } + + function cleanup() { + /// HACK should not be done + /// DO NOT screw around with the internals + /// it is your fault if things break done + var Core = core(); + if (__status !== Core.Qtt.Status.Skipped) { + log('Status is not set to skipped ...'); + Internals.changeReport(Core.Qtt.Status.Failed); + } else { + Internals.changeReport(Core.Qtt.Status.Passed); + } + } +} diff --git a/tests/interpreter/runner/UntestedTest.qml b/tests/interpreter/runner/UntestedTest.qml new file mode 100644 index 0000000..f9f0bd0 --- /dev/null +++ b/tests/interpreter/runner/UntestedTest.qml @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import 'RunnerInternals.js' as Internals + +Test { + id: root + name: 'untested test' + description: name + property bool runGotExecuted: false; + property int untestedTestsBeforeRun: 0 + function setup() { + var Core = core(); + Internals.setItem(root); + Internals.setRunner(__runner); + untestedTestsBeforeRun = __runner.report[Core.Qtt.Status.Untested]; + fail('Generating a failure inside setup'); + } + + // Not having run shouldn't matter since this shouldn't + // be even executed + function run() { + runGotExecuted = true; + } + + function cleanup() { + /// HACK should not be done + /// DO NOT screw around with the internals + /// it is your fault if things break done + var Core = core(); + if (runGotExecuted) { + log('Run got executed somehow ...'); + Internals.changeReport(Core.Qtt.Status.Failed); + return; + } + if (__status !== Core.Qtt.Status.Untested) { + log('Status is not set to Untestsed ...'); + Internals.changeReport(Core.Qtt.Status.Failed); + return; + } + var untestedAfterRun = __runner.report[Core.Qtt.Status.Untested]; + if ( untestedTestsBeforeRun + 1 !== untestedAfterRun) { + log('Wrong count of untested. Untested before run was : ', untestedTestsBeforeRun, + ' and after run is : ', untestedAfterRun); + Internals.changeReport(Core.Qtt.Status.Failed); + return; + } + Internals.changeReport(Core.Qtt.Status.Passed); + } +} diff --git a/tests/interpreter/runner/UntestedTests.qml b/tests/interpreter/runner/UntestedTests.qml new file mode 100644 index 0000000..2e180cd --- /dev/null +++ b/tests/interpreter/runner/UntestedTests.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import 'RunnerInternals.js' as Internals + +TestCollection { + id: root + name: 'untested test collection' + description: 'tests if failing in the setup ' + + 'of a test collection sets all child tests to ' + + ' untested' + + property bool runGotExecuted: false; + property int untestedTestsBeforeRun: 0 + function setup() { + var Core = core(); + Internals.setItem(dummyTest); + Internals.setRunner(__runner); + untestedTestsBeforeRun = __runner.report[Core.Qtt.Status.Untested]; + log('Ignore the untested report, done on purpose'); + fail('Generating a failure inside test collection -> setup'); + } + + Test { + id: dummyTest + name: 'a dummy test'; description: name + + // Not having run shouldn't matter since this shouldn't + // be even executed + function run() { + runGotExecuted = true; + } + } + + function cleanup() { + /// HACK should not be done + /// DO NOT screw around with the internals + /// it is your fault if things break done + var Core = core(); + if (runGotExecuted) { + log('Run got executed somehow ...'); + Internals.changeReport(Core.Qtt.Status.Failed); + return; + } + if (dummyTest.__status !== Core.Qtt.Status.Untested) { + log('Status is not set to Untestsed ...'); + Internals.changeReport(Core.Qtt.Status.Failed); + return; + } + var untestedAfterRun = __runner.report[Core.Qtt.Status.Untested]; + if ( untestedTestsBeforeRun + 1 !== untestedAfterRun) { + log('Wrong count of untested. Untested before run was : ', untestedTestsBeforeRun, + ' and after run is : ', untestedAfterRun); + Internals.changeReport(Core.Qtt.Status.Failed); + return; + } + Internals.changeReport(Core.Qtt.Status.Passed); + } +} diff --git a/tests/remote/AssistantTest.qml b/tests/remote/AssistantTest.qml new file mode 100644 index 0000000..87e0733 --- /dev/null +++ b/tests/remote/AssistantTest.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import 'common' + +ApplicationTest { + name: 'Assistant test' + executableName: 'assistant' + + function run() { + var i, + zoomIn = app.item( { toolTip: "Zoom in"} ), + zoomOut = app.item( { toolTip: "Zoom out"} ); + + app.mouseClick(zoomIn, Qt.RightButton); + sleep(1000); + + for (i=0; i<10; i++) { + app.mouseClick(zoomIn); + } + + for (i=0; i<10; i++) { + app.mouseClick(zoomOut); + } + + app.keyPress(Qt.Key_H); + app.keyPress(Qt.Key_E); + app.keyPress(Qt.Key_L); + app.keyPress(Qt.Key_L); + app.keyPress(Qt.Key_O); + + var p = Qt.point(200,300); + app.mouseClick(p); + sleep(1000); + } +} diff --git a/tests/remote/QstObjectApiTests.qml b/tests/remote/QstObjectApiTests.qml new file mode 100644 index 0000000..e04f1b6 --- /dev/null +++ b/tests/remote/QstObjectApiTests.qml @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +import "qstobject" + +TestCollection { + name: 'QstObject api tests'; description: name + + ItemPropertyTest{} + ParentApiTest{} + InheritanceBasedItemHandlerTest{} +} + diff --git a/tests/remote/RemoteApiTests.qml b/tests/remote/RemoteApiTests.qml new file mode 100644 index 0000000..84cb71e --- /dev/null +++ b/tests/remote/RemoteApiTests.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import 'common' + +TestCollection { + name: 'Remote component Test'; description: name + + ApplicationTest { + name: 'Same Application object test'; description: name + executableName: 'testapp_widgets' + + function run() { + var currentApp = remote.currentApplication(); + expect(currentApp.toString()).toBe(app.toString()); + expect(currentApp).toBe(app); + } + } + +} + diff --git a/tests/remote/RunProcessTests.qml b/tests/remote/RunProcessTests.qml new file mode 100644 index 0000000..c85ad8f --- /dev/null +++ b/tests/remote/RunProcessTests.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +import "runProcess" + +TestCollection { + name: 'runProcess tests'; description: name + + RunCommandTest{} +} diff --git a/tests/remote/TestAppWidgetTest.qml b/tests/remote/TestAppWidgetTest.qml new file mode 100644 index 0000000..3cf62ee --- /dev/null +++ b/tests/remote/TestAppWidgetTest.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import 'common' + +ApplicationTest { + name: 'testwidget tests' + executableName: 'testapp_widgets' + + function run() { + var textEdit = app.item({ + inherits: 'QLineEdit' + } ); + + expect(textEdit.property('text')).not.toBe(undefined); + expect(textEdit.property('text')).toBe(''); + app.mouseClick(textEdit); + + app.keyPress(Qt.Key_H); + app.keyPress(Qt.Key_E); + app.keyPress(Qt.Key_L); + app.keyPress(Qt.Key_L); + app.keyPress(Qt.Key_O); + + expect(textEdit.property('text')).toBe('hello'); + } + +} diff --git a/tests/remote/common/ApplicationTest.qml b/tests/remote/common/ApplicationTest.qml new file mode 100644 index 0000000..5af0acd --- /dev/null +++ b/tests/remote/common/ApplicationTest.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +Test { + name: ''; description: name + + property string executableName: '' + property Application app + property alias remote: host + + remotes: [ + Remote { + id: host + host: config.remotes.localhost.address + } + ] + + + function setup() { + expect(executableName).not.toBe(''); + app = host.startApplication(executableName); + } + + function cleanup() { + app.terminate(); + } +} diff --git a/tests/remote/qstobject/InheritanceBasedItemHandlerTest.qml b/tests/remote/qstobject/InheritanceBasedItemHandlerTest.qml new file mode 100644 index 0000000..83b1fd4 --- /dev/null +++ b/tests/remote/qstobject/InheritanceBasedItemHandlerTest.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import '../common' + +ApplicationTest { + name: 'parent api test' + executableName: 'testapp_widgets' + + function run() { + var textEdit = app.item({ + inherits: 'QLineEdit' + }); + + expect(textEdit.type()).toBe('QLineEdit'); + expect(textEdit.handles).toBe('QWidget'); + + core().ItemFactory.register('QLineEdit', 'MyQLineEdit.qml'); + + var sameTextEdit = app.item({ + inherits: 'QLineEdit' + }); + expect(sameTextEdit.type()).toBe('QLineEdit'); + expect(sameTextEdit.handles).toBe('QLineEdit'); + + core().ItemFactory.unregister('QLineEdit'); + var textEdit3 = app.item({ + text: '', + inherits: 'QLineEdit' + } ); + expect(textEdit3.type()).toBe('QLineEdit'); + expect(textEdit3.handles).toBe('QWidget'); + + } +} diff --git a/tests/remote/qstobject/ItemPropertyTest.qml b/tests/remote/qstobject/ItemPropertyTest.qml new file mode 100644 index 0000000..9022045 --- /dev/null +++ b/tests/remote/qstobject/ItemPropertyTest.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import '../common' + +ApplicationTest { + name: 'property setProperty test' + executableName: 'testapp_widgets' + + function run() { + var textEdit = app.item({ + text: '', + inherits: 'QLineEdit' + } ); + + expect(textEdit.property('text')).not.toBe(undefined); + textEdit.setProperty('text', 'Hello World'); + expect(textEdit.property('text')).toBe('Hello World'); + } +} diff --git a/tests/remote/qstobject/MyQLineEdit.qml b/tests/remote/qstobject/MyQLineEdit.qml new file mode 100644 index 0000000..ee1a299 --- /dev/null +++ b/tests/remote/qstobject/MyQLineEdit.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 + +QstObject { + handles: 'QLineEdit' + function enter(text) { + } +} diff --git a/tests/remote/qstobject/ParentApiTest.qml b/tests/remote/qstobject/ParentApiTest.qml new file mode 100644 index 0000000..59e0008 --- /dev/null +++ b/tests/remote/qstobject/ParentApiTest.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import QtSystemTest 1.0 +import '../common' + +ApplicationTest { + name: 'parent api test' + executableName: 'testapp_widgets' + + function run() { + var textEdit = app.item({ + text: '', + inherits: 'QLineEdit' + } ); + expect(textEdit.type()).toBe('QLineEdit'); + + var parent = textEdit.parent(); + expect(parent).not.toBe(undefined); + expect(parent.__isQmlWrapper).toBe(true); + expect(parent.type()).not.toBe(undefined); + } +} diff --git a/tests/remote/qstobject/QstObjectApiTests.qml b/tests/remote/qstobject/QstObjectApiTests.qml new file mode 100644 index 0000000..9e42e15 --- /dev/null +++ b/tests/remote/qstobject/QstObjectApiTests.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtSystemTest 1.0 +import '../common' + +ApplicationTest { + name: 'parent api test' + executableName: 'testapp_widgets' + + function run() { + var textEdit = app.item({ + text: '', + inherits: 'QLineEdit' + } ); + expect(textEdit.type()).toBe('QLineEdit'); + + var parent = textEdit.parent(); + expect(parent).not.toBe(undefined); + expect(parent.__isQmlWrapper).toBe(true); + expect(parent.type()).not.toBe(undefined); + } +} + diff --git a/tests/remote/runProcess/RunCommandTest.qml b/tests/remote/runProcess/RunCommandTest.qml new file mode 100644 index 0000000..22f9f7e --- /dev/null +++ b/tests/remote/runProcess/RunCommandTest.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of QtSystemTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtSystemTest 1.0 + +Test { + name: 'run ls'; description: name + + remotes: [ + Remote { + id: host + host: config.remotes.localhost.address + } + ] + + function run() { + var output = host.runProcess( { program: "/bin/ls", timeout: 1000 } ); + expect(output).not.toBe(undefined); + expect(output).not.toBe(null); + expect(output.length).not.toBe(0); + log(output); + } +} diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 0000000..8915388 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,31 @@ +TEMPLATE = aux +OTHER_FILES = \ + AllTests.qml \ + InterpreterTests.qml \ + interpreter/RunnerTests.qml \ + interpreter/runner/EmptyTest.qml \ + interpreter/runner/FailTest.qml \ + interpreter/runner/MyUtils.js \ + interpreter/runner/SkipTest.qml \ + interpreter/runner/EmptyTests.qml \ + interpreter/runner/RunnerInternals.js \ + interpreter/runner/UntestedTests.qml \ + interpreter/runner/UntestedTest.qml \ + interpreter/runner/DefaultConfigTest.qml \ + interpreter/CoreTests.qml \ + interpreter/core/ClassTest.qml \ + interpreter/core/FailApiTest.qml \ + interpreter/core/SleepTest.qml \ + interpreter/core/ExpectApiTests.qml \ + interpreter/core/ItemHandlerTests.qml \ + interpreter/core/itemhandlers/DefaultItemHandler.qml \ + interpreter/core/itemhandlers/RegisterUnregisterHandlerTest.qml \ + interpreter/core/itemhandlers/CustomItemHandlerTest.qml \ + interpreter/core/itemhandlers/QstPushButton.qml \ + MyConfig.qml \ + RemoteTests.qml \ + remote/RunProcessTests.qml \ + remote/runProcess/RunCommandTest.qml \ + remote/ItemPropertyTest.qml \ + remote/assistant/AssistantTest.qml \ + remote/TestAppWidgetTest.qml |