456 QFETCH(int, expectedValue); |
457 QFETCH(int, expectedValue); |
457 |
458 |
458 QValueSpaceSubscriber *subscriber = qvariant_cast<QValueSpaceSubscriber*>(testItem); |
459 QValueSpaceSubscriber *subscriber = qvariant_cast<QValueSpaceSubscriber*>(testItem); |
459 QCOMPARE(subscriber->parent(), (QObject*)this); |
460 QCOMPARE(subscriber->parent(), (QObject*)this); |
460 QCOMPARE(subscriber->value(), value); |
461 QCOMPARE(subscriber->value(), value); |
461 #ifdef Q_OS_SYMBIAN |
462 QVERIFY(subscriber->subPaths().toSet().contains(subPaths.toSet())); |
462 QVERIFY(subscriber->subPaths().toSet().contains(subPaths.toSet())); |
|
463 #else |
|
464 QCOMPARE(subscriber->subPaths().toSet(), subPaths.toSet()); |
|
465 #endif |
|
466 QCOMPARE(subscriber->path(), path); |
463 QCOMPARE(subscriber->path(), path); |
467 QCOMPARE(subscriber->value(relItemPath, 100).toInt(), expectedValue); |
464 QCOMPARE(subscriber->value(relItemPath, 100).toInt(), expectedValue); |
468 } |
465 } |
469 |
466 |
470 #define ADD(opt, invalid) do {\ |
467 #define ADD(opt, invalid) do {\ |
527 QStringList homeUserPaths; |
524 QStringList homeUserPaths; |
528 homeUserPaths << "bool" << "int" << "QString" << "QStringList" << "qint64" << "QByteArray" |
525 homeUserPaths << "bool" << "int" << "QString" << "QStringList" << "qint64" << "QByteArray" |
529 << "double" << "float" << "QChar"; |
526 << "double" << "float" << "QChar"; |
530 |
527 |
531 QCOMPARE(subscriber.path(), QLatin1String("/")); |
528 QCOMPARE(subscriber.path(), QLatin1String("/")); |
532 #ifdef Q_OS_SYMBIAN |
529 QVERIFY(subscriber.subPaths().toSet().contains(rootPaths.toSet())); |
533 QVERIFY(subscriber.subPaths().toSet().contains(rootPaths.toSet())); |
|
534 #else |
|
535 QCOMPARE(subscriber.subPaths().toSet(), rootPaths.toSet()); |
|
536 #endif |
|
537 |
530 |
538 subscriber.cd("home"); |
531 subscriber.cd("home"); |
539 QCOMPARE(subscriber.path(), QLatin1String("/home")); |
532 QCOMPARE(subscriber.path(), QLatin1String("/home")); |
540 #ifdef Q_OS_SYMBIAN |
533 QVERIFY(subscriber.subPaths().toSet().contains(homePaths.toSet())); |
541 QVERIFY(subscriber.subPaths().toSet().contains(homePaths.toSet())); |
|
542 #else |
|
543 QCOMPARE(subscriber.subPaths().toSet(), homePaths.toSet()); |
|
544 #endif |
|
545 |
534 |
546 subscriber.cd("user"); |
535 subscriber.cd("user"); |
547 QCOMPARE(subscriber.path(), QLatin1String("/home/user")); |
536 QCOMPARE(subscriber.path(), QLatin1String("/home/user")); |
548 #ifdef Q_OS_SYMBIAN |
537 QVERIFY(subscriber.subPaths().toSet().contains(homeUserPaths.toSet())); |
549 QVERIFY(subscriber.subPaths().toSet().contains(homeUserPaths.toSet())); |
|
550 #else |
|
551 QCOMPARE(subscriber.subPaths().toSet(), homeUserPaths.toSet()); |
|
552 #endif |
|
553 |
538 |
554 subscriber.cdUp(); |
539 subscriber.cdUp(); |
555 QCOMPARE(subscriber.path(), QLatin1String("/home")); |
540 QCOMPARE(subscriber.path(), QLatin1String("/home")); |
556 #ifdef Q_OS_SYMBIAN |
541 QVERIFY(subscriber.subPaths().toSet().contains(homePaths.toSet())); |
557 QVERIFY(subscriber.subPaths().toSet().contains(homePaths.toSet())); |
|
558 #else |
|
559 QCOMPARE(subscriber.subPaths().toSet(), homePaths.toSet()); |
|
560 #endif |
|
561 |
542 |
562 subscriber.cd("/home/user"); |
543 subscriber.cd("/home/user"); |
563 QCOMPARE(subscriber.path(), QLatin1String("/home/user")); |
544 QCOMPARE(subscriber.path(), QLatin1String("/home/user")); |
564 #ifdef Q_OS_SYMBIAN |
545 QVERIFY(subscriber.subPaths().toSet().contains(homeUserPaths.toSet())); |
565 QVERIFY(subscriber.subPaths().toSet().contains(homeUserPaths.toSet())); |
|
566 #else |
|
567 QCOMPARE(subscriber.subPaths().toSet(), homeUserPaths.toSet()); |
|
568 #endif |
|
569 } |
546 } |
570 |
547 |
571 void tst_QValueSpaceSubscriber::contentsChanged_data() |
548 void tst_QValueSpaceSubscriber::contentsChanged_data() |
572 { |
549 { |
573 QTest::addColumn<QAbstractValueSpaceLayer *>("layer"); |
550 QTest::addColumn<QAbstractValueSpaceLayer *>("layer"); |
771 QCOMPARE(base.value("home/user/QString", "default").toString(), QString("testString")); |
756 QCOMPARE(base.value("home/user/QString", "default").toString(), QString("testString")); |
772 QCOMPARE(base.value("home/user/bool", false).toBool(), true); |
757 QCOMPARE(base.value("home/user/bool", false).toBool(), true); |
773 QCOMPARE(base.value("home/user/int", 5).toInt(), 3); |
758 QCOMPARE(base.value("home/user/int", 5).toInt(), 3); |
774 QCOMPARE(base.value("home/user/QByteArray", QByteArray("invalid")).toByteArray(), |
759 QCOMPARE(base.value("home/user/QByteArray", QByteArray("invalid")).toByteArray(), |
775 QByteArray("testByteArray")); |
760 QByteArray("testByteArray")); |
776 QCOMPARE(base.value("home/user/double", 4.0).toDouble(), double(4.56)); |
761 QVERIFY(fabs(base.value("home/user/double", 4.0).toDouble() - double(4.56)) < 0.01); |
777 //QCOMPARE(base.value("home/user/float", 4.0).toDouble(), (double)4.56); |
762 //QCOMPARE(base.value("home/user/float", 4.0).toDouble(), (double)4.56); |
778 |
763 |
779 QValueSpaceSubscriber base1(layer->id(), QString("/home")); |
764 QValueSpaceSubscriber base1(layer->id(), QString("/home")); |
780 QCOMPARE(base1.value(QString("usercount"), 5).toInt(), 1); |
765 QCOMPARE(base1.value(QString("usercount"), 5).toInt(), 1); |
781 QCOMPARE(base1.value(QString("user/QString"), "default").toString(), QString("testString")); |
766 QCOMPARE(base1.value(QString("user/QString"), "default").toString(), QString("testString")); |
782 QCOMPARE(base1.value("user/bool", false).toBool(), true); |
767 QCOMPARE(base1.value("user/bool", false).toBool(), true); |
783 QCOMPARE(base1.value("user/int", 5).toInt(), 3); |
768 QCOMPARE(base1.value("user/int", 5).toInt(), 3); |
784 QCOMPARE(base1.value("user/QByteArray", QByteArray("invalid")).toByteArray(), |
769 QCOMPARE(base1.value("user/QByteArray", QByteArray("invalid")).toByteArray(), |
785 QByteArray("testByteArray")); |
770 QByteArray("testByteArray")); |
786 QCOMPARE(base1.value("user/double", 4.0).toDouble(), double(4.56)); |
771 QVERIFY(fabs(base.value("home/user/double", 4.0).toDouble() - double(4.56)) < 0.01); |
787 //QCOMPARE(base1.value("user/float", 4.0).toDouble(), double(4.56)); |
772 //QCOMPARE(base1.value("user/float", 4.0).toDouble(), double(4.56)); |
788 |
773 |
789 QValueSpaceSubscriber base2(layer->id(), QString("/home/user")); |
774 QValueSpaceSubscriber base2(layer->id(), QString("/home/user")); |
790 QCOMPARE(base2.value(QString("usercount"), 5).toInt(), 5); |
775 QCOMPARE(base2.value(QString("usercount"), 5).toInt(), 5); |
791 QCOMPARE(base2.value(QString("QString"), "default").toString(), QString("testString")); |
776 QCOMPARE(base2.value(QString("QString"), "default").toString(), QString("testString")); |
792 QCOMPARE(base2.value("bool", false).toBool(), true); |
777 QCOMPARE(base2.value("bool", false).toBool(), true); |
793 QCOMPARE(base2.value("int", 5).toInt(), 3); |
778 QCOMPARE(base2.value("int", 5).toInt(), 3); |
794 QCOMPARE(base2.value("QByteArray", QByteArray("invalid")).toByteArray(), |
779 QCOMPARE(base2.value("QByteArray", QByteArray("invalid")).toByteArray(), |
795 QByteArray("testByteArray")); |
780 QByteArray("testByteArray")); |
796 QCOMPARE(base2.value("double", 4.0).toDouble(), double(4.56)); |
781 QVERIFY(fabs(base.value("home/user/double", 4.0).toDouble() - double(4.56)) < 0.01); |
797 //QCOMPARE(base2.value("float", 4.0).toDouble(), 4.56); |
782 //QCOMPARE(base2.value("float", 4.0).toDouble(), 4.56); |
798 } |
783 } |
799 |
784 |
800 void tst_QValueSpaceSubscriber::ipcTests_data() |
785 void tst_QValueSpaceSubscriber::ipcTests_data() |
801 { |
786 { |
826 QSignalSpy spy(&listener, SIGNAL(baseChanged())); |
811 QSignalSpy spy(&listener, SIGNAL(baseChanged())); |
827 connect(&subscriber, SIGNAL(contentsChanged()), &listener, SIGNAL(baseChanged())); |
812 connect(&subscriber, SIGNAL(contentsChanged()), &listener, SIGNAL(baseChanged())); |
828 |
813 |
829 QProcess process; |
814 QProcess process; |
830 process.setProcessChannelMode(QProcess::ForwardedChannels); |
815 process.setProcessChannelMode(QProcess::ForwardedChannels); |
|
816 #ifdef Q_OS_UNIX |
|
817 process.start("./vsiTestLackey", QStringList() << "-ipcTests" << layer->id().toString()); |
|
818 #else |
831 process.start("vsiTestLackey", QStringList() << "-ipcTests" << layer->id().toString()); |
819 process.start("vsiTestLackey", QStringList() << "-ipcTests" << layer->id().toString()); |
|
820 #endif |
832 QVERIFY(process.waitForStarted()); |
821 QVERIFY(process.waitForStarted()); |
833 |
822 |
834 //lackey sets value to 100 as part of its startup |
823 //lackey sets value to 100 as part of its startup |
835 QTRY_COMPARE(spy.count(), 1); |
824 QTRY_COMPARE(spy.count(), 1); |
836 QCOMPARE(subscriber.value("", 99).toInt(), 100); |
825 QCOMPARE(subscriber.value("", 99).toInt(), 100); |
898 QSignalSpy changeSpy(&listener, SIGNAL(baseChanged())); |
887 QSignalSpy changeSpy(&listener, SIGNAL(baseChanged())); |
899 QObject::connect(&subscriber, SIGNAL(contentsChanged()), &listener, SIGNAL(baseChanged())); |
888 QObject::connect(&subscriber, SIGNAL(contentsChanged()), &listener, SIGNAL(baseChanged())); |
900 |
889 |
901 QProcess process; |
890 QProcess process; |
902 process.setProcessChannelMode(QProcess::ForwardedChannels); |
891 process.setProcessChannelMode(QProcess::ForwardedChannels); |
|
892 #ifdef Q_OS_UNIX |
|
893 process.start("./vsiTestLackey", QStringList() << "-ipcRemoveKey" << layer->id().toString()); |
|
894 #else |
903 process.start("vsiTestLackey", QStringList() << "-ipcRemoveKey" << layer->id().toString()); |
895 process.start("vsiTestLackey", QStringList() << "-ipcRemoveKey" << layer->id().toString()); |
|
896 #endif |
904 QVERIFY(process.waitForStarted()); |
897 QVERIFY(process.waitForStarted()); |
905 |
898 |
906 // Wait for lackey to create "value". |
899 // Wait for lackey to create "value". |
907 QTRY_COMPARE(changeSpy.count(), 1); |
900 QTRY_COMPARE(changeSpy.count(), 1); |
908 QCOMPARE(subscriber.value("value", 5).toInt(), 100); |
901 QCOMPARE(subscriber.value("value", 5).toInt(), 100); |
1039 // Lackey is not running, so value will not exist. |
1032 // Lackey is not running, so value will not exist. |
1040 QCOMPARE(subscriber->value(QString(), 10).toInt(), 10); |
1033 QCOMPARE(subscriber->value(QString(), 10).toInt(), 10); |
1041 |
1034 |
1042 QProcess process; |
1035 QProcess process; |
1043 process.setProcessChannelMode(QProcess::ForwardedChannels); |
1036 process.setProcessChannelMode(QProcess::ForwardedChannels); |
|
1037 #ifdef Q_OS_UNIX |
|
1038 process.start("./vsiTestLackey", QStringList() |
|
1039 << "-ipcInterestNotification" << layer->id().toString()); |
|
1040 #else |
1044 process.start("vsiTestLackey", QStringList() |
1041 process.start("vsiTestLackey", QStringList() |
1045 << "-ipcInterestNotification" << layer->id().toString()); |
1042 << "-ipcInterestNotification" << layer->id().toString()); |
|
1043 #endif |
1046 QVERIFY(process.waitForStarted()); |
1044 QVERIFY(process.waitForStarted()); |
1047 |
1045 |
1048 // Lackey will receive interestChanged from server and set the attribute. |
1046 // Lackey will receive interestChanged from server and set the attribute. |
1049 QTRY_COMPARE(changeSpy.count(), 1); |
1047 QTRY_COMPARE(changeSpy.count(), 1); |
1050 changeSpy.clear(); |
1048 changeSpy.clear(); |
1120 class ReadThread : public QThread |
1119 class ReadThread : public QThread |
1121 { |
1120 { |
1122 Q_OBJECT |
1121 Q_OBJECT |
1123 |
1122 |
1124 public: |
1123 public: |
1125 ReadThread(QValueSpaceSubscriber *subscriber, bool sync); |
1124 ReadThread(QValueSpaceSubscriber *subscriber, bool sync, const QUuid& layerId); |
1126 |
1125 |
1127 protected: |
1126 protected: |
1128 void run(); |
1127 void run(); |
1129 |
1128 |
1130 private: |
1129 private: |
1131 QValueSpaceSubscriber *masterSubscriber; |
1130 QValueSpaceSubscriber *masterSubscriber; |
1132 int iterations; |
1131 int iterations; |
1133 bool synchronised; |
1132 bool synchronised; |
|
1133 const QUuid& layerId; |
1134 }; |
1134 }; |
1135 |
1135 |
1136 ReadThread::ReadThread(QValueSpaceSubscriber *subscriber, bool sync) |
1136 ReadThread::ReadThread(QValueSpaceSubscriber *subscriber, bool sync, const QUuid& layerId) |
1137 : masterSubscriber(subscriber), iterations(0), synchronised(sync) |
1137 : masterSubscriber(subscriber), iterations(0), synchronised(sync), layerId(layerId) |
1138 { |
1138 { |
1139 } |
1139 } |
1140 |
1140 |
1141 void ReadThread::run() |
1141 void ReadThread::run() |
1142 { |
1142 { |
1143 while (true) { |
1143 while (true) { |
1144 QValueSpaceSubscriber subscriber; |
1144 QValueSpaceSubscriber subscriber(layerId, masterSubscriber->path()); |
1145 subscriber.setPath(masterSubscriber); |
|
1146 |
1145 |
1147 if (synchronised) { |
1146 if (synchronised) { |
1148 QEventLoop loop; |
1147 QEventLoop loop; |
1149 connect(&subscriber, SIGNAL(contentsChanged()), &loop, SLOT(quit())); |
1148 connect(&subscriber, SIGNAL(contentsChanged()), &loop, SLOT(quit())); |
1150 QTimer::singleShot(1000, &loop, SLOT(quit())); |
1149 QTimer::singleShot(1000, &loop, SLOT(quit())); |
1161 |
1160 |
1162 void tst_QValueSpaceSubscriber::threads_data() |
1161 void tst_QValueSpaceSubscriber::threads_data() |
1163 { |
1162 { |
1164 QTest::addColumn<unsigned int>("threads"); |
1163 QTest::addColumn<unsigned int>("threads"); |
1165 QTest::addColumn<bool>("synchronised"); |
1164 QTest::addColumn<bool>("synchronised"); |
1166 |
1165 QTest::addColumn<QUuid>("layerId"); |
1167 QTest::newRow("1 thread") << uint(1) << true; |
1166 |
1168 QTest::newRow("2 threads") << uint(2) << true; |
1167 QList<QAbstractValueSpaceLayer *> layers = QValueSpaceManager::instance()->getLayers(); |
|
1168 |
|
1169 int foundLayers = 0; |
|
1170 for (int i = 0; i < layers.count(); ++i) { |
|
1171 QAbstractValueSpaceLayer *layer = layers.at(i); |
|
1172 |
|
1173 //GConfLayer can't provide thread-safety because it eventually depends on |
|
1174 //DBus which isn't fully thread-safe |
|
1175 if (layer->id() == QVALUESPACE_GCONF_LAYER) { |
|
1176 continue; |
|
1177 } |
|
1178 |
|
1179 const QUuid id = layer->id(); |
|
1180 |
|
1181 QTest::newRow("1 thread") << uint(1) << true << id; |
|
1182 QTest::newRow("2 threads") << uint(2) << true << id; |
1169 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) |
1183 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) |
1170 QTest::newRow("10 threads") << uint(10) << true; |
1184 QTest::newRow("10 threads") << uint(10) << true << id; |
1171 #else |
1185 #else |
1172 QTest::newRow("100 threads") << uint(100) << true; |
1186 QTest::newRow("100 threads") << uint(100) << true << id; |
1173 #endif |
1187 #endif |
1174 QTest::newRow("1 thread, unsynchronised") << uint(1) << false; |
1188 QTest::newRow("1 thread, unsynchronised") << uint(1) << false << id; |
1175 QTest::newRow("2 threads, unsynchronised") << uint(2) << false; |
1189 QTest::newRow("2 threads, unsynchronised") << uint(2) << false << id; |
1176 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) |
1190 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) |
1177 QTest::newRow("10 threads") << uint(10) << false; |
1191 QTest::newRow("10 threads") << uint(10) << false << id; |
1178 #else |
1192 #else |
1179 QTest::newRow("100 threads, unsynchronised") << uint(100) << false; |
1193 QTest::newRow("100 threads, unsynchronised") << uint(100) << false << id; |
1180 #endif |
1194 #endif |
|
1195 foundLayers++; |
|
1196 } |
|
1197 |
|
1198 if (foundLayers == 0) |
|
1199 QSKIP("No layers providing thread-safety found", SkipAll); |
1181 } |
1200 } |
1182 |
1201 |
1183 void tst_QValueSpaceSubscriber::threads() |
1202 void tst_QValueSpaceSubscriber::threads() |
1184 { |
1203 { |
1185 QFETCH(unsigned int, threads); |
1204 QFETCH(unsigned int, threads); |
1186 QFETCH(bool, synchronised); |
1205 QFETCH(bool, synchronised); |
|
1206 QFETCH(QUuid, layerId); |
1187 |
1207 |
1188 QEventLoop writeLoop; |
1208 QEventLoop writeLoop; |
1189 WriteThread *writeThread = new WriteThread; |
1209 WriteThread *writeThread = new WriteThread(layerId); |
1190 connect(writeThread, SIGNAL(finished()), &writeLoop, SLOT(quit())); |
1210 connect(writeThread, SIGNAL(finished()), &writeLoop, SLOT(quit())); |
1191 writeThread->start(); |
1211 writeThread->start(); |
1192 |
1212 |
1193 QValueSpaceSubscriber masterSubscriber("/threads/value"); |
1213 QValueSpaceSubscriber masterSubscriber(layerId, "/threads/value"); |
1194 |
1214 |
1195 QVector<ReadThread *> readThreads(threads); |
1215 QVector<ReadThread *> readThreads(threads); |
1196 |
1216 |
1197 for (unsigned int i = 0; i < threads; ++i) { |
1217 for (unsigned int i = 0; i < threads; ++i) { |
1198 readThreads[i] = new ReadThread(&masterSubscriber, synchronised); |
1218 readThreads[i] = new ReadThread(&masterSubscriber, synchronised, layerId); |
1199 readThreads[i]->start(); |
1219 readThreads[i]->start(); |
1200 } |
1220 } |
1201 |
1221 |
1202 for (unsigned int i = 0; i < threads; ++i) { |
1222 for (unsigned int i = 0; i < threads; ++i) { |
1203 QEventLoop loop; |
1223 QEventLoop loop; |