blob: 88b291022ca5523c9b36ceab6acb763fe82c188e [file] [log] [blame]
// Copyright 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "feedback/feedback_service.h"
#include <utime.h>
#include <memory>
#include <string>
#include <vector>
#include <base/at_exit.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/guid.h>
#include <base/strings/stringprintf.h>
#include <base/task/single_thread_task_executor.h>
#include <base/threading/thread.h>
#include <chromeos/dbus/service_constants.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "components/feedback/feedback_common.h"
#include "components/feedback/feedback_report.h"
#include "components/feedback/feedback_uploader.h"
#include "components/feedback/proto/extension.pb.h"
namespace feedback {
namespace {
static constexpr char kThreadName[] = "FeedbackWorkerThread";
static constexpr char kFeedbackReportPath[] = "Feedback Reports";
static constexpr int kTestProductId = 84;
} // namespace
class MockFeedbackUploader : public feedback::FeedbackUploader {
public:
MockFeedbackUploader(const base::FilePath& path,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: FeedbackUploader(path, task_runner) {}
MOCK_METHOD(void, DispatchReport, (const std::string&), (override));
};
class MockFeedbackUploaderQueue : public MockFeedbackUploader {
public:
MockFeedbackUploaderQueue(
const base::FilePath& path,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: MockFeedbackUploader(path, task_runner) {}
MOCK_METHOD(void, QueueReport, (const std::string&), (override));
};
class FailedFeedbackUploader : public MockFeedbackUploader {
public:
FailedFeedbackUploader(
const base::FilePath& path,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: MockFeedbackUploader(path, task_runner) {}
void DispatchReport(const std::string& data) {
MockFeedbackUploader::DispatchReport(data);
RetryReport(data);
}
feedback::FeedbackReport* GetFirstReport() {
scoped_refptr<feedback::FeedbackReport> report = reports_queue_.top();
return report.get();
}
};
class FeedbackServiceTest : public testing::Test {
public:
FeedbackServiceTest() : task_executor_(base::MessagePumpType::IO) {}
static void CallbackFeedbackResult(bool expected_result,
bool result,
const std::string& err) {
EXPECT_EQ(result, expected_result);
}
userfeedback::ExtensionSubmit GetBaseReport() {
userfeedback::ExtensionSubmit report;
report.mutable_common_data();
report.mutable_web_data();
report.set_type_id(0);
report.set_product_id(kTestProductId);
return report;
}
void WaitOnThread() { worker_thread_->FlushForTesting(); }
protected:
virtual void SetUp() {
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
CreateDirectory(temp_dir_.GetPath().Append(kFeedbackReportPath));
worker_thread_ = std::make_unique<base::Thread>(kThreadName);
worker_thread_->Start();
worker_task_runner_ = worker_thread_->task_runner();
}
virtual void TearDown() {
WaitOnThread();
worker_thread_->Stop();
}
base::ScopedTempDir temp_dir_;
base::SingleThreadTaskExecutor task_executor_;
std::unique_ptr<base::Thread> worker_thread_;
scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_;
};
TEST_F(FeedbackServiceTest, SendFeedback) {
MockFeedbackUploaderQueue uploader(temp_dir_.GetPath(), worker_task_runner_);
std::string data;
userfeedback::ExtensionSubmit report = GetBaseReport();
report.SerializeToString(&data);
EXPECT_CALL(uploader, QueueReport(data)).Times(1);
scoped_refptr<FeedbackService> svc = new FeedbackService(&uploader);
svc->SendFeedback(
report, base::Bind(&FeedbackServiceTest::CallbackFeedbackResult, true));
}
TEST_F(FeedbackServiceTest, DispatchTest) {
MockFeedbackUploader uploader(temp_dir_.GetPath(), worker_task_runner_);
std::string data;
userfeedback::ExtensionSubmit report = GetBaseReport();
report.SerializeToString(&data);
EXPECT_CALL(uploader, DispatchReport(data)).Times(1);
scoped_refptr<FeedbackService> svc = new FeedbackService(&uploader);
svc->SendFeedback(
report, base::Bind(&FeedbackServiceTest::CallbackFeedbackResult, true));
}
TEST_F(FeedbackServiceTest, UploadFailure) {
FailedFeedbackUploader uploader(temp_dir_.GetPath(), worker_task_runner_);
std::string data;
userfeedback::ExtensionSubmit report = GetBaseReport();
report.SerializeToString(&data);
EXPECT_CALL(uploader, DispatchReport(data)).Times(1);
scoped_refptr<FeedbackService> svc = new FeedbackService(&uploader);
svc->SendFeedback(
report, base::Bind(&FeedbackServiceTest::CallbackFeedbackResult, true));
WaitOnThread();
// Verify that this got put back on the queue.
EXPECT_TRUE(uploader.GetFirstReport() != nullptr);
EXPECT_EQ(uploader.GetFirstReport()->data(), data);
}
} // namespace feedback