Home | History | Annotate | Download | only in rappor
      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_);
     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_);
     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_);
    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