1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/feedback/feedback_uploader.h"
6
7#include <set>
8
9#include "base/bind.h"
10#include "base/message_loop/message_loop.h"
11#include "base/prefs/testing_pref_service.h"
12#include "base/run_loop.h"
13#include "base/stl_util.h"
14#include "components/feedback/feedback_uploader_chrome.h"
15#include "components/feedback/feedback_uploader_factory.h"
16#include "components/user_prefs/user_prefs.h"
17#include "content/public/test/test_browser_context.h"
18#include "content/public/test/test_browser_thread.h"
19#include "testing/gmock/include/gmock/gmock.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace {
23
24const char kReportOne[] = "one";
25const char kReportTwo[] = "two";
26const char kReportThree[] = "three";
27const char kReportFour[] = "four";
28const char kReportFive[] = "five";
29
30const base::TimeDelta kRetryDelayForTest =
31    base::TimeDelta::FromMilliseconds(100);
32
33KeyedService* CreateFeedbackUploaderService(content::BrowserContext* context) {
34  return new feedback::FeedbackUploaderChrome(context);
35}
36
37}  // namespace
38
39namespace feedback {
40
41class FeedbackUploaderTest : public testing::Test {
42 protected:
43  FeedbackUploaderTest()
44     : ui_thread_(content::BrowserThread::UI, &message_loop_),
45       context_(new content::TestBrowserContext()),
46       prefs_(new TestingPrefServiceSimple()),
47       dispatched_reports_count_(0),
48       expected_reports_(0) {
49    user_prefs::UserPrefs::Set(context_.get(), prefs_.get());
50    FeedbackUploaderFactory::GetInstance()->SetTestingFactory(
51        context_.get(), &CreateFeedbackUploaderService);
52
53    uploader_ = FeedbackUploaderFactory::GetForBrowserContext(context_.get());
54    uploader_->setup_for_test(
55        base::Bind(&FeedbackUploaderTest::MockDispatchReport,
56                   base::Unretained(this)),
57        kRetryDelayForTest);
58  }
59
60  virtual ~FeedbackUploaderTest() {
61    FeedbackUploaderFactory::GetInstance()->SetTestingFactory(
62        context_.get(), NULL);
63  }
64
65  void QueueReport(const std::string& data) {
66    uploader_->QueueReport(data);
67  }
68
69  void ReportFailure(const std::string& data) {
70    uploader_->RetryReport(data);
71  }
72
73  void MockDispatchReport(const std::string& report_data) {
74    if (ContainsKey(dispatched_reports_, report_data)) {
75      dispatched_reports_[report_data]++;
76    } else {
77      dispatched_reports_[report_data] = 1;
78    }
79    dispatched_reports_count_++;
80
81    // Dispatch will always update the timer, whether successful or not,
82    // simulate the same behavior.
83    uploader_->UpdateUploadTimer();
84
85    if (ProcessingComplete()) {
86      if (run_loop_.get())
87        run_loop_->Quit();
88    }
89  }
90
91  bool ProcessingComplete() {
92    return (dispatched_reports_count_ >= expected_reports_);
93  }
94
95  void RunMessageLoop() {
96    if (ProcessingComplete())
97      return;
98    run_loop_.reset(new base::RunLoop());
99    run_loop_->Run();
100  }
101
102  base::MessageLoop message_loop_;
103  scoped_ptr<base::RunLoop> run_loop_;
104  content::TestBrowserThread ui_thread_;
105  scoped_ptr<content::TestBrowserContext> context_;
106  scoped_ptr<PrefService> prefs_;
107
108  FeedbackUploader* uploader_;
109
110  std::map<std::string, unsigned int> dispatched_reports_;
111  size_t dispatched_reports_count_;
112  size_t expected_reports_;
113};
114
115#if defined(OS_LINUX) || defined(OS_MACOSX)
116#define MAYBE_QueueMultiple QueueMultiple
117#else
118// crbug.com/330547
119#define MAYBE_QueueMultiple DISABLED_QueueMultiple
120#endif
121TEST_F(FeedbackUploaderTest, MAYBE_QueueMultiple) {
122  dispatched_reports_.clear();
123  QueueReport(kReportOne);
124  QueueReport(kReportTwo);
125  QueueReport(kReportThree);
126  QueueReport(kReportFour);
127
128  EXPECT_EQ(dispatched_reports_.size(), 4u);
129  EXPECT_EQ(dispatched_reports_[kReportOne], 1u);
130  EXPECT_EQ(dispatched_reports_[kReportTwo], 1u);
131  EXPECT_EQ(dispatched_reports_[kReportThree], 1u);
132  EXPECT_EQ(dispatched_reports_[kReportFour], 1u);
133}
134
135#if defined(OS_WIN) || defined(OS_ANDROID)
136// crbug.com/330547
137#define MAYBE_QueueMultipleWithFailures DISABLED_QueueMultipleWithFailures
138#else
139#define MAYBE_QueueMultipleWithFailures QueueMultipleWithFailures
140#endif
141TEST_F(FeedbackUploaderTest, MAYBE_QueueMultipleWithFailures) {
142  dispatched_reports_.clear();
143
144  QueueReport(kReportOne);
145  QueueReport(kReportTwo);
146  QueueReport(kReportThree);
147  QueueReport(kReportFour);
148
149  ReportFailure(kReportThree);
150  ReportFailure(kReportTwo);
151  QueueReport(kReportFive);
152
153  expected_reports_ = 7;
154  RunMessageLoop();
155
156  EXPECT_EQ(dispatched_reports_.size(), 5u);
157  EXPECT_EQ(dispatched_reports_[kReportOne], 1u);
158  EXPECT_EQ(dispatched_reports_[kReportTwo], 2u);
159  EXPECT_EQ(dispatched_reports_[kReportThree], 2u);
160  EXPECT_EQ(dispatched_reports_[kReportFour], 1u);
161  EXPECT_EQ(dispatched_reports_[kReportFive], 1u);
162}
163
164}  // namespace feedback
165