// Copyright 2014 The Chromium 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 "components/feedback/feedback_uploader.h"
#include <set>
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/testing_pref_service.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "components/feedback/feedback_uploader_chrome.h"
#include "components/feedback/feedback_uploader_factory.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const char kReportOne[] = "one";
const char kReportTwo[] = "two";
const char kReportThree[] = "three";
const char kReportFour[] = "four";
const char kReportFive[] = "five";
const base::TimeDelta kRetryDelayForTest =
base::TimeDelta::FromMilliseconds(100);
KeyedService* CreateFeedbackUploaderService(content::BrowserContext* context) {
return new feedback::FeedbackUploaderChrome(context);
}
} // namespace
namespace feedback {
class FeedbackUploaderTest : public testing::Test {
protected:
FeedbackUploaderTest()
: ui_thread_(content::BrowserThread::UI, &message_loop_),
context_(new content::TestBrowserContext()),
prefs_(new TestingPrefServiceSimple()),
dispatched_reports_count_(0),
expected_reports_(0) {
user_prefs::UserPrefs::Set(context_.get(), prefs_.get());
FeedbackUploaderFactory::GetInstance()->SetTestingFactory(
context_.get(), &CreateFeedbackUploaderService);
uploader_ = FeedbackUploaderFactory::GetForBrowserContext(context_.get());
uploader_->setup_for_test(
base::Bind(&FeedbackUploaderTest::MockDispatchReport,
base::Unretained(this)),
kRetryDelayForTest);
}
virtual ~FeedbackUploaderTest() {
FeedbackUploaderFactory::GetInstance()->SetTestingFactory(
context_.get(), NULL);
}
void QueueReport(const std::string& data) {
uploader_->QueueReport(data);
}
void ReportFailure(const std::string& data) {
uploader_->RetryReport(data);
}
void MockDispatchReport(const std::string& report_data) {
if (ContainsKey(dispatched_reports_, report_data)) {
dispatched_reports_[report_data]++;
} else {
dispatched_reports_[report_data] = 1;
}
dispatched_reports_count_++;
// Dispatch will always update the timer, whether successful or not,
// simulate the same behavior.
uploader_->UpdateUploadTimer();
if (ProcessingComplete()) {
if (run_loop_.get())
run_loop_->Quit();
}
}
bool ProcessingComplete() {
return (dispatched_reports_count_ >= expected_reports_);
}
void RunMessageLoop() {
if (ProcessingComplete())
return;
run_loop_.reset(new base::RunLoop());
run_loop_->Run();
}
base::MessageLoop message_loop_;
scoped_ptr<base::RunLoop> run_loop_;
content::TestBrowserThread ui_thread_;
scoped_ptr<content::TestBrowserContext> context_;
scoped_ptr<PrefService> prefs_;
FeedbackUploader* uploader_;
std::map<std::string, unsigned int> dispatched_reports_;
size_t dispatched_reports_count_;
size_t expected_reports_;
};
#if defined(OS_LINUX) || defined(OS_MACOSX)
#define MAYBE_QueueMultiple QueueMultiple
#else
// crbug.com/330547
#define MAYBE_QueueMultiple DISABLED_QueueMultiple
#endif
TEST_F(FeedbackUploaderTest, MAYBE_QueueMultiple) {
dispatched_reports_.clear();
QueueReport(kReportOne);
QueueReport(kReportTwo);
QueueReport(kReportThree);
QueueReport(kReportFour);
EXPECT_EQ(dispatched_reports_.size(), 4u);
EXPECT_EQ(dispatched_reports_[kReportOne], 1u);
EXPECT_EQ(dispatched_reports_[kReportTwo], 1u);
EXPECT_EQ(dispatched_reports_[kReportThree], 1u);
EXPECT_EQ(dispatched_reports_[kReportFour], 1u);
}
#if defined(OS_WIN) || defined(OS_ANDROID)
// crbug.com/330547
#define MAYBE_QueueMultipleWithFailures DISABLED_QueueMultipleWithFailures
#else
#define MAYBE_QueueMultipleWithFailures QueueMultipleWithFailures
#endif
TEST_F(FeedbackUploaderTest, MAYBE_QueueMultipleWithFailures) {
dispatched_reports_.clear();
QueueReport(kReportOne);
QueueReport(kReportTwo);
QueueReport(kReportThree);
QueueReport(kReportFour);
ReportFailure(kReportThree);
ReportFailure(kReportTwo);
QueueReport(kReportFive);
expected_reports_ = 7;
RunMessageLoop();
EXPECT_EQ(dispatched_reports_.size(), 5u);
EXPECT_EQ(dispatched_reports_[kReportOne], 1u);
EXPECT_EQ(dispatched_reports_[kReportTwo], 2u);
EXPECT_EQ(dispatched_reports_[kReportThree], 2u);
EXPECT_EQ(dispatched_reports_[kReportFour], 1u);
EXPECT_EQ(dispatched_reports_[kReportFive], 1u);
}
} // namespace feedback