1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project
3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License.
6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at
7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software
11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and
14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License.
15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
163d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
173d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include "shill/connectivity_trial.h"
183d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1922f1fbc11b69ee41af8370ec38f1b90577db6c3cBen Chan#include <memory>
203d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include <string>
213d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
223d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include <base/bind.h>
233d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include <gmock/gmock.h>
243d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include <gtest/gtest.h>
253d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
263d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include "shill/mock_connection.h"
273d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include "shill/mock_control.h"
283d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include "shill/mock_device_info.h"
293d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include "shill/mock_event_dispatcher.h"
303d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein#include "shill/mock_http_request.h"
318d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/mock_time.h"
323d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
333d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing base::Bind;
343d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing base::Callback;
353d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing base::Unretained;
363d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing std::string;
3722f1fbc11b69ee41af8370ec38f1b90577db6c3cBen Chanusing std::unique_ptr;
383d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing std::vector;
393d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::_;
403d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::AtLeast;
413d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::DoAll;
423d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::InSequence;
433d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::Mock;
443d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::NiceMock;
453d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::Return;
463d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::ReturnRef;
473d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::SetArgumentPointee;
483d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::StrictMock;
493d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinusing testing::Test;
503d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
513d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinnamespace shill {
523d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
533d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinnamespace {
543d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinconst char kBadURL[] = "badurl";
553d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinconst char kInterfaceName[] = "int0";
563d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinconst char kURL[] = "http://www.chromium.org";
573d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinconst char kDNSServer0[] = "8.8.8.8";
583d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinconst char kDNSServer1[] = "8.8.4.4";
593b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewartconst char* kDNSServers[] = { kDNSServer0, kDNSServer1 };
603d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}  // namespace
613d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
623d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinMATCHER_P(IsResult, result, "") {
633d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  return (result.phase == arg.phase &&
643d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein          result.status == arg.status);
653d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
663d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
673d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinclass ConnectivityTrialTest : public Test {
683d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein public:
693d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ConnectivityTrialTest()
70cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan      : device_info_(
71cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan            new NiceMock<MockDeviceInfo>(&control_, nullptr, nullptr, nullptr)),
723d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        connection_(new StrictMock<MockConnection>(device_info_.get())),
733d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        connectivity_trial_(new ConnectivityTrial(
74cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan            connection_.get(), &dispatcher_, kTrialTimeout,
753d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            callback_target_.result_callback())),
763d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        interface_name_(kInterfaceName),
773d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        dns_servers_(kDNSServers, kDNSServers + 2),
78cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan        http_request_(nullptr) {
793d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    current_time_.tv_sec = current_time_.tv_usec = 0;
803d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
813d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
823d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  virtual void SetUp() {
833d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(*connection_.get(), IsIPv6())
843d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                .WillRepeatedly(Return(false));
853d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(*connection_.get(), interface_name())
863d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        .WillRepeatedly(ReturnRef(interface_name_));
873d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(time_, GetTimeMonotonic(_))
883d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        .WillRepeatedly(Invoke(this, &ConnectivityTrialTest::GetTimeMonotonic));
893d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(*connection_.get(), dns_servers())
903d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        .WillRepeatedly(ReturnRef(dns_servers_));
913d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_FALSE(connectivity_trial_->request_.get());
923d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
933d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
943d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  virtual void TearDown() {
953d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    Mock::VerifyAndClearExpectations(&http_request_);
963d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    if (connectivity_trial_->request_.get()) {
973d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      EXPECT_CALL(*http_request(), Stop());
983d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
993d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      // Delete the ConnectivityTrial while expectations still exist.
1003d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      connectivity_trial_.reset();
1013d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    }
1023d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1033d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1043d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein protected:
1053d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  static const int kNumAttempts;
1063d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  static const int kTrialTimeout;
1073d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1083d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  class CallbackTarget {
1093d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein   public:
1103d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    CallbackTarget()
1113d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        : result_callback_(Bind(&CallbackTarget::ResultCallback,
1123d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                Unretained(this))) {
1133d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    }
1143d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1153d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    MOCK_METHOD1(ResultCallback, void(ConnectivityTrial::Result result));
1163b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart    Callback<void(ConnectivityTrial::Result)>& result_callback() {
1173d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      return result_callback_;
1183d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    }
1193d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1203d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein   private:
1213d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    Callback<void(ConnectivityTrial::Result)> result_callback_;
1223d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  };
1233d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1243d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  void AssignHTTPRequest() {
1253d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    http_request_ = new StrictMock<MockHTTPRequest>(connection_);
1263d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    connectivity_trial_->request_.reset(http_request_);  // Passes ownership.
1273d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1283d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1293b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  bool StartTrialWithDelay(const string& url_string, int delay) {
1303d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    bool ret = connectivity_trial_->Start(url_string, delay);
1313d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    if (ret) {
1323d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      AssignHTTPRequest();
1333d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    }
1343d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    return ret;
1353d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1363d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1373b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  bool StartTrial(const string& url_string) {
1383d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    return StartTrialWithDelay(url_string, 0);
1393d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1403d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1413d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  void StartTrialTask() {
1423d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    AssignHTTPRequest();
1433d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(*http_request(), Start(_, _, _))
1443d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        .WillOnce(Return(HTTPRequest::kResultInProgress));
1453d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(dispatcher(), PostDelayedTask(_, kTrialTimeout * 1000));
1463d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    connectivity_trial()->StartTrialTask();
1473d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1483d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1493b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  void ExpectTrialReturn(const ConnectivityTrial::Result& result) {
1503d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(callback_target(), ResultCallback(IsResult(result)));
1513d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1523d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    // Expect the PortalDetector to stop the current request.
1533d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(*http_request(), Stop());
1543d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1553d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1563d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  void TimeoutTrial() {
1573d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    connectivity_trial_->TimeoutTrialTask();
1583d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1593d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1603b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  MockHTTPRequest* http_request() { return http_request_; }
1613b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  ConnectivityTrial* connectivity_trial() { return connectivity_trial_.get(); }
1623b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  MockEventDispatcher& dispatcher() { return dispatcher_; }
1633b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  CallbackTarget& callback_target() { return callback_target_; }
1643b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  ByteString& response_data() { return response_data_; }
1653d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1663d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  void ExpectReset() {
1673d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_TRUE(callback_target_.result_callback().
1683d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                Equals(connectivity_trial_->trial_callback_));
1693d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_FALSE(connectivity_trial_->request_.get());
1703d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1713d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1723b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  void ExpectTrialRetry(const ConnectivityTrial::Result& result, int delay) {
1733d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(callback_target(), ResultCallback(IsResult(result)));
1743d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1753d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    // Expect the ConnectivityTrial to stop the current request.
1763d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(*http_request(), Stop());
1773d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1783d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    // Expect the ConnectivityTrial to schedule the next attempt.
1793d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(dispatcher(), PostDelayedTask(_, delay));
1803d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1813d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1823d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  void AdvanceTime(int milliseconds) {
1833d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    struct timeval tv = { milliseconds / 1000, (milliseconds % 1000) * 1000 };
1843d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    timeradd(&current_time_, &tv, &current_time_);
1853d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1863d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1873d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  void StartTrial() {
1883d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
1893d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_TRUE(StartTrial(kURL));
1903d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1913d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    // Expect that the request will be started -- return failure.
1923d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(*http_request(), Start(_, _, _))
1933d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        .WillOnce(Return(HTTPRequest::kResultInProgress));
1943d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(dispatcher(), PostDelayedTask(
1953d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        _, kTrialTimeout * 1000));
1963d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
1973d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    connectivity_trial()->StartTrialTask();
1983d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
1993d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2003b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  void AppendReadData(const string& read_data) {
2013d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    response_data_.Append(ByteString(read_data, false));
2023d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    connectivity_trial_->RequestReadCallback(response_data_);
2033d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
2043d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2053d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein private:
2063b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  int GetTimeMonotonic(struct timeval* tv) {
2073d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    *tv = current_time_;
2083d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    return 0;
2093d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
2103d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2113d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  StrictMock<MockEventDispatcher> dispatcher_;
2123d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  MockControl control_;
21322f1fbc11b69ee41af8370ec38f1b90577db6c3cBen Chan  unique_ptr<MockDeviceInfo> device_info_;
2143d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  scoped_refptr<MockConnection> connection_;
2153d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  CallbackTarget callback_target_;
21622f1fbc11b69ee41af8370ec38f1b90577db6c3cBen Chan  unique_ptr<ConnectivityTrial> connectivity_trial_;
2173d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  StrictMock<MockTime> time_;
2183d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  struct timeval current_time_;
2193d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  const string interface_name_;
2203d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  vector<string> dns_servers_;
2213d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ByteString response_data_;
2223b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  MockHTTPRequest* http_request_;
2233d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein};
2243d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2253d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein// static
2263d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinconst int ConnectivityTrialTest::kNumAttempts = 0;
2273d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinconst int ConnectivityTrialTest::kTrialTimeout = 4;
2283d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2293d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, Constructor) {
2303d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ExpectReset();
2313d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
2323d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2333d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, InvalidURL) {
2343d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_FALSE(connectivity_trial()->IsActive());
2353d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0)).Times(0);
2363d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_FALSE(StartTrial(kBadURL));
2373d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ExpectReset();
2383d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2393d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_FALSE(connectivity_trial()->Retry(0));
2403d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_FALSE(connectivity_trial()->IsActive());
2413d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
2423d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2433d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, IsActive) {
2443d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Before the trial is started, should not be active.
2453d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_FALSE(connectivity_trial()->IsActive());
2463d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2473d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Once the trial is started, IsActive should return true.
2483d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
2493d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
2503d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  StartTrialTask();
2513d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(connectivity_trial()->IsActive());
2523d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2533d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Finish the trial, IsActive should return false.
2543d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Stop());
2553d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  connectivity_trial()->CompleteTrial(
2563d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::Result(ConnectivityTrial::kPhaseContent,
2573d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                ConnectivityTrial::kStatusFailure));
2583d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_FALSE(connectivity_trial()->IsActive());
2593d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
2603d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2613d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, StartAttemptFailed) {
2623d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
2633d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
2643d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2653d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Expect that the request will be started -- return failure.
2663d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Start(_, _, _))
2673d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      .WillOnce(Return(HTTPRequest::kResultConnectionFailure));
2683d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Expect a failure to be relayed to the caller.
2693d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(callback_target(),
2703d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein              ResultCallback(IsResult(
2713d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                  ConnectivityTrial::Result(
2723d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                      ConnectivityTrial::kPhaseConnection,
2733d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                      ConnectivityTrial::kStatusFailure))))
2743d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      .Times(1);
2753d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2763d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0)).Times(0);
2773d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Stop());
2783d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2793d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  connectivity_trial()->StartTrialTask();
2803d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
2813d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2823d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, StartRepeated) {
2833d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0)).Times(1);
2843d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
2853d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2863d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // A second call should cancel the existing trial and set up the new one.
2873d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Stop());
2883d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 10)).Times(1);
2893d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrialWithDelay(kURL, 10));
2903d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
2913d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2923d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, StartTrialAfterDelay) {
2933d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  const int kDelaySeconds = 123;
2943d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // The trial should be delayed by kDelaySeconds.
2953d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, kDelaySeconds));
2963d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrialWithDelay(kURL, kDelaySeconds));
2973d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
2983d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
2993d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, TrialRetry) {
3003d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
3013d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
3023d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3033d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Expect that the request will be started -- return failure.
3043d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Start(_, _, _))
3053d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      .WillOnce(Return(HTTPRequest::kResultConnectionFailure));
3063d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Stop());
3073d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  connectivity_trial()->StartTrialTask();
3083d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3093d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  const int kRetryDelay = 7;
3103d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Stop());
3113d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, kRetryDelay)).Times(1);
3123d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(connectivity_trial()->Retry(kRetryDelay));
3133d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
3143d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3153d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, TrialRetryFail) {
3163d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
3173d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
3183d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3193d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Stop());
3203d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  connectivity_trial()->Stop();
3213d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3223d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_FALSE(connectivity_trial()->Retry(0));
3233d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
3243d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3253d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein// Exactly like AttemptCount, except that the termination conditions are
3263d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein// different because we're triggering a different sort of error.
3273d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, ReadBadHeadersRetry) {
3283d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  int num_failures = 3;
3293d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  int sec_between_attempts = 3;
3303d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3313d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Expect ConnectivityTrial to immediately post a task for the each attempt.
3323d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
3333d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
3343d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3353d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Expect that the request will be started and return the in progress status.
3363d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), Start(_, _, _))
3373d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      .Times(num_failures).WillRepeatedly(
3383d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein          Return(HTTPRequest::kResultInProgress));
3393d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3403d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Each HTTP request that gets started will have a request timeout.
3413d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, kTrialTimeout * 1000))
3423d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      .Times(num_failures);
3433d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3443d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Expect failures for all attempts but the last.
3453d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(callback_target(),
3463d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein              ResultCallback(IsResult(
3473d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                  ConnectivityTrial::Result(
3483d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                      ConnectivityTrial::kPhaseContent,
3493d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                      ConnectivityTrial::kStatusFailure))))
3503d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      .Times(num_failures);
3513d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3523d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // Expect the ConnectivityTrial to stop the current request each time, plus
3533d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  // an extra time in ConnectivityTrial::Stop().
3543d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ByteString response_data("X", 1);
3553d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3563d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  for (int i = 0; i < num_failures; ++i) {
3573d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    connectivity_trial()->StartTrialTask();
3583d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    AdvanceTime(sec_between_attempts * 1000);
3593d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(*http_request(), Stop()).Times(2);
3603d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0)).Times(1);
3613d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    connectivity_trial()->RequestReadCallback(response_data);
3623d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    EXPECT_TRUE(connectivity_trial()->Retry(0));
3633d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  }
3643d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
3653d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3663d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3673d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, ReadBadHeader) {
3683d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
3693d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
3703d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3713d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  StartTrialTask();
3723d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3733d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ExpectTrialReturn(ConnectivityTrial::Result(
3743d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kPhaseContent,
3753d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kStatusFailure));
3763d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  AppendReadData("X");
3773d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
3783d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3793d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, RequestTimeout) {
3803d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
3813d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
3823d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3833d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  StartTrialTask();
3843d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3853d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ExpectTrialReturn(ConnectivityTrial::Result(
3863d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kPhaseUnknown,
3873d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kStatusTimeout));
3883d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3893d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), response_data())
3903d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      .WillOnce(ReturnRef(response_data()));
3913d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3923d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  TimeoutTrial();
3933d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
3943d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3953d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, ReadPartialHeaderTimeout) {
3963d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
3973d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
3983d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
3993d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  StartTrialTask();
4003d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4013d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4023d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  const string response_expected(ConnectivityTrial::kResponseExpected);
4033d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  const size_t partial_size = response_expected.length() / 2;
4043d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  AppendReadData(response_expected.substr(0, partial_size));
4053d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4063d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ExpectTrialReturn(ConnectivityTrial::Result(
4073d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kPhaseContent,
4083d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kStatusTimeout));
4093d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4103d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(*http_request(), response_data())
4113d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      .WillOnce(ReturnRef(response_data()));
4123d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4133d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  TimeoutTrial();
4143d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
4153d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4163d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, ReadCompleteHeader) {
4173d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  const string response_expected(ConnectivityTrial::kResponseExpected);
4183d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  const size_t partial_size = response_expected.length() / 2;
4193d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4203d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
4213d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
4223d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4233d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  StartTrialTask();
4243d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4253d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  AppendReadData(response_expected.substr(0, partial_size));
4263d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4273d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ExpectTrialReturn(ConnectivityTrial::Result(
4283d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kPhaseContent,
4293d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kStatusSuccess));
4303d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4313d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  AppendReadData(response_expected.substr(partial_size));
4323d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
4333d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4343d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_F(ConnectivityTrialTest, ReadMatchingHeader) {
4353d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  const string kResponse("HTTP/9.8 204");
4363d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4373d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_CALL(dispatcher(), PostDelayedTask(_, 0));
4383d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_TRUE(StartTrial(kURL));
4393d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4403d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  StartTrialTask();
4413d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4423d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ExpectTrialReturn(ConnectivityTrial::Result(
4433d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kPhaseContent,
4443d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::kStatusSuccess));
4453d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4463d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  AppendReadData(kResponse);
4473d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
4483d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4493d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinstruct ResultMapping {
4503d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ResultMapping() : http_result(HTTPRequest::kResultUnknown), trial_result() {}
4513d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ResultMapping(HTTPRequest::Result in_http_result,
4523b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart                const ConnectivityTrial::Result& in_trial_result)
4533d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      : http_result(in_http_result),
4543d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        trial_result(in_trial_result) {}
4553d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  HTTPRequest::Result http_result;
4563d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ConnectivityTrial::Result trial_result;
4573d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein};
4583d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4593d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silbersteinclass ConnectivityTrialResultMappingTest
4603d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    : public testing::TestWithParam<ResultMapping> {};
4613d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4623d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinTEST_P(ConnectivityTrialResultMappingTest, MapResult) {
4633d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  ConnectivityTrial::Result trial_result =
4643d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein      ConnectivityTrial::GetPortalResultForRequestResult(
4653d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein          GetParam().http_result);
4663d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_EQ(trial_result.phase, GetParam().trial_result.phase);
4673d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein  EXPECT_EQ(trial_result.status, GetParam().trial_result.status);
4683d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}
4693d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
4703d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca SilbersteinINSTANTIATE_TEST_CASE_P(
4713d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    TrialResultMappingTest,
4723d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    ConnectivityTrialResultMappingTest,
4733d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein    ::testing::Values(
4743d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
4753d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultUnknown,
4763d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseUnknown,
4773d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusFailure)),
4783d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
4793d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultInProgress,
4803d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseUnknown,
4813d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusFailure)),
4823d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
4833d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultDNSFailure,
4843d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseDNS,
4853d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusFailure)),
4863d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
4873d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultDNSTimeout,
4883d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseDNS,
4893d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusTimeout)),
4903d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
4913d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultConnectionFailure,
4923d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseConnection,
4933d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusFailure)),
4943d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
4953d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultConnectionTimeout,
4963d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseConnection,
4973d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusTimeout)),
4983d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
4993d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultRequestFailure,
5003d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseHTTP,
5013d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusFailure)),
5023d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
5033d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultRequestTimeout,
5043d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseHTTP,
5053d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusTimeout)),
5063d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
5073d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultResponseFailure,
5083d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseHTTP,
5093d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusFailure)),
5103d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
5113d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultResponseTimeout,
5123d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseHTTP,
5133d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusTimeout)),
5143d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein        ResultMapping(
5153d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            HTTPRequest::kResultSuccess,
5163d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein            ConnectivityTrial::Result(ConnectivityTrial::kPhaseContent,
5173d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein                                      ConnectivityTrial::kStatusFailure))));
5183d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein
5193d49ea435a59436f762c2cc5e750ff27ece0d3c5Rebecca Silberstein}  // namespace shill
520