普通文本  |  191行  |  5.87 KB

// 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/domain_reliability/context.h"

#include <map>
#include <string>

#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "components/domain_reliability/beacon.h"
#include "components/domain_reliability/dispatcher.h"
#include "components/domain_reliability/scheduler.h"
#include "components/domain_reliability/test_util.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace domain_reliability {
namespace {

typedef std::vector<DomainReliabilityBeacon> BeaconVector;

DomainReliabilityBeacon MakeBeacon(MockableTime* time) {
  DomainReliabilityBeacon beacon;
  beacon.domain = "localhost";
  beacon.status = "ok";
  beacon.chrome_error = net::OK;
  beacon.server_ip = "127.0.0.1";
  beacon.protocol = "HTTP";
  beacon.http_response_code = 200;
  beacon.elapsed = base::TimeDelta::FromMilliseconds(250);
  beacon.start_time = time->NowTicks() - beacon.elapsed;
  return beacon;
}

class DomainReliabilityContextTest : public testing::Test {
 protected:
  DomainReliabilityContextTest()
      : dispatcher_(&time_),
        params_(MakeTestSchedulerParams()),
        uploader_(base::Bind(&DomainReliabilityContextTest::OnUploadRequest,
                             base::Unretained(this))),
        upload_reporter_string_("test-reporter"),
        context_(&time_,
                 params_,
                 upload_reporter_string_,
                 &dispatcher_,
                 &uploader_,
                 MakeTestConfig().Pass()),
        upload_pending_(false) {}

  TimeDelta min_delay() const { return params_.minimum_upload_delay; }
  TimeDelta max_delay() const { return params_.maximum_upload_delay; }
  TimeDelta retry_interval() const { return params_.upload_retry_interval; }
  TimeDelta zero_delta() const { return TimeDelta::FromMicroseconds(0); }

  bool upload_pending() { return upload_pending_; }

  const std::string& upload_report() {
    DCHECK(upload_pending_);
    return upload_report_;
  }

  const GURL& upload_url() {
    DCHECK(upload_pending_);
    return upload_url_;
  }

  void CallUploadCallback(bool success) {
    DCHECK(upload_pending_);
    upload_callback_.Run(success);
    upload_pending_ = false;
  }

  bool CheckNoBeacons() {
    BeaconVector beacons;
    context_.GetQueuedBeaconsForTesting(&beacons);
    return beacons.empty();
  }

  bool CheckCounts(size_t index,
                   unsigned expected_successful,
                   unsigned expected_failed) {
    unsigned successful, failed;
    context_.GetRequestCountsForTesting(index, &successful, &failed);
    return successful == expected_successful && failed == expected_failed;
  }

  MockTime time_;
  DomainReliabilityDispatcher dispatcher_;
  DomainReliabilityScheduler::Params params_;
  MockUploader uploader_;
  std::string upload_reporter_string_;
  DomainReliabilityContext context_;

 private:
  void OnUploadRequest(
      const std::string& report_json,
      const GURL& upload_url,
      const DomainReliabilityUploader::UploadCallback& callback) {
    DCHECK(!upload_pending_);
    upload_report_ = report_json;
    upload_url_ = upload_url;
    upload_callback_ = callback;
    upload_pending_ = true;
  }

  bool upload_pending_;
  std::string upload_report_;
  GURL upload_url_;
  DomainReliabilityUploader::UploadCallback upload_callback_;
};

TEST_F(DomainReliabilityContextTest, Create) {
  EXPECT_TRUE(CheckNoBeacons());
  EXPECT_TRUE(CheckCounts(0, 0, 0));
  EXPECT_TRUE(CheckCounts(1, 0, 0));
}

TEST_F(DomainReliabilityContextTest, NoResource) {
  GURL url("http://example/no_resource");
  DomainReliabilityBeacon beacon = MakeBeacon(&time_);
  context_.OnBeacon(url, beacon);

  EXPECT_TRUE(CheckNoBeacons());
  EXPECT_TRUE(CheckCounts(0, 0, 0));
  EXPECT_TRUE(CheckCounts(1, 0, 0));
}

TEST_F(DomainReliabilityContextTest, NeverReport) {
  GURL url("http://example/never_report");
  DomainReliabilityBeacon beacon = MakeBeacon(&time_);
  context_.OnBeacon(url, beacon);

  EXPECT_TRUE(CheckNoBeacons());
  EXPECT_TRUE(CheckCounts(0, 0, 0));
  EXPECT_TRUE(CheckCounts(1, 1, 0));
}

TEST_F(DomainReliabilityContextTest, AlwaysReport) {
  GURL url("http://example/always_report");
  DomainReliabilityBeacon beacon = MakeBeacon(&time_);
  context_.OnBeacon(url, beacon);

  BeaconVector beacons;
  context_.GetQueuedBeaconsForTesting(&beacons);
  EXPECT_EQ(1u, beacons.size());
  EXPECT_TRUE(CheckCounts(0, 1, 0));
  EXPECT_TRUE(CheckCounts(1, 0, 0));
}

TEST_F(DomainReliabilityContextTest, ReportUpload) {
  GURL url("http://example/always_report");
  DomainReliabilityBeacon beacon = MakeBeacon(&time_);
  context_.OnBeacon(url, beacon);

  BeaconVector beacons;
  context_.GetQueuedBeaconsForTesting(&beacons);
  EXPECT_EQ(1u, beacons.size());
  EXPECT_TRUE(CheckCounts(0, 1, 0));
  EXPECT_TRUE(CheckCounts(1, 0, 0));

  // N.B.: Assumes max_delay is 5 minutes.
  const char* kExpectedReport = "{"
      "\"config_version\":\"1\","
      "\"entries\":[{\"domain\":\"localhost\","
          "\"http_response_code\":200,\"protocol\":\"HTTP\","
          "\"request_age_ms\":300250,\"request_elapsed_ms\":250,"
          "\"resource\":\"always_report\",\"server_ip\":\"127.0.0.1\","
          "\"status\":\"ok\"}],"
      "\"reporter\":\"test-reporter\","
      "\"resources\":[{\"failed_requests\":0,\"name\":\"always_report\","
          "\"successful_requests\":1}]}";

  time_.Advance(max_delay());
  EXPECT_TRUE(upload_pending());
  EXPECT_EQ(kExpectedReport, upload_report());
  EXPECT_EQ(GURL("https://exampleuploader/upload"), upload_url());
  CallUploadCallback(true);

  EXPECT_TRUE(CheckNoBeacons());
  EXPECT_TRUE(CheckCounts(0, 0, 0));
  EXPECT_TRUE(CheckCounts(1, 0, 0));
}

}  // namespace
}  // namespace domain_reliability