From 585b6a6a5037f9ef630a244ede18ac7854955fc6 Mon Sep 17 00:00:00 2001
From: fearlessTobi <thm.frey@gmail.com>
Date: Fri, 26 Oct 2018 16:21:45 +0200
Subject: [PATCH] compatdb: Use a seperate endpoint for testcase submission

---
 src/common/telemetry.h             |  4 ++++
 src/core/telemetry_session.cpp     |  9 +++++++++
 src/core/telemetry_session.h       |  6 ++++++
 src/web_service/telemetry_json.cpp | 21 ++++++++++++++++-----
 src/web_service/telemetry_json.h   |  1 +
 src/yuzu/compatdb.cpp              | 27 +++++++++++++++++++++++++--
 src/yuzu/compatdb.h                |  4 ++++
 7 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/src/common/telemetry.h b/src/common/telemetry.h
index 8d6ab986b..854a73fae 100644
--- a/src/common/telemetry.h
+++ b/src/common/telemetry.h
@@ -153,6 +153,7 @@ struct VisitorInterface : NonCopyable {
 
     /// Completion method, called once all fields have been visited
     virtual void Complete() = 0;
+    virtual bool SubmitTestcase() = 0;
 };
 
 /**
@@ -178,6 +179,9 @@ struct NullVisitor : public VisitorInterface {
     void Visit(const Field<std::chrono::microseconds>& /*field*/) override {}
 
     void Complete() override {}
+    bool SubmitTestcase() override {
+        return false;
+    }
 };
 
 /// Appends build-specific information to the given FieldCollection,
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index 0de13edd3..a3b08c740 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -184,4 +184,13 @@ TelemetrySession::~TelemetrySession() {
     backend = nullptr;
 }
 
+bool TelemetrySession::SubmitTestcase() {
+#ifdef ENABLE_WEB_SERVICE
+    field_collection.Accept(*backend);
+    return backend->SubmitTestcase();
+#else
+    return false;
+#endif
+}
+
 } // namespace Core
diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h
index 2a4845797..023612b79 100644
--- a/src/core/telemetry_session.h
+++ b/src/core/telemetry_session.h
@@ -31,6 +31,12 @@ public:
         field_collection.AddField(type, name, std::move(value));
     }
 
+    /**
+     * Submits a Testcase.
+     * @returns A bool indicating whether the submission succeeded
+     */
+    bool SubmitTestcase();
+
 private:
     Telemetry::FieldCollection field_collection; ///< Tracks all added fields for the session
     std::unique_ptr<Telemetry::VisitorInterface> backend; ///< Backend interface that logs fields
diff --git a/src/web_service/telemetry_json.cpp b/src/web_service/telemetry_json.cpp
index 0a8f2bd9e..9156ce802 100644
--- a/src/web_service/telemetry_json.cpp
+++ b/src/web_service/telemetry_json.cpp
@@ -102,16 +102,27 @@ void TelemetryJson::Complete() {
     impl->SerializeSection(Telemetry::FieldType::App, "App");
     impl->SerializeSection(Telemetry::FieldType::Session, "Session");
     impl->SerializeSection(Telemetry::FieldType::Performance, "Performance");
-    impl->SerializeSection(Telemetry::FieldType::UserFeedback, "UserFeedback");
     impl->SerializeSection(Telemetry::FieldType::UserConfig, "UserConfig");
     impl->SerializeSection(Telemetry::FieldType::UserSystem, "UserSystem");
 
     auto content = impl->TopSection().dump();
     // Send the telemetry async but don't handle the errors since they were written to the log
-    Common::DetachedTasks::AddTask(
-        [host{impl->host}, username{impl->username}, token{impl->token}, content]() {
-            Client{host, username, token}.PostJson("/telemetry", content, true);
-        });
+    Common::DetachedTasks::AddTask([host{impl->host}, content]() {
+        Client{host, "", ""}.PostJson("/telemetry", content, true);
+    });
+}
+
+bool TelemetryJson::SubmitTestcase() {
+    impl->SerializeSection(Telemetry::FieldType::App, "App");
+    impl->SerializeSection(Telemetry::FieldType::Session, "Session");
+    impl->SerializeSection(Telemetry::FieldType::UserFeedback, "UserFeedback");
+    impl->SerializeSection(Telemetry::FieldType::UserSystem, "UserSystem");
+
+    auto content = impl->TopSection().dump();
+    Client client(impl->host, impl->username, impl->token);
+    auto value = client.PostJson("/gamedb/testcase", content, false);
+
+    return value.result_code == Common::WebResult::Code::Success;
 }
 
 } // namespace WebService
diff --git a/src/web_service/telemetry_json.h b/src/web_service/telemetry_json.h
index 93371414a..dfd202829 100644
--- a/src/web_service/telemetry_json.h
+++ b/src/web_service/telemetry_json.h
@@ -35,6 +35,7 @@ public:
     void Visit(const Telemetry::Field<std::chrono::microseconds>& field) override;
 
     void Complete() override;
+    bool SubmitTestcase() override;
 
 private:
     struct Impl;
diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp
index 91e754274..5f0896f84 100644
--- a/src/yuzu/compatdb.cpp
+++ b/src/yuzu/compatdb.cpp
@@ -5,6 +5,7 @@
 #include <QButtonGroup>
 #include <QMessageBox>
 #include <QPushButton>
+#include <QtConcurrent/qtconcurrentrun.h>
 #include "common/logging/log.h"
 #include "common/telemetry.h"
 #include "core/core.h"
@@ -23,6 +24,8 @@ CompatDB::CompatDB(QWidget* parent)
     connect(ui->radioButton_IntroMenu, &QRadioButton::clicked, this, &CompatDB::EnableNext);
     connect(ui->radioButton_WontBoot, &QRadioButton::clicked, this, &CompatDB::EnableNext);
     connect(button(NextButton), &QPushButton::clicked, this, &CompatDB::Submit);
+    connect(&testcase_watcher, &QFutureWatcher<bool>::finished, this,
+            &CompatDB::OnTestcaseSubmitted);
 }
 
 CompatDB::~CompatDB() = default;
@@ -48,18 +51,38 @@ void CompatDB::Submit() {
         }
         break;
     case CompatDBPage::Final:
+        back();
         LOG_DEBUG(Frontend, "Compatibility Rating: {}", compatibility->checkedId());
         Core::Telemetry().AddField(Telemetry::FieldType::UserFeedback, "Compatibility",
                                    compatibility->checkedId());
-        // older versions of QT don't support the "NoCancelButtonOnLastPage" option, this is a
-        // workaround
+
+        button(NextButton)->setEnabled(false);
+        button(NextButton)->setText(tr("Submitting"));
         button(QWizard::CancelButton)->setVisible(false);
+
+        testcase_watcher.setFuture(QtConcurrent::run(
+            [this]() { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); }));
         break;
     default:
         LOG_ERROR(Frontend, "Unexpected page: {}", currentId());
     }
 }
 
+void CompatDB::OnTestcaseSubmitted() {
+    if (!testcase_watcher.result()) {
+        QMessageBox::critical(this, tr("Communication error"),
+                              tr("An error occured while sending the Testcase"));
+        button(NextButton)->setEnabled(true);
+        button(NextButton)->setText(tr("Next"));
+        button(QWizard::CancelButton)->setVisible(true);
+    } else {
+        next();
+        // older versions of QT don't support the "NoCancelButtonOnLastPage" option, this is a
+        // workaround
+        button(QWizard::CancelButton)->setVisible(false);
+    }
+}
+
 void CompatDB::EnableNext() {
     button(NextButton)->setEnabled(true);
 }
diff --git a/src/yuzu/compatdb.h b/src/yuzu/compatdb.h
index ca0dd11d6..5381f67f7 100644
--- a/src/yuzu/compatdb.h
+++ b/src/yuzu/compatdb.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <memory>
+#include <QFutureWatcher>
 #include <QWizard>
 
 namespace Ui {
@@ -19,8 +20,11 @@ public:
     ~CompatDB();
 
 private:
+    QFutureWatcher<bool> testcase_watcher;
+
     std::unique_ptr<Ui::CompatDB> ui;
 
     void Submit();
+    void OnTestcaseSubmitted();
     void EnableNext();
 };