From 086f33dd4c70be03adcbc1703997afa27add920b Mon Sep 17 00:00:00 2001
From: Bea Lam <bea.lam@nokia.com>
Date: Tue, 4 Jan 2011 15:03:53 +1000
Subject: Fix results of number() queries for zero and non-number values

Use xs:string() to test whether a value is empty, instead of using a
simple boolean check which fails for zero-type values. This fix also
means 'NaN' is returned for non-number (including empty) values.

Task-number: QTBUG-16423, QTBUG-16265
Reviewed-by: Michael Brasser
---
 src/declarative/util/qdeclarativexmllistmodel.cpp  |  2 +-
 .../qdeclarativexmllistmodel/data/model2.qml       | 11 ----
 .../tst_qdeclarativexmllistmodel.cpp               | 76 ++++++++++++++++++----
 3 files changed, 64 insertions(+), 25 deletions(-)
 delete mode 100644 tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml

diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp
index 49a12b1..f5c3ad4 100644
--- a/src/declarative/util/qdeclarativexmllistmodel.cpp
+++ b/src/declarative/util/qdeclarativexmllistmodel.cpp
@@ -382,7 +382,7 @@ void QDeclarativeXmlQuery::doSubQueryJob()
     for (int i = 0; i < queries.size(); ++i) {
         QList<QVariant> resultList;
         if (!queries[i].isEmpty()) {
-            subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + queries[i] + QLatin1String(" return if ($v) then ") + queries[i] + QLatin1String(" else \"\")"));
+            subquery.setQuery(m_prefix + QLatin1String("(let $v := string(") + queries[i] + QLatin1String(") return if ($v) then ") + queries[i] + QLatin1String(" else \"\")"));
             if (subquery.isValid()) {
                 QXmlResultItems resultItems;
                 subquery.evaluateTo(&resultItems);
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml
deleted file mode 100644
index e56aafa..0000000
--- a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import QtQuick 1.0
-
-XmlListModel {
-    source: "model.xml"
-    query: "/Pets/Pet"
-    XmlRole { name: "name"; query: "name/string()" }
-    XmlRole { name: "type"; query: "type/string()" }
-    XmlRole { name: "age"; query: "age/number()" }
-    XmlRole { name: "size"; query: "size/string()" }
-    XmlRole { name: "tricks"; query: "tricks/string()" }
-}
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
index a14f942..3e81c53 100644
--- a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
@@ -38,6 +38,12 @@
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
+#include <private/qdeclarativeengine_p.h>
+
+#include <QtTest/QtTest>
+#include <QtGlobal>
+#include <math.h>
+
 #include <qtest.h>
 #include <QtTest/qsignalspy.h>
 #include <QtCore/qtimer.h>
@@ -75,7 +81,8 @@ private slots:
     }
 
     void buildModel();
-    void missingFields();
+    void testTypes();
+    void testTypes_data();
     void cdata();
     void attributes();
     void roles();
@@ -158,27 +165,70 @@ void tst_qdeclarativexmllistmodel::buildModel()
     delete model;
 }
 
-void tst_qdeclarativexmllistmodel::missingFields()
+void tst_qdeclarativexmllistmodel::testTypes()
 {
-    QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model2.qml"));
+    QFETCH(QString, xml);
+    QFETCH(QString, roleName);
+    QFETCH(QVariant, expectedValue);
+
+    QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/testtypes.qml"));
     QDeclarativeXmlListModel *model = qobject_cast<QDeclarativeXmlListModel*>(component.create());
     QVERIFY(model != 0);
-    QTRY_COMPARE(model->count(), 9);
+    model->setXml(xml.toUtf8());
+    model->reload();
+    QTRY_COMPARE(model->count(), 1);
 
-    QList<int> roles;
-    roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3 << Qt::UserRole + 4;
-    QHash<int, QVariant> data = model->data(5, roles);
-    QVERIFY(data.count() == 5);
-    QCOMPARE(data.value(Qt::UserRole+3).toString(), QLatin1String(""));
-    QCOMPARE(data.value(Qt::UserRole+4).toString(), QLatin1String(""));
+    int role = -1;
+    foreach (int i, model->roles()) {
+        if (model->toString(i) == roleName) {
+            role = i;
+            break;
+        }
+    }
+    QVERIFY(role >= 0);
 
-    data = model->data(7, roles);
-    QVERIFY(data.count() == 5);
-    QCOMPARE(data.value(Qt::UserRole+2).toString(), QLatin1String(""));
+    if (expectedValue.toString() == "nan")
+        QVERIFY(qIsNaN(model->data(0, role).toDouble()));
+    else
+        QCOMPARE(model->data(0, role), expectedValue);
 
     delete model;
 }
 
+void tst_qdeclarativexmllistmodel::testTypes_data()
+{
+    QTest::addColumn<QString>("xml");
+    QTest::addColumn<QString>("roleName");
+    QTest::addColumn<QVariant>("expectedValue");
+
+    QTest::newRow("missing string field") << "<data></data>"
+            << "stringValue" << QVariant("");
+    QTest::newRow("empty string") << "<data><a-string></a-string></data>"
+            << "stringValue" << QVariant("");
+    QTest::newRow("1-char string") << "<data><a-string>5</a-string></data>"
+            << "stringValue" << QVariant("5");
+    QTest::newRow("string ok") << "<data><a-string>abc def g</a-string></data>"
+            << "stringValue" << QVariant("abc def g");
+
+    QTest::newRow("missing number field") << "<data></data>"
+            << "numberValue" << QVariant("");
+    double nan = qQNaN();
+    QTest::newRow("empty number field") << "<data><a-number></a-number></data>"
+            << "numberValue" << QVariant(nan);
+    QTest::newRow("number field with string") << "<data><a-number>a string</a-number></data>"
+            << "numberValue" << QVariant(nan);
+    QTest::newRow("-1") << "<data><a-number>-1</a-number></data>"
+            << "numberValue" << QVariant("-1");
+    QTest::newRow("-1.5") << "<data><a-number>-1.5</a-number></data>"
+            << "numberValue" << QVariant("-1.5");
+    QTest::newRow("0") << "<data><a-number>0</a-number></data>"
+            << "numberValue" << QVariant("0");
+    QTest::newRow("+1") << "<data><a-number>1</a-number></data>"
+            << "numberValue" << QVariant("1");
+    QTest::newRow("+1.5") << "<data><a-number>1.5</a-number></data>"
+            << "numberValue" << QVariant("1.5");
+}
+
 void tst_qdeclarativexmllistmodel::cdata()
 {
     QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/recipes.qml"));
-- 
cgit v0.12