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/rappor/log_uploader.h" 6 7 #include "base/compiler_specific.h" 8 #include "base/message_loop/message_loop_proxy.h" 9 #include "net/url_request/test_url_fetcher_factory.h" 10 #include "net/url_request/url_request_test_util.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 namespace rappor { 14 15 namespace { 16 17 const char kTestServerURL[] = "http://a.com/"; 18 const char kTestMimeType[] = "text/plain"; 19 20 class TestLogUploader : public LogUploader { 21 public: 22 TestLogUploader(net::URLRequestContextGetter* request_context) : 23 LogUploader(GURL(kTestServerURL), kTestMimeType, request_context) { 24 } 25 26 base::TimeDelta last_interval_set() const { return last_interval_set_; }; 27 28 void StartUpload() { 29 last_interval_set_ = base::TimeDelta(); 30 StartScheduledUpload(); 31 } 32 33 static base::TimeDelta BackOff(base::TimeDelta t) { 34 return LogUploader::BackOffUploadInterval(t); 35 } 36 37 protected: 38 virtual bool IsUploadScheduled() const OVERRIDE { 39 return last_interval_set() != base::TimeDelta(); 40 } 41 42 // Schedules a future call to StartScheduledUpload if one isn't already 43 // pending. 44 virtual void ScheduleNextUpload(base::TimeDelta interval) OVERRIDE { 45 EXPECT_EQ(last_interval_set(), base::TimeDelta()); 46 last_interval_set_ = interval; 47 } 48 49 base::TimeDelta last_interval_set_; 50 51 DISALLOW_COPY_AND_ASSIGN(TestLogUploader); 52 }; 53 54 } // namespace 55 56 class LogUploaderTest : public testing::Test { 57 public: 58 LogUploaderTest() 59 : request_context_(new net::TestURLRequestContextGetter( 60 base::MessageLoopProxy::current())), 61 factory_(NULL) {} 62 63 protected: 64 // Required for base::MessageLoopProxy::current(). 65 base::MessageLoopForUI loop_; 66 scoped_refptr<net::TestURLRequestContextGetter> request_context_; 67 net::FakeURLFetcherFactory factory_; 68 69 DISALLOW_COPY_AND_ASSIGN(LogUploaderTest); 70 }; 71 72 TEST_F(LogUploaderTest, Success) { 73 TestLogUploader uploader(request_context_.get()); 74 75 factory_.SetFakeResponse(GURL(kTestServerURL), 76 std::string(), 77 net::HTTP_OK, 78 net::URLRequestStatus::SUCCESS); 79 80 uploader.QueueLog("log1"); 81 base::MessageLoop::current()->RunUntilIdle(); 82 // Log should be discarded instead of retransmitted. 83 EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta()); 84 } 85 86 TEST_F(LogUploaderTest, Rejection) { 87 TestLogUploader uploader(request_context_.get()); 88 89 factory_.SetFakeResponse(GURL(kTestServerURL), 90 std::string(), 91 net::HTTP_BAD_REQUEST, 92 net::URLRequestStatus::SUCCESS); 93 94 uploader.QueueLog("log1"); 95 base::MessageLoop::current()->RunUntilIdle(); 96 // Log should be discarded instead of retransmitted. 97 EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta()); 98 } 99 100 TEST_F(LogUploaderTest, Failure) { 101 TestLogUploader uploader(request_context_.get()); 102 103 factory_.SetFakeResponse(GURL(kTestServerURL), 104 std::string(), 105 net::HTTP_INTERNAL_SERVER_ERROR, 106 net::URLRequestStatus::SUCCESS); 107 108 uploader.QueueLog("log1"); 109 base::MessageLoop::current()->RunUntilIdle(); 110 // Log should be scheduled for retransmission. 111 base::TimeDelta error_interval = uploader.last_interval_set(); 112 EXPECT_GT(error_interval, base::TimeDelta()); 113 114 for (int i = 0; i < 10; i++) { 115 uploader.QueueLog("logX"); 116 } 117 118 // A second failure should lead to a longer interval, and the log should 119 // be discarded due to full queue. 120 uploader.StartUpload(); 121 base::MessageLoop::current()->RunUntilIdle(); 122 EXPECT_GT(uploader.last_interval_set(), error_interval); 123 124 factory_.SetFakeResponse(GURL(kTestServerURL), 125 std::string(), 126 net::HTTP_OK, 127 net::URLRequestStatus::SUCCESS); 128 129 // A success should revert to base interval while queue is not empty. 130 for (int i = 0; i < 9; i++) { 131 uploader.StartUpload(); 132 base::MessageLoop::current()->RunUntilIdle(); 133 EXPECT_LT(uploader.last_interval_set(), error_interval); 134 } 135 136 // Queue should be empty. 137 uploader.StartUpload(); 138 base::MessageLoop::current()->RunUntilIdle(); 139 EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta()); 140 } 141 142 TEST_F(LogUploaderTest, Backoff) { 143 base::TimeDelta current = base::TimeDelta(); 144 base::TimeDelta next = base::TimeDelta::FromSeconds(1); 145 // Backoff until the maximum is reached. 146 while (next > current) { 147 current = next; 148 next = TestLogUploader::BackOff(current); 149 } 150 // Maximum backoff should have been reached. 151 EXPECT_EQ(next, current); 152 } 153 154 } // namespace rappor 155