/* SPDX-FileCopyrightText: 2016 Volker Krause SPDX-License-Identifier: MIT */ #include "servercontroller.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KUserFeedback; using namespace KUserFeedback::Console; class SubmitTest : public QObject { Q_OBJECT private: ServerController m_server; bool waitForFinished(QNetworkReply *reply) { Q_ASSERT(reply); QSignalSpy spy(reply, &QNetworkReply::finished); Q_ASSERT(spy.isValid()); return spy.wait(); } private Q_SLOTS: void initTestCase() { Q_INIT_RESOURCE(schematemplates); QStandardPaths::setTestModeEnabled(true); QVERIFY(m_server.start()); } void init() { // clear past audit logs AuditLogUiController alc; alc.clear(); QVERIFY(alc.logEntryModel()); QCOMPARE(alc.logEntryModel()->rowCount(), 0); } void testProvider_data() { QTest::addColumn("path"); QTest::newRow("direct") << QString(); QTest::newRow("absolute redirect") << QStringLiteral("/absRedirect"); QTest::newRow("relative redirect") << QStringLiteral("/relRedirect"); } void testProvider() { QFETCH(QString, path); ServerInfo serverInfo; auto serverUrl = m_server.url(); serverInfo.setUrl(serverUrl); serverUrl.setPath(path); // delete previous leftovers RESTClient client; client.setServerInfo(serverInfo); client.setConnected(true); QVERIFY(client.isConnected()); Product p; p.setName(QStringLiteral("org.kde.UserFeedback.UnitTestProduct")); auto reply = RESTApi::deleteProduct(&client, p); waitForFinished(reply); // create test product for (const auto &tpl : SchemaEntryTemplates::availableTemplates()) p.addTemplate(tpl); QVERIFY(p.isValid()); reply = RESTApi::createProduct(&client, p); QVERIFY(waitForFinished(reply)); QCOMPARE(reply->error(), QNetworkReply::NoError); // submit data Provider provider; provider.setProductIdentifier(QStringLiteral("org.kde.UserFeedback.UnitTestProduct")); provider.setTelemetryMode(Provider::DetailedUsageStatistics); provider.setFeedbackServer(serverUrl); provider.addDataSource(new ScreenInfoSource); provider.addDataSource(new PlatformInfoSource); provider.submit(); QTest::qWait(100); // HACK submit is async // retrieve data reply = RESTApi::listSamples(&client, p); QVERIFY(waitForFinished(reply)); QVERIFY(reply->header(QNetworkRequest::ContentTypeHeader).toString().startsWith(QLatin1String("text/json"))); auto doc = QJsonDocument::fromJson(reply->readAll()); QVERIFY(doc.isArray()); auto a = doc.array(); QCOMPARE(a.size(), 1); auto obj = a.at(0).toObject(); QVERIFY(!obj.isEmpty()); QVERIFY(obj.contains(QLatin1String("id"))); QVERIFY(obj.contains(QLatin1String("timestamp"))); QVERIFY(obj.contains(QLatin1String("platform"))); auto sub = obj.value(QLatin1String("platform")).toObject(); QVERIFY(sub.contains(QLatin1String("os"))); QVERIFY(sub.contains(QLatin1String("version"))); QVERIFY(obj.contains(QLatin1String("screens"))); a = obj.value(QLatin1String("screens")).toArray(); QVERIFY(a.size() > 0); sub = a.at(0).toObject(); QVERIFY(sub.contains(QLatin1String("height"))); QVERIFY(sub.contains(QLatin1String("width"))); // check we wrote an audit log AuditLogUiController alc; QVERIFY(alc.logEntryModel()); QCOMPARE(alc.logEntryModel()->rowCount(), 1); } void testRedirectLoop() { auto serverUrl = m_server.url(); serverUrl.setPath(QLatin1String("/circleRedirect")); // this must pass without ending in an infinite loop Provider provider; provider.setProductIdentifier(QStringLiteral("org.kde.UserFeedback.UnitTestProduct")); provider.setTelemetryMode(Provider::DetailedUsageStatistics); provider.setFeedbackServer(serverUrl); provider.addDataSource(new ScreenInfoSource); provider.addDataSource(new PlatformInfoSource); provider.submit(); QTest::qWait(500); // HACK submit is async, and we have no way of knowning the redirect loop ended... } void testSurveyWithoutTelemetry() { ServerInfo serverInfo; auto serverUrl = m_server.url(); serverInfo.setUrl(serverUrl); // delete previous leftovers RESTClient client; client.setServerInfo(serverInfo); client.setConnected(true); QVERIFY(client.isConnected()); Product p; p.setName(QStringLiteral("org.kde.UserFeedback.UnitTestProduct")); auto reply = RESTApi::deleteProduct(&client, p); waitForFinished(reply); // create test product for (const auto &tpl : SchemaEntryTemplates::availableTemplates()) p.addTemplate(tpl); QVERIFY(p.isValid()); reply = RESTApi::createProduct(&client, p); QVERIFY(waitForFinished(reply)); QCOMPARE(reply->error(), QNetworkReply::NoError); // submit data Provider provider; provider.setProductIdentifier(QStringLiteral("org.kde.UserFeedback.UnitTestProduct")); provider.setTelemetryMode(Provider::NoTelemetry); provider.setSubmissionInterval(7); provider.setSurveyInterval(30); provider.setFeedbackServer(serverUrl); provider.addDataSource(new ScreenInfoSource); provider.addDataSource(new PlatformInfoSource); provider.submit(); QTest::qWait(100); // HACK submit is async // retrieve data reply = RESTApi::listSamples(&client, p); QVERIFY(waitForFinished(reply)); QVERIFY(reply->header(QNetworkRequest::ContentTypeHeader).toString().startsWith(QLatin1String("text/json"))); auto doc = QJsonDocument::fromJson(reply->readAll()); QVERIFY(doc.isArray()); auto a = doc.array(); QCOMPARE(a.size(), 0); // check we wrote an audit log AuditLogUiController alc; QVERIFY(alc.logEntryModel()); QCOMPARE(alc.logEntryModel()->rowCount(), 1); } }; QTEST_MAIN(SubmitTest) #include "submittest.moc"