diff options
Diffstat (limited to 'tests/auto')
14 files changed, 1008 insertions, 0 deletions
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/SequenceConversionComponent.qml b/tests/auto/declarative/qdeclarativeecmascript/data/SequenceConversionComponent.qml new file mode 100644 index 0000000000..0c7f60b062 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/SequenceConversionComponent.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +MySequenceConversionObject { + id: sccmsco + objectName: "sccmsco" +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.array.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.array.qml new file mode 100644 index 0000000000..5eaa225708 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.array.qml @@ -0,0 +1,152 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + } + + property bool success: false + + property variant intList + property variant qrealList + property variant boolList + property variant stringList + + function indexedAccess() { + intList = msco.intListProperty; + var jsIntList = msco.intListProperty; + qrealList = msco.qrealListProperty; + var jsQrealList = msco.qrealListProperty; + boolList = msco.boolListProperty; + var jsBoolList = msco.boolListProperty; + stringList = msco.stringListProperty; + var jsStringList = msco.stringListProperty; + + // Three cases: direct property modification, variant copy modification, js var reference modification. + // Only the first and third should "write back" to the original QObject Q_PROPERTY; the second one + // should have no effect whatsoever to maintain "property variant" semantics (see e.g., valuetype). + success = true; + + msco.intListProperty[1] = 33; + if (msco.intListProperty[1] != 33) success = false; // ensure write back + intList[1] = 44; + if (intList[1] == 44) success = false; // ensure no effect + jsIntList[1] = 55; + if (jsIntList[1] != 55 + || jsIntList[1] != msco.intListProperty[1]) success = false; // ensure write back + + msco.qrealListProperty[1] = 33.3; + if (msco.qrealListProperty[1] != 33.3) success = false; // ensure write back + qrealList[1] = 44.4; + if (qrealList[1] == 44.4) success = false; // ensure no effect + jsQrealList[1] = 55.5; + if (jsQrealList[1] != 55.5 + || jsQrealList[1] != msco.qrealListProperty[1]) success = false; // ensure write back + + msco.boolListProperty[1] = true; + if (msco.boolListProperty[1] != true) success = false; // ensure write back + boolList[1] = true; + if (boolList[1] != false) success = false; // ensure no effect + jsBoolList[1] = false; + if (jsBoolList[1] != false + || jsBoolList[1] != msco.boolListProperty[1]) success = false; // ensure write back + + msco.stringListProperty[1] = "changed"; + if (msco.stringListProperty[1] != "changed") success = false; // ensure write back + stringList[1] = "changed"; + if (stringList[1] != "second") success = false; // ensure no effect + jsStringList[1] = "different"; + if (jsStringList[1] != "different" + || jsStringList[1] != msco.stringListProperty[1]) success = false; // ensure write back + } + + function arrayOperations() { + success = true; + var expected = 0; + var expectedStr = ""; + + // ecma262r3 defines array as implementing Length and Put. Test put here. + msco.intListProperty.asdf = 5; // shouldn't work, only indexes are valid names. + if (msco.intListProperty.asdf == 5) success = false; + msco.intListProperty[3] = 38; // should work. + if (msco.intListProperty[3] != 38) success = false; + msco.intListProperty[199] = 200; // should work, and should set length to 200. + if (msco.intListProperty[199] != 200) success = false; + if (msco.intListProperty.length != 200) success = false; + + // other operations are defined on the array prototype; see if they work. + msco.intListProperty = [ 0, 1, 2, 3, 4, 5, 6, 7 ]; + msco.intListProperty.splice(1,3, 33, 44, 55, 66); + expected = [ 0, 33, 44, 55, 66, 4, 5, 6, 7 ]; + if (msco.intListProperty.toString() != expected.toString()) success = false; + + msco.qrealListProperty = [ 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1 ]; + msco.qrealListProperty.splice(1,3, 33.33, 44.44, 55.55, 66.66); + expected = [ 0.1, 33.33, 44.44, 55.55, 66.66, 4.1, 5.1, 6.1, 7.1 ]; + if (msco.qrealListProperty.toString() != expected.toString()) success = false; + + msco.boolListProperty = [ false, true, true, false, false, true, false, true ]; + msco.boolListProperty.splice(1,3, false, true, false, false); + expected = [ false, false, true, false, false, false, true, false, true ]; + if (msco.boolListProperty.toString() != expected.toString()) success = false; + + msco.stringListProperty = [ "one", "two", "three", "four", "five", "six", "seven", "eight" ]; + msco.stringListProperty.splice(1,3, "nine", "ten", "eleven", "twelve"); + expected = [ "one", "nine", "ten", "eleven", "twelve", "five", "six", "seven", "eight" ]; + if (msco.stringListProperty.toString() != expected.toString()) success = false; + } + + property variant variantList: [ 1, 2, 3, 4, 5 ]; + property variant variantList2: [ 1, 2, 3, 4, 5 ]; + function testEqualitySemantics() { + // ensure equality semantics match JS array equality semantics + success = true; + + msco.intListProperty = [ 1, 2, 3, 4, 5 ]; + msco.intListProperty2 = [ 1, 2, 3, 4, 5 ]; + var jsIntList = [ 1, 2, 3, 4, 5 ]; + var jsIntList2 = [ 1, 2, 3, 4, 5 ]; + + if (jsIntList != jsIntList) success = false; + if (jsIntList == jsIntList2) success = false; + if (jsIntList == msco.intListProperty) success = false; + if (jsIntList == variantList) success = false; + + if (msco.intListProperty != msco.intListProperty) success = false; + if (msco.intListProperty == msco.intListProperty2) success = false; + if (msco.intListProperty == jsIntList) success = false; + if (msco.intListProperty == variantList) success = false; + + if (variantList == variantList) return false; + if (variantList == variantList2) return false; + if (variantList == msco.intListProperty) return false; + if (variantList == jsIntList) return false; + + if ((jsIntList == jsIntList2) != (jsIntList == msco.intListProperty)) success = false; + if ((jsIntList == jsIntList2) != (msco.intListProperty == msco.intListProperty2)) success = false; + if ((jsIntList == jsIntList) != (msco.intListProperty == msco.intListProperty)) success = false; + if ((jsIntList == variantList) != (msco.intListProperty == variantList)) success = false; + if ((variantList == jsIntList) != (variantList == msco.intListProperty)) success = false; + if ((msco.intListProperty == variantList) != (variantList == msco.intListProperty)) success = false; + } + + property bool referenceDeletion: false + function testReferenceDeletion() { + referenceDeletion = true; + var testObj = msco.generateTestObject(); + testObj.intListProperty = [1, 2, 3, 4, 5]; + var testSequence = testObj.intListProperty; + var prevString = testSequence.toString(); + var prevValueOf = testSequence.valueOf(); + var prevLength = testSequence.length; + msco.deleteTestObject(testObj); // delete referenced object. + if (testSequence.toString() == prevString) referenceDeletion = false; + if (testSequence.valueOf() == prevValueOf) referenceDeletion = false; + if (testSequence.length == prevLength) referenceDeletion = false; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.bindings.error.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.bindings.error.qml new file mode 100644 index 0000000000..9c87dd293e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.bindings.error.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + intListProperty: [ 1, 2, 3, 6, 7 ] + } + + MySequenceConversionObject { + id: mscoTwo + objectName: "mscoTwo" + boolListProperty: msco.intListProperty + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.bindings.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.bindings.qml new file mode 100644 index 0000000000..8d83e9f9f5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.bindings.qml @@ -0,0 +1,28 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + intListProperty: [ 1, 2, 3, 6, 7 ] + } + + MySequenceConversionObject { + id: mscoTwo + objectName: "mscoTwo" + intListProperty: msco.intListProperty + } + + property variant boundSequence: msco.intListProperty + property int boundElement: msco.intListProperty[3] + property variant boundSequenceTwo: mscoTwo.intListProperty + + Component.onCompleted: { + msco.intListProperty[3] = 12; + mscoTwo.intListProperty[4] = 14; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.copy.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.copy.qml new file mode 100644 index 0000000000..f6614dad0c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.copy.qml @@ -0,0 +1,160 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + } + + property bool success: true + + property variant intList + property variant qrealList + property variant boolList + property variant stringList + property variant urlList + property variant qstringList + + // this test ensures that the "copy resource" codepaths work + function testCopySequences() { + success = true; + + // create "copy resource" sequences + var jsIntList = msco.generateIntSequence(); + var jsQrealList = msco.generateQrealSequence(); + var jsBoolList = msco.generateBoolSequence(); + var jsStringList = msco.generateStringSequence(); + var jsUrlList = msco.generateUrlSequence(); + var jsQStringList = msco.generateQStringSequence(); + + if (jsIntList.toString() != [1, 2, 3].toString()) + success = false; + if (jsQrealList.toString() != [1.1, 2.2, 3.3].toString()) + success = false; + if (jsBoolList.toString() != [true, false, true].toString()) + success = false; + if (jsStringList.toString() != ["one", "two", "three"].toString()) + success = false; + if (jsUrlList.toString() != ["http://www.example1.com", "http://www.example2.com", "http://www.example3.com"].toString()) + success = false; + if (jsQStringList.toString() != ["one", "two", "three"].toString()) + success = false; + + // copy the sequence; should result in a new copy + intList = jsIntList; + qrealList = jsQrealList; + boolList = jsBoolList; + stringList = jsStringList; + urlList = jsUrlList; + qstringList = jsQStringList; + + // these operations shouldn't modify either variables - because + // we don't handle writing to the intermediate variant at list[index] + // for variant properties. + intList[1] = 8; + qrealList[1] = 8.8; + boolList[1] = true; + stringList[1] = "eight"; + urlList[1] = "http://www.example8.com"; + qstringList[1] = "eight"; + + if (jsIntList[1] == 8) + success = false; + if (jsQrealList[1] == 8.8) + success = false; + if (jsBoolList[1] == true) + success = false; + if (jsStringList[1] == "eight") + success = false; + if (jsUrlList[1] == "http://www.example8.com") + success = false; + if (jsQStringList[1] == "eight") + success = false; + + // assign a "copy resource" sequence to a QObject Q_PROPERTY + msco.intListProperty = intList; + msco.qrealListProperty = qrealList; + msco.boolListProperty = boolList; + msco.stringListProperty = stringList; + msco.urlListProperty = urlList; + msco.qstringListProperty = qstringList; + + if (msco.intListProperty.toString() != [1, 2, 3].toString()) + success = false; + if (msco.qrealListProperty.toString() != [1.1, 2.2, 3.3].toString()) + success = false; + if (msco.boolListProperty.toString() != [true, false, true].toString()) + success = false; + if (msco.stringListProperty.toString() != ["one", "two", "three"].toString()) + success = false; + if (msco.urlListProperty.toString() != ["http://www.example1.com", "http://www.example2.com", "http://www.example3.com"].toString()) + success = false; + if (msco.qstringListProperty.toString() != ["one", "two", "three"].toString()) + success = false; + + // now modify the QObject Q_PROPERTY (reference resource) sequences - shouldn't modify the copy resource sequences. + msco.intListProperty[2] = 9; + msco.qrealListProperty[2] = 9.9; + msco.boolListProperty[2] = false; + msco.stringListProperty[2] = "nine"; + msco.urlListProperty[2] = "http://www.example9.com"; + msco.qstringListProperty[2] = "nine"; + + if (intList[2] == 9) + success = false; + if (qrealList[2] == 9.9) + success = false; + if (boolList[2] == false) + success = false; + if (stringList[2] == "nine") + success = false; + if (urlList[2] == "http://www.example9.com") + success = false; + if (qstringList[2] == "nine") + success = false; + } + + property int intVal + property real qrealVal + property bool boolVal + property string stringVal + + // this test ensures that indexed access works for copy resource sequences. + function readSequenceCopyElements() { + success = true; + + var jsIntList = msco.generateIntSequence(); + var jsQrealList = msco.generateQrealSequence(); + var jsBoolList = msco.generateBoolSequence(); + var jsStringList = msco.generateStringSequence(); + + intVal = jsIntList[1]; + qrealVal = jsQrealList[1]; + boolVal = jsBoolList[1]; + stringVal = jsStringList[1]; + + if (intVal != 2) + success = false; + if (qrealVal != 2.2) + success = false; + if (boolVal != false) + success = false; + if (stringVal != "two") + success = false; + } + + // this test ensures that equality works for copy resource sequences. + function testEqualitySemantics() { + success = true; + + var jsIntList = msco.generateIntSequence(); + var jsIntList2 = msco.generateIntSequence(); + + if (jsIntList == jsIntList2) success = false; + if (jsIntList != jsIntList) success = false; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.read.error.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.read.error.qml new file mode 100644 index 0000000000..12a76d7e7d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.read.error.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + } + + property int pointListLength: 0 + property variant pointList + + function performTest() { + // we have NOT registered QList<QPoint> as a type + pointListLength = msco.pointListProperty.length; + pointList = msco.pointListProperty; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.read.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.read.qml new file mode 100644 index 0000000000..4a8a4a17b2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.read.qml @@ -0,0 +1,105 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + } + + property int intListLength: 0 + property variant intList + property int qrealListLength: 0 + property variant qrealList + property int boolListLength: 0 + property variant boolList + property int stringListLength: 0 + property variant stringList + property int urlListLength: 0 + property variant urlList + property int qstringListLength: 0 + property variant qstringList + + function readSequences() { + intListLength = msco.intListProperty.length; + intList = msco.intListProperty; + qrealListLength = msco.qrealListProperty.length; + qrealList = msco.qrealListProperty; + boolListLength = msco.boolListProperty.length; + boolList = msco.boolListProperty; + stringListLength = msco.stringListProperty.length; + stringList = msco.stringListProperty; + urlListLength = msco.urlListProperty.length; + urlList = msco.urlListProperty; + qstringListLength = msco.qstringListProperty.length; + qstringList = msco.qstringListProperty; + } + + property int intVal + property real qrealVal + property bool boolVal + property string stringVal + property url urlVal + property string qstringVal + + function readSequenceElements() { + intVal = msco.intListProperty[1]; + qrealVal = msco.qrealListProperty[1]; + boolVal = msco.boolListProperty[1]; + stringVal = msco.stringListProperty[1]; + urlVal = msco.urlListProperty[1]; + qstringVal = msco.qstringListProperty[1]; + } + + property bool enumerationMatches + function enumerateSequenceElements() { + var jsIntList = [1, 2, 3, 4, 5]; + msco.intListProperty = [1, 2, 3, 4, 5]; + + var jsIntListProps = [] + var seqIntListProps = [] + + enumerationMatches = true; + for (var i in jsIntList) { + jsIntListProps.push(i); + if (jsIntList[i] != msco.intListProperty[i]) { + enumerationMatches = false; + } + } + for (var j in msco.intListProperty) { + seqIntListProps.push(j); + if (jsIntList[j] != msco.intListProperty[j]) { + enumerationMatches = false; + } + } + + if (jsIntListProps.length != seqIntListProps.length) { + enumerationMatches = false; + } + + var emptyList = []; + msco.stringListProperty = [] + if (emptyList.toString() != msco.stringListProperty.toString()) { + enumerationMatches = false; + } + if (emptyList.valueOf() != msco.stringListProperty.valueOf()) { + enumerationMatches = false; + } + } + + property bool referenceDeletion: false + function testReferenceDeletion() { + referenceDeletion = true; + var testObj = msco.generateTestObject(); + testObj.intListProperty = [1, 2, 3, 4, 5]; + var testSequence = testObj.intListProperty; + if (testSequence[4] != 5) + referenceDeletion = false; + msco.deleteTestObject(testObj); // delete referenced object. + if (testSequence[4] == 5) + referenceDeletion = false; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.threads.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.threads.qml new file mode 100644 index 0000000000..5c4afe0574 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.threads.qml @@ -0,0 +1,69 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + } + + property bool success: false + property bool finished: false + + function testIntSequence() { + msco.intListProperty = [ 0, 1, 2, 3, 4, 5, 6, 7 ]; + worker.sendSequence(msco.intListProperty); + } + + function testQrealSequence() { + msco.qrealListProperty = [ 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1 ]; + worker.sendSequence(msco.qrealListProperty); + } + + function testBoolSequence() { + msco.boolListProperty = [ false, true, true, false, false, true, false, true ]; + worker.sendSequence(msco.boolListProperty); + } + + function testStringSequence() { + msco.stringListProperty = [ "one", "two", "three", "four" ]; + worker.sendSequence(msco.stringListProperty); + } + + function testQStringSequence() { + msco.qstringListProperty = [ "one", "two", "three", "four" ]; + worker.sendSequence(msco.qstringListProperty); + } + + function testUrlSequence() { + msco.urlListProperty = [ "www.example1.com", "www.example2.com", "www.example3.com", "www.example4.com" ]; + worker.sendSequence(msco.urlListProperty); + } + + WorkerScript { + id: worker + source: "threadScript.js" + + property variant expected + property variant response + + function sendSequence(seq) { + root.success = false; + root.finished = false; + worker.expected = seq; + worker.sendMessage(seq); + } + + onMessage: { + worker.response = messageObject; + if (worker.response.toString() == worker.expected.toString()) + root.success = true; + else + root.success = false; + root.finished = true; + } + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.write.error.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.write.error.qml new file mode 100644 index 0000000000..75beafd1ee --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.write.error.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + } + + function performTest() { + // we have NOT registered QList<QPoint> as a type + var pointList = [ Qt.point(7,7), Qt.point(8,8), Qt.point(9,9) ]; + msco.pointListProperty = pointList; // error. + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.write.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.write.qml new file mode 100644 index 0000000000..812de043b7 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sequenceConversion.write.qml @@ -0,0 +1,109 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + objectName: "root" + + MySequenceConversionObject { + id: msco + objectName: "msco" + } + + property bool success + + function writeSequences() { + success = true; + + var intList = [ 9, 8, 7, 6 ]; + msco.intListProperty = intList; + var qrealList = [ 9.9, 8.8, 7.7, 6.6 ]; + msco.qrealListProperty = qrealList; + var boolList = [ false, false, false, true ]; + msco.boolListProperty = boolList; + var stringList = [ "nine", "eight", "seven", "six" ] + msco.stringListProperty = stringList; + var urlList = [ "http://www.example9.com", "http://www.example8.com", "http://www.example7.com", "http://www.example6.com" ] + msco.urlListProperty = urlList; + var qstringList = [ "nine", "eight", "seven", "six" ] + msco.qstringListProperty = qstringList; + + if (msco.intListProperty[0] != 9 || msco.intListProperty[1] != 8 || msco.intListProperty[2] != 7 || msco.intListProperty[3] != 6) + success = false; + if (msco.qrealListProperty[0] != 9.9 || msco.qrealListProperty[1] != 8.8 || msco.qrealListProperty[2] != 7.7 || msco.qrealListProperty[3] != 6.6) + success = false; + if (msco.boolListProperty[0] != false || msco.boolListProperty[1] != false || msco.boolListProperty[2] != false || msco.boolListProperty[3] != true) + success = false; + if (msco.stringListProperty[0] != "nine" || msco.stringListProperty[1] != "eight" || msco.stringListProperty[2] != "seven" || msco.stringListProperty[3] != "six") + success = false; + if (msco.urlListProperty[0] != "http://www.example9.com" || msco.urlListProperty[1] != "http://www.example8.com" || msco.urlListProperty[2] != "http://www.example7.com" || msco.urlListProperty[3] != "http://www.example6.com") + success = false; + if (msco.qstringListProperty[0] != "nine" || msco.qstringListProperty[1] != "eight" || msco.qstringListProperty[2] != "seven" || msco.qstringListProperty[3] != "six") + success = false; + } + + function writeSequenceElements() { + // set up initial conditions. + writeSequences(); + success = true; + + // element set. + msco.intListProperty[3] = 2; + msco.qrealListProperty[3] = 2.2; + msco.boolListProperty[3] = false; + msco.stringListProperty[3] = "changed"; + msco.urlListProperty[3] = "http://www.examplechanged.com"; + msco.qstringListProperty[3] = "changed"; + + if (msco.intListProperty[0] != 9 || msco.intListProperty[1] != 8 || msco.intListProperty[2] != 7 || msco.intListProperty[3] != 2) + success = false; + if (msco.qrealListProperty[0] != 9.9 || msco.qrealListProperty[1] != 8.8 || msco.qrealListProperty[2] != 7.7 || msco.qrealListProperty[3] != 2.2) + success = false; + if (msco.boolListProperty[0] != false || msco.boolListProperty[1] != false || msco.boolListProperty[2] != false || msco.boolListProperty[3] != false) + success = false; + if (msco.stringListProperty[0] != "nine" || msco.stringListProperty[1] != "eight" || msco.stringListProperty[2] != "seven" || msco.stringListProperty[3] != "changed") + success = false; + if (msco.urlListProperty[0] != "http://www.example9.com" || msco.urlListProperty[1] != "http://www.example8.com" || msco.urlListProperty[2] != "http://www.example7.com" || msco.urlListProperty[3] != "http://www.examplechanged.com") + success = false; + if (msco.qstringListProperty[0] != "nine" || msco.qstringListProperty[1] != "eight" || msco.qstringListProperty[2] != "seven" || msco.qstringListProperty[3] != "changed") + success = false; + } + + function writeOtherElements() { + success = true; + var jsIntList = [1, 2, 3, 4, 5]; + msco.intListProperty = [1, 2, 3, 4, 5]; + + jsIntList[8] = 8; + msco.intListProperty[8] = 8; + if (jsIntList[8] != msco.intListProperty[8]) + success = false; + if (jsIntList.length != msco.intListProperty.length) + success = false; + + // NOTE: we can't exactly match the spec here -- we fill the sequence with a default (rather than empty) value + if (msco.intListProperty[5] != 0 || msco.intListProperty[6] != 0 || msco.intListProperty[7] != 0) + success = false; + + // should have no effect + var currLength = jsIntList.length; + jsIntList.someThing = 9; + msco.intListProperty.someThing = 9; + if (msco.intListProperty.length != currLength) + success = false; + } + + property bool referenceDeletion: false + function testReferenceDeletion() { + referenceDeletion = true; + var testObj = msco.generateTestObject(); + testObj.intListProperty = [1, 2, 3, 4, 5]; + var testSequence = testObj.intListProperty; + if (testSequence[4] != 5) + referenceDeletion = false; + msco.deleteTestObject(testObj); // delete referenced object. + testSequence[4] = 5; // shouldn't work, since referenced object no longer exists. + if (testSequence[4] == 5) + referenceDeletion = false; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/threadScript.js b/tests/auto/declarative/qdeclarativeecmascript/data/threadScript.js new file mode 100644 index 0000000000..9f94de1bc1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/threadScript.js @@ -0,0 +1,4 @@ +WorkerScript.onMessage = function(msg) { + WorkerScript.sendMessage(msg); +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index 513705d697..781b78663f 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -196,6 +196,8 @@ void registerTypes() qmlRegisterType<MyDynamicCreationDestructionObject>("Qt.test", 1, 0, "MyDynamicCreationDestructionObject"); qmlRegisterType<WriteCounter>("Qt.test", 1, 0, "WriteCounter"); + + qmlRegisterType<MySequenceConversionObject>("Qt.test", 1, 0, "MySequenceConversionObject"); } #include "testtypes.moc" diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index 7684ddd438..af4225c8da 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -1148,6 +1148,87 @@ private: int m_count; }; +class MySequenceConversionObject : public QObject +{ + Q_OBJECT + + Q_PROPERTY (QList<int> intListProperty READ intListProperty WRITE setIntListProperty NOTIFY intListPropertyChanged) + Q_PROPERTY (QList<int> intListProperty2 READ intListProperty2 WRITE setIntListProperty2 NOTIFY intListProperty2Changed) + Q_PROPERTY (QList<qreal> qrealListProperty READ qrealListProperty WRITE setQrealListProperty NOTIFY qrealListPropertyChanged) + Q_PROPERTY (QList<bool> boolListProperty READ boolListProperty WRITE setBoolListProperty NOTIFY boolListPropertyChanged) + Q_PROPERTY (QList<QString> stringListProperty READ stringListProperty WRITE setStringListProperty NOTIFY stringListPropertyChanged) + Q_PROPERTY (QList<QUrl> urlListProperty READ urlListProperty WRITE setUrlListProperty NOTIFY urlListPropertyChanged) + + Q_PROPERTY (QStringList qstringListProperty READ qstringListProperty WRITE setQStringListProperty NOTIFY qstringListPropertyChanged) + Q_PROPERTY (QList<QPoint> pointListProperty READ pointListProperty WRITE setPointListProperty NOTIFY pointListPropertyChanged) + +public: + MySequenceConversionObject() + { + m_intList << 1 << 2 << 3 << 4; + m_intList2 << 1 << 2 << 3 << 4; + m_qrealList << 1.1 << 2.2 << 3.3 << 4.4; + m_boolList << true << false << true << false; + m_stringList << QLatin1String("first") << QLatin1String("second") << QLatin1String("third") << QLatin1String("fourth"); + m_urlList << QUrl("http://www.example1.com") << QUrl("http://www.example2.com") << QUrl("http://www.example3.com"); + + m_qstringList << QLatin1String("first") << QLatin1String("second") << QLatin1String("third") << QLatin1String("fourth"); + m_pointList << QPoint(1, 2) << QPoint(3, 4) << QPoint(5, 6); + } + + ~MySequenceConversionObject() {} + + QList<int> intListProperty() const { return m_intList; } + void setIntListProperty(const QList<int> &list) { m_intList = list; emit intListPropertyChanged(); } + QList<int> intListProperty2() const { return m_intList2; } + void setIntListProperty2(const QList<int> &list) { m_intList2 = list; emit intListProperty2Changed(); } + QList<qreal> qrealListProperty() const { return m_qrealList; } + void setQrealListProperty(const QList<qreal> &list) { m_qrealList = list; emit qrealListPropertyChanged(); } + QList<bool> boolListProperty() const { return m_boolList; } + void setBoolListProperty(const QList<bool> &list) { m_boolList = list; emit boolListPropertyChanged(); } + QList<QString> stringListProperty() const { return m_stringList; } + void setStringListProperty(const QList<QString> &list) { m_stringList = list; emit stringListPropertyChanged(); } + QList<QUrl> urlListProperty() const { return m_urlList; } + void setUrlListProperty(const QList<QUrl> &list) { m_urlList = list; emit urlListPropertyChanged(); } + QStringList qstringListProperty() const { return m_qstringList; } + void setQStringListProperty(const QStringList &list) { m_qstringList = list; emit qstringListPropertyChanged(); } + QList<QPoint> pointListProperty() const { return m_pointList; } + void setPointListProperty(const QList<QPoint> &list) { m_pointList = list; emit pointListPropertyChanged(); } + + // now for "copy resource" sequences: + Q_INVOKABLE QList<int> generateIntSequence() const { QList<int> retn; retn << 1 << 2 << 3; return retn; } + Q_INVOKABLE QList<qreal> generateQrealSequence() const { QList<qreal> retn; retn << 1.1 << 2.2 << 3.3; return retn; } + Q_INVOKABLE QList<bool> generateBoolSequence() const { QList<bool> retn; retn << true << false << true; return retn; } + Q_INVOKABLE QList<QString> generateStringSequence() const { QList<QString> retn; retn << "one" << "two" << "three"; return retn; } + Q_INVOKABLE QList<QUrl> generateUrlSequence() const { QList<QUrl> retn; retn << QUrl("http://www.example1.com") << QUrl("http://www.example2.com") << QUrl("http://www.example3.com"); return retn; } + Q_INVOKABLE QStringList generateQStringSequence() const { QStringList retn; retn << "one" << "two" << "three"; return retn; } + + // "reference resource" underlying qobject deletion test: + Q_INVOKABLE MySequenceConversionObject *generateTestObject() const { return new MySequenceConversionObject; } + Q_INVOKABLE void deleteTestObject(QObject *object) const { delete object; } + +signals: + void intListPropertyChanged(); + void intListProperty2Changed(); + void qrealListPropertyChanged(); + void boolListPropertyChanged(); + void stringListPropertyChanged(); + void urlListPropertyChanged(); + void qstringListPropertyChanged(); + void pointListPropertyChanged(); + +private: + QList<int> m_intList; + QList<int> m_intList2; + QList<qreal> m_qrealList; + QList<bool> m_boolList; + QList<QString> m_stringList; + QList<QUrl> m_urlList; + + QStringList m_qstringList; // not a supported sequence type, but QStringList support is hardcoded. + QList<QPoint> m_pointList; // not a supported sequence type +}; + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index c92dc809e9..ee228ec3b8 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -170,6 +170,13 @@ private slots: void handleReferenceManagement(); void stringArg(); void readonlyDeclaration(); + void sequenceConversionRead(); + void sequenceConversionWrite(); + void sequenceConversionArray(); + void sequenceConversionThreads(); + void sequenceConversionBindings(); + void sequenceConversionCopy(); + void bug1(); void bug2(); void dynamicCreationCrash(); @@ -4048,6 +4055,232 @@ void tst_qdeclarativeecmascript::readonlyDeclaration() delete object; } +Q_DECLARE_METATYPE(QList<int>) +Q_DECLARE_METATYPE(QList<qreal>) +Q_DECLARE_METATYPE(QList<bool>) +Q_DECLARE_METATYPE(QList<QString>) +Q_DECLARE_METATYPE(QList<QUrl>) +void tst_qdeclarativeecmascript::sequenceConversionRead() +{ + { + QUrl qmlFile = TEST_FILE("sequenceConversion.read.qml"); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco"); + QVERIFY(seq != 0); + + QMetaObject::invokeMethod(object, "readSequences"); + QList<int> intList; intList << 1 << 2 << 3 << 4; + QCOMPARE(object->property("intListLength").toInt(), intList.length()); + QCOMPARE(object->property("intList").value<QList<int> >(), intList); + QList<qreal> qrealList; qrealList << 1.1 << 2.2 << 3.3 << 4.4; + QCOMPARE(object->property("qrealListLength").toInt(), qrealList.length()); + QCOMPARE(object->property("qrealList").value<QList<qreal> >(), qrealList); + QList<bool> boolList; boolList << true << false << true << false; + QCOMPARE(object->property("boolListLength").toInt(), boolList.length()); + QCOMPARE(object->property("boolList").value<QList<bool> >(), boolList); + QList<QString> stringList; stringList << QLatin1String("first") << QLatin1String("second") << QLatin1String("third") << QLatin1String("fourth"); + QCOMPARE(object->property("stringListLength").toInt(), stringList.length()); + QCOMPARE(object->property("stringList").value<QList<QString> >(), stringList); + QList<QUrl> urlList; urlList << QUrl("http://www.example1.com") << QUrl("http://www.example2.com") << QUrl("http://www.example3.com"); + QCOMPARE(object->property("urlListLength").toInt(), urlList.length()); + QCOMPARE(object->property("urlList").value<QList<QUrl> >(), urlList); + QStringList qstringList; qstringList << QLatin1String("first") << QLatin1String("second") << QLatin1String("third") << QLatin1String("fourth"); + QCOMPARE(object->property("qstringListLength").toInt(), qstringList.length()); + QCOMPARE(object->property("qstringList").value<QStringList>(), qstringList); + + QMetaObject::invokeMethod(object, "readSequenceElements"); + QCOMPARE(object->property("intVal").toInt(), 2); + QCOMPARE(object->property("qrealVal").toReal(), 2.2); + QCOMPARE(object->property("boolVal").toBool(), false); + QCOMPARE(object->property("stringVal").toString(), QString(QLatin1String("second"))); + QCOMPARE(object->property("urlVal").toUrl(), QUrl("http://www.example2.com")); + QCOMPARE(object->property("qstringVal").toString(), QString(QLatin1String("second"))); + + QMetaObject::invokeMethod(object, "enumerateSequenceElements"); + QCOMPARE(object->property("enumerationMatches").toBool(), true); + + intList.clear(); intList << 1 << 2 << 3 << 4 << 5; // set by the enumerateSequenceElements test. + QDeclarativeProperty seqProp(seq, "intListProperty"); + QCOMPARE(seqProp.read().value<QList<int> >(), intList); + QDeclarativeProperty seqProp2(seq, "intListProperty", &engine); + QCOMPARE(seqProp2.read().value<QList<int> >(), intList); + + QMetaObject::invokeMethod(object, "testReferenceDeletion"); + QCOMPARE(object->property("referenceDeletion").toBool(), true); + + delete object; + } + + { + QUrl qmlFile = TEST_FILE("sequenceConversion.read.error.qml"); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco"); + QVERIFY(seq != 0); + + // we haven't registered QList<QPoint> as a sequence type. + QString warningOne = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'QList<QPoint>' for property 'MySequenceConversionObject::pointListProperty'"); + QString warningTwo = qmlFile.toString() + QLatin1String(":18: TypeError: Cannot read property 'length' of undefined"); + QTest::ignoreMessage(QtWarningMsg, warningOne.toAscii().constData()); + QTest::ignoreMessage(QtWarningMsg, warningTwo.toAscii().constData()); + + QMetaObject::invokeMethod(object, "performTest"); + + // QList<QPoint> has not been registered as a sequence type. + QCOMPARE(object->property("pointListLength").toInt(), 0); + QVERIFY(!object->property("pointList").isValid()); + QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::read: Unable to handle unregistered datatype 'QList<QPoint>' for property 'MySequenceConversionObject::pointListProperty'"); + QDeclarativeProperty seqProp(seq, "pointListProperty", &engine); + QVERIFY(!seqProp.read().isValid()); // not a valid/known sequence type + + delete object; + } +} + +void tst_qdeclarativeecmascript::sequenceConversionWrite() +{ + { + QUrl qmlFile = TEST_FILE("sequenceConversion.write.qml"); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco"); + QVERIFY(seq != 0); + + QMetaObject::invokeMethod(object, "writeSequences"); + QCOMPARE(object->property("success").toBool(), true); + + QMetaObject::invokeMethod(object, "writeSequenceElements"); + QCOMPARE(object->property("success").toBool(), true); + + QMetaObject::invokeMethod(object, "writeOtherElements"); + QCOMPARE(object->property("success").toBool(), true); + + QMetaObject::invokeMethod(object, "testReferenceDeletion"); + QCOMPARE(object->property("referenceDeletion").toBool(), true); + + delete object; + } + + { + QUrl qmlFile = TEST_FILE("sequenceConversion.write.error.qml"); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco"); + QVERIFY(seq != 0); + + // we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work. + QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QVariantList to void"); + QTest::ignoreMessage(QtWarningMsg, warningOne.toAscii().constData()); + + QMetaObject::invokeMethod(object, "performTest"); + + QList<QPoint> pointList; pointList << QPoint(1, 2) << QPoint(3, 4) << QPoint(5, 6); // original values, shouldn't have changed + QCOMPARE(seq->pointListProperty(), pointList); + + delete object; + } +} + +void tst_qdeclarativeecmascript::sequenceConversionArray() +{ + // ensure that in JS the returned sequences act just like normal JS Arrays. + QUrl qmlFile = TEST_FILE("sequenceConversion.array.qml"); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + //QMetaObject::invokeMethod(object, "indexedAccess"); + //QVERIFY(object->property("success").toBool()); + //QMetaObject::invokeMethod(object, "arrayOperations"); + //QVERIFY(object->property("success").toBool()); + QMetaObject::invokeMethod(object, "testEqualitySemantics"); + QVERIFY(object->property("success").toBool()); + //QMetaObject::invokeMethod(object, "testReferenceDeletion"); + //QCOMPARE(object->property("referenceDeletion").toBool(), true); + delete object; +} + +void tst_qdeclarativeecmascript::sequenceConversionThreads() +{ + // ensure that sequence conversion operations work correctly in a worker thread + // and that serialisation between the main and worker thread succeeds. + QUrl qmlFile = TEST_FILE("sequenceConversion.threads.qml"); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + + QMetaObject::invokeMethod(object, "testIntSequence"); + QTRY_VERIFY(object->property("finished").toBool()); + QVERIFY(object->property("success").toBool()); + + QMetaObject::invokeMethod(object, "testQrealSequence"); + QTRY_VERIFY(object->property("finished").toBool()); + QVERIFY(object->property("success").toBool()); + + QMetaObject::invokeMethod(object, "testBoolSequence"); + QTRY_VERIFY(object->property("finished").toBool()); + QVERIFY(object->property("success").toBool()); + + QMetaObject::invokeMethod(object, "testStringSequence"); + QTRY_VERIFY(object->property("finished").toBool()); + QVERIFY(object->property("success").toBool()); + + QMetaObject::invokeMethod(object, "testQStringSequence"); + QTRY_VERIFY(object->property("finished").toBool()); + QVERIFY(object->property("success").toBool()); + + QMetaObject::invokeMethod(object, "testUrlSequence"); + QTRY_VERIFY(object->property("finished").toBool()); + QVERIFY(object->property("success").toBool()); + + delete object; +} + +void tst_qdeclarativeecmascript::sequenceConversionBindings() +{ + { + QUrl qmlFile = TEST_FILE("sequenceConversion.bindings.qml"); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + QList<int> intList; intList << 1 << 2 << 3 << 12 << 7; + QCOMPARE(object->property("boundSequence").value<QList<int> >(), intList); + QCOMPARE(object->property("boundElement").toInt(), intList.at(3)); + QList<int> intListTwo; intListTwo << 1 << 2 << 3 << 12 << 14; + QCOMPARE(object->property("boundSequenceTwo").value<QList<int> >(), intListTwo); + delete object; + } + + { + QUrl qmlFile = TEST_FILE("sequenceConversion.bindings.error.qml"); + QString warning = QString(QLatin1String("%1:17: Unable to assign QList<int> to QList<bool>")).arg(qmlFile.toString()); + QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData()); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + delete object; + } +} + +void tst_qdeclarativeecmascript::sequenceConversionCopy() +{ + QUrl qmlFile = TEST_FILE("sequenceConversion.copy.qml"); + QDeclarativeComponent component(&engine, qmlFile); + QObject *object = component.create(); + QVERIFY(object != 0); + QMetaObject::invokeMethod(object, "testCopySequences"); + QCOMPARE(object->property("success").toBool(), true); + QMetaObject::invokeMethod(object, "readSequenceCopyElements"); + QCOMPARE(object->property("success").toBool(), true); + QMetaObject::invokeMethod(object, "testEqualitySemantics"); + QCOMPARE(object->property("success").toBool(), true); + delete object; +} + // Test that assigning a null object works // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4 void tst_qdeclarativeecmascript::nullObjectBinding() |