| // | 
 | // Copyright (C) 2012 The Android Open Source Project | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 | // | 
 |  | 
 | #include "shill/connectivity_trial.h" | 
 |  | 
 | #include <memory> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | #include <base/bind.h> | 
 | #include <gmock/gmock.h> | 
 | #include <gtest/gtest.h> | 
 |  | 
 | #include "shill/mock_connection.h" | 
 | #include "shill/mock_control.h" | 
 | #include "shill/mock_device_info.h" | 
 | #include "shill/mock_event_dispatcher.h" | 
 | #include "shill/mock_http_request.h" | 
 | #include "shill/net/mock_time.h" | 
 |  | 
 | using base::Bind; | 
 | using base::Callback; | 
 | using base::Unretained; | 
 | using std::string; | 
 | using std::unique_ptr; | 
 | using std::vector; | 
 | using testing::_; | 
 | using testing::Mock; | 
 | using testing::NiceMock; | 
 | using testing::Return; | 
 | using testing::ReturnRef; | 
 | using testing::StrictMock; | 
 | using testing::Test; | 
 |  | 
 | namespace shill { | 
 |  | 
 | namespace { | 
 | const char kBadURL[] = "badurl"; | 
 | const char kInterfaceName[] = "int0"; | 
 | const char kURL[] = "http://www.chromium.org"; | 
 | const char kDNSServer0[] = "8.8.8.8"; | 
 | const char kDNSServer1[] = "8.8.4.4"; | 
 | const char* const kDNSServers[] = {kDNSServer0, kDNSServer1}; | 
 | }  // namespace | 
 |  | 
 | MATCHER_P(IsResult, result, "") { | 
 |   return (result.phase == arg.phase && | 
 |           result.status == arg.status); | 
 | } | 
 |  | 
 | class ConnectivityTrialTest : public Test { | 
 |  public: | 
 |   ConnectivityTrialTest() | 
 |       : device_info_( | 
 |             new NiceMock<MockDeviceInfo>(&control_, nullptr, nullptr, nullptr)), | 
 |         connection_(new StrictMock<MockConnection>(device_info_.get())), | 
 |         connectivity_trial_(new ConnectivityTrial( | 
 |             connection_.get(), &dispatcher_, kTrialTimeout, | 
 |             callback_target_.result_callback())), | 
 |         interface_name_(kInterfaceName), | 
 |         dns_servers_(kDNSServers, kDNSServers + 2), | 
 |         http_request_(nullptr) { | 
 |     current_time_.tv_sec = current_time_.tv_usec = 0; | 
 |   } | 
 |  | 
 |   void SetUp() override { | 
 |     EXPECT_CALL(*connection_.get(), IsIPv6()) | 
 |                 .WillRepeatedly(Return(false)); | 
 |     EXPECT_CALL(*connection_.get(), interface_name()) | 
 |         .WillRepeatedly(ReturnRef(interface_name_)); | 
 |     EXPECT_CALL(time_, GetTimeMonotonic(_)) | 
 |         .WillRepeatedly(Invoke(this, &ConnectivityTrialTest::GetTimeMonotonic)); | 
 |     EXPECT_CALL(*connection_.get(), dns_servers()) | 
 |         .WillRepeatedly(ReturnRef(dns_servers_)); | 
 |     EXPECT_FALSE(connectivity_trial_->request_.get()); | 
 |   } | 
 |  | 
 |   void TearDown() override { | 
 |     Mock::VerifyAndClearExpectations(&http_request_); | 
 |     if (connectivity_trial_->request_.get()) { | 
 |       EXPECT_CALL(*http_request(), Stop()); | 
 |  | 
 |       // Delete the ConnectivityTrial while expectations still exist. | 
 |       connectivity_trial_.reset(); | 
 |     } | 
 |   } | 
 |  | 
 |  protected: | 
 |   static const int kNumAttempts; | 
 |   static const int kTrialTimeout; | 
 |  | 
 |   class CallbackTarget { | 
 |    public: | 
 |     CallbackTarget() | 
 |         : result_callback_(Bind(&CallbackTarget::ResultCallback, | 
 |                                 Unretained(this))) { | 
 |     } | 
 |  | 
 |     MOCK_METHOD1(ResultCallback, void(ConnectivityTrial::Result result)); | 
 |     Callback<void(ConnectivityTrial::Result)>& result_callback() { | 
 |       return result_callback_; | 
 |     } | 
 |  | 
 |    private: | 
 |     Callback<void(ConnectivityTrial::Result)> result_callback_; | 
 |   }; | 
 |  | 
 |   void AssignHttpRequest() { | 
 |     http_request_ = new StrictMock<MockHttpRequest>(connection_); | 
 |     connectivity_trial_->request_.reset(http_request_);  // Passes ownership. | 
 |   } | 
 |  | 
 |   bool StartTrialWithDelay(const string& url_string, int delay) { | 
 |     bool ret = connectivity_trial_->Start(url_string, delay); | 
 |     if (ret) { | 
 |       AssignHttpRequest(); | 
 |     } | 
 |     return ret; | 
 |   } | 
 |  | 
 |   bool StartTrial(const string& url_string) { | 
 |     return StartTrialWithDelay(url_string, 0); | 
 |   } | 
 |  | 
 |   void StartTrialTask() { | 
 |     AssignHttpRequest(); | 
 |     EXPECT_CALL(*http_request(), Start(_, _, _)) | 
 |         .WillOnce(Return(HttpRequest::kResultInProgress)); | 
 |     EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, kTrialTimeout * 1000)); | 
 |     connectivity_trial()->StartTrialTask(); | 
 |   } | 
 |  | 
 |   void ExpectTrialReturn(const ConnectivityTrial::Result& result) { | 
 |     EXPECT_CALL(callback_target(), ResultCallback(IsResult(result))); | 
 |  | 
 |     // Expect the PortalDetector to stop the current request. | 
 |     EXPECT_CALL(*http_request(), Stop()); | 
 |   } | 
 |  | 
 |   void TimeoutTrial() { | 
 |     connectivity_trial_->TimeoutTrialTask(); | 
 |   } | 
 |  | 
 |   MockHttpRequest* http_request() { return http_request_; } | 
 |   ConnectivityTrial* connectivity_trial() { return connectivity_trial_.get(); } | 
 |   MockEventDispatcher& dispatcher() { return dispatcher_; } | 
 |   CallbackTarget& callback_target() { return callback_target_; } | 
 |   ByteString& response_data() { return response_data_; } | 
 |  | 
 |   void ExpectReset() { | 
 |     EXPECT_TRUE(callback_target_.result_callback(). | 
 |                 Equals(connectivity_trial_->trial_callback_)); | 
 |     EXPECT_FALSE(connectivity_trial_->request_.get()); | 
 |   } | 
 |  | 
 |   void ExpectTrialRetry(const ConnectivityTrial::Result& result, int delay) { | 
 |     EXPECT_CALL(callback_target(), ResultCallback(IsResult(result))); | 
 |  | 
 |     // Expect the ConnectivityTrial to stop the current request. | 
 |     EXPECT_CALL(*http_request(), Stop()); | 
 |  | 
 |     // Expect the ConnectivityTrial to schedule the next attempt. | 
 |     EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, delay)); | 
 |   } | 
 |  | 
 |   void AdvanceTime(int milliseconds) { | 
 |     struct timeval tv = { milliseconds / 1000, (milliseconds % 1000) * 1000 }; | 
 |     timeradd(¤t_time_, &tv, ¤t_time_); | 
 |   } | 
 |  | 
 |   void StartTrial() { | 
 |     EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |     EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |     // Expect that the request will be started -- return failure. | 
 |     EXPECT_CALL(*http_request(), Start(_, _, _)) | 
 |         .WillOnce(Return(HttpRequest::kResultInProgress)); | 
 |     EXPECT_CALL(dispatcher(), PostDelayedTask( | 
 |         _, _, kTrialTimeout * 1000)); | 
 |  | 
 |     connectivity_trial()->StartTrialTask(); | 
 |   } | 
 |  | 
 |   void AppendReadData(const string& read_data) { | 
 |     response_data_.Append(ByteString(read_data, false)); | 
 |     connectivity_trial_->RequestReadCallback(response_data_); | 
 |   } | 
 |  | 
 |  private: | 
 |   int GetTimeMonotonic(struct timeval* tv) { | 
 |     *tv = current_time_; | 
 |     return 0; | 
 |   } | 
 |  | 
 |   StrictMock<MockEventDispatcher> dispatcher_; | 
 |   MockControl control_; | 
 |   unique_ptr<MockDeviceInfo> device_info_; | 
 |   scoped_refptr<MockConnection> connection_; | 
 |   CallbackTarget callback_target_; | 
 |   unique_ptr<ConnectivityTrial> connectivity_trial_; | 
 |   StrictMock<MockTime> time_; | 
 |   struct timeval current_time_; | 
 |   const string interface_name_; | 
 |   vector<string> dns_servers_; | 
 |   ByteString response_data_; | 
 |   MockHttpRequest* http_request_; | 
 | }; | 
 |  | 
 | // static | 
 | const int ConnectivityTrialTest::kNumAttempts = 0; | 
 | const int ConnectivityTrialTest::kTrialTimeout = 4; | 
 |  | 
 | TEST_F(ConnectivityTrialTest, Constructor) { | 
 |   ExpectReset(); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, InvalidURL) { | 
 |   EXPECT_FALSE(connectivity_trial()->IsActive()); | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)).Times(0); | 
 |   EXPECT_FALSE(StartTrial(kBadURL)); | 
 |   ExpectReset(); | 
 |  | 
 |   EXPECT_FALSE(connectivity_trial()->Retry(0)); | 
 |   EXPECT_FALSE(connectivity_trial()->IsActive()); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, IsActive) { | 
 |   // Before the trial is started, should not be active. | 
 |   EXPECT_FALSE(connectivity_trial()->IsActive()); | 
 |  | 
 |   // Once the trial is started, IsActive should return true. | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |   StartTrialTask(); | 
 |   EXPECT_TRUE(connectivity_trial()->IsActive()); | 
 |  | 
 |   // Finish the trial, IsActive should return false. | 
 |   EXPECT_CALL(*http_request(), Stop()); | 
 |   connectivity_trial()->CompleteTrial( | 
 |       ConnectivityTrial::Result(ConnectivityTrial::kPhaseContent, | 
 |                                 ConnectivityTrial::kStatusFailure)); | 
 |   EXPECT_FALSE(connectivity_trial()->IsActive()); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, StartAttemptFailed) { | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   // Expect that the request will be started -- return failure. | 
 |   EXPECT_CALL(*http_request(), Start(_, _, _)) | 
 |       .WillOnce(Return(HttpRequest::kResultConnectionFailure)); | 
 |   // Expect a failure to be relayed to the caller. | 
 |   EXPECT_CALL(callback_target(), | 
 |               ResultCallback(IsResult( | 
 |                   ConnectivityTrial::Result( | 
 |                       ConnectivityTrial::kPhaseConnection, | 
 |                       ConnectivityTrial::kStatusFailure)))) | 
 |       .Times(1); | 
 |  | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)).Times(0); | 
 |   EXPECT_CALL(*http_request(), Stop()); | 
 |  | 
 |   connectivity_trial()->StartTrialTask(); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, StartRepeated) { | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)).Times(1); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   // A second call should cancel the existing trial and set up the new one. | 
 |   EXPECT_CALL(*http_request(), Stop()); | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 10)).Times(1); | 
 |   EXPECT_TRUE(StartTrialWithDelay(kURL, 10)); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, StartTrialAfterDelay) { | 
 |   const int kDelaySeconds = 123; | 
 |   // The trial should be delayed by kDelaySeconds. | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, kDelaySeconds)); | 
 |   EXPECT_TRUE(StartTrialWithDelay(kURL, kDelaySeconds)); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, TrialRetry) { | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   // Expect that the request will be started -- return failure. | 
 |   EXPECT_CALL(*http_request(), Start(_, _, _)) | 
 |       .WillOnce(Return(HttpRequest::kResultConnectionFailure)); | 
 |   EXPECT_CALL(*http_request(), Stop()); | 
 |   connectivity_trial()->StartTrialTask(); | 
 |  | 
 |   const int kRetryDelay = 7; | 
 |   EXPECT_CALL(*http_request(), Stop()); | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, kRetryDelay)).Times(1); | 
 |   EXPECT_TRUE(connectivity_trial()->Retry(kRetryDelay)); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, TrialRetryFail) { | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   EXPECT_CALL(*http_request(), Stop()); | 
 |   connectivity_trial()->Stop(); | 
 |  | 
 |   EXPECT_FALSE(connectivity_trial()->Retry(0)); | 
 | } | 
 |  | 
 | // Exactly like AttemptCount, except that the termination conditions are | 
 | // different because we're triggering a different sort of error. | 
 | TEST_F(ConnectivityTrialTest, ReadBadHeadersRetry) { | 
 |   int num_failures = 3; | 
 |   int sec_between_attempts = 3; | 
 |  | 
 |   // Expect ConnectivityTrial to immediately post a task for the each attempt. | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   // Expect that the request will be started and return the in progress status. | 
 |   EXPECT_CALL(*http_request(), Start(_, _, _)) | 
 |       .Times(num_failures).WillRepeatedly( | 
 |           Return(HttpRequest::kResultInProgress)); | 
 |  | 
 |   // Each HTTP request that gets started will have a request timeout. | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, kTrialTimeout * 1000)) | 
 |       .Times(num_failures); | 
 |  | 
 |   // Expect failures for all attempts but the last. | 
 |   EXPECT_CALL(callback_target(), | 
 |               ResultCallback(IsResult( | 
 |                   ConnectivityTrial::Result( | 
 |                       ConnectivityTrial::kPhaseContent, | 
 |                       ConnectivityTrial::kStatusFailure)))) | 
 |       .Times(num_failures); | 
 |  | 
 |   // Expect the ConnectivityTrial to stop the current request each time, plus | 
 |   // an extra time in ConnectivityTrial::Stop(). | 
 |   ByteString response_data("X", 1); | 
 |  | 
 |   for (int i = 0; i < num_failures; ++i) { | 
 |     connectivity_trial()->StartTrialTask(); | 
 |     AdvanceTime(sec_between_attempts * 1000); | 
 |     EXPECT_CALL(*http_request(), Stop()).Times(2); | 
 |     EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)).Times(1); | 
 |     connectivity_trial()->RequestReadCallback(response_data); | 
 |     EXPECT_TRUE(connectivity_trial()->Retry(0)); | 
 |   } | 
 | } | 
 |  | 
 |  | 
 | TEST_F(ConnectivityTrialTest, ReadBadHeader) { | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   StartTrialTask(); | 
 |  | 
 |   ExpectTrialReturn(ConnectivityTrial::Result( | 
 |       ConnectivityTrial::kPhaseContent, | 
 |       ConnectivityTrial::kStatusFailure)); | 
 |   AppendReadData("X"); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, RequestTimeout) { | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   StartTrialTask(); | 
 |  | 
 |   ExpectTrialReturn(ConnectivityTrial::Result( | 
 |       ConnectivityTrial::kPhaseUnknown, | 
 |       ConnectivityTrial::kStatusTimeout)); | 
 |  | 
 |   EXPECT_CALL(*http_request(), response_data()) | 
 |       .WillOnce(ReturnRef(response_data())); | 
 |  | 
 |   TimeoutTrial(); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, ReadPartialHeaderTimeout) { | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   StartTrialTask(); | 
 |  | 
 |  | 
 |   const string response_expected(ConnectivityTrial::kResponseExpected); | 
 |   const size_t partial_size = response_expected.length() / 2; | 
 |   AppendReadData(response_expected.substr(0, partial_size)); | 
 |  | 
 |   ExpectTrialReturn(ConnectivityTrial::Result( | 
 |       ConnectivityTrial::kPhaseContent, | 
 |       ConnectivityTrial::kStatusTimeout)); | 
 |  | 
 |   EXPECT_CALL(*http_request(), response_data()) | 
 |       .WillOnce(ReturnRef(response_data())); | 
 |  | 
 |   TimeoutTrial(); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, ReadCompleteHeader) { | 
 |   const string response_expected(ConnectivityTrial::kResponseExpected); | 
 |   const size_t partial_size = response_expected.length() / 2; | 
 |  | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   StartTrialTask(); | 
 |  | 
 |   AppendReadData(response_expected.substr(0, partial_size)); | 
 |  | 
 |   ExpectTrialReturn(ConnectivityTrial::Result( | 
 |       ConnectivityTrial::kPhaseContent, | 
 |       ConnectivityTrial::kStatusSuccess)); | 
 |  | 
 |   AppendReadData(response_expected.substr(partial_size)); | 
 | } | 
 |  | 
 | TEST_F(ConnectivityTrialTest, ReadMatchingHeader) { | 
 |   const string kResponse("HTTP/9.8 204"); | 
 |  | 
 |   EXPECT_CALL(dispatcher(), PostDelayedTask(_, _, 0)); | 
 |   EXPECT_TRUE(StartTrial(kURL)); | 
 |  | 
 |   StartTrialTask(); | 
 |  | 
 |   ExpectTrialReturn(ConnectivityTrial::Result( | 
 |       ConnectivityTrial::kPhaseContent, | 
 |       ConnectivityTrial::kStatusSuccess)); | 
 |  | 
 |   AppendReadData(kResponse); | 
 | } | 
 |  | 
 | struct ResultMapping { | 
 |   ResultMapping() : http_result(HttpRequest::kResultUnknown), trial_result() {} | 
 |   ResultMapping(HttpRequest::Result in_http_result, | 
 |                 const ConnectivityTrial::Result& in_trial_result) | 
 |       : http_result(in_http_result), | 
 |         trial_result(in_trial_result) {} | 
 |   HttpRequest::Result http_result; | 
 |   ConnectivityTrial::Result trial_result; | 
 | }; | 
 |  | 
 | class ConnectivityTrialResultMappingTest | 
 |     : public testing::TestWithParam<ResultMapping> {}; | 
 |  | 
 | TEST_P(ConnectivityTrialResultMappingTest, MapResult) { | 
 |   ConnectivityTrial::Result trial_result = | 
 |       ConnectivityTrial::GetPortalResultForRequestResult( | 
 |           GetParam().http_result); | 
 |   EXPECT_EQ(trial_result.phase, GetParam().trial_result.phase); | 
 |   EXPECT_EQ(trial_result.status, GetParam().trial_result.status); | 
 | } | 
 |  | 
 | INSTANTIATE_TEST_CASE_P( | 
 |     TrialResultMappingTest, | 
 |     ConnectivityTrialResultMappingTest, | 
 |     ::testing::Values( | 
 |         ResultMapping( | 
 |             HttpRequest::kResultUnknown, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseUnknown, | 
 |                                       ConnectivityTrial::kStatusFailure)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultInProgress, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseUnknown, | 
 |                                       ConnectivityTrial::kStatusFailure)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultDNSFailure, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseDNS, | 
 |                                       ConnectivityTrial::kStatusFailure)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultDNSTimeout, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseDNS, | 
 |                                       ConnectivityTrial::kStatusTimeout)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultConnectionFailure, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseConnection, | 
 |                                       ConnectivityTrial::kStatusFailure)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultConnectionTimeout, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseConnection, | 
 |                                       ConnectivityTrial::kStatusTimeout)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultRequestFailure, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseHTTP, | 
 |                                       ConnectivityTrial::kStatusFailure)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultRequestTimeout, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseHTTP, | 
 |                                       ConnectivityTrial::kStatusTimeout)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultResponseFailure, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseHTTP, | 
 |                                       ConnectivityTrial::kStatusFailure)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultResponseTimeout, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseHTTP, | 
 |                                       ConnectivityTrial::kStatusTimeout)), | 
 |         ResultMapping( | 
 |             HttpRequest::kResultSuccess, | 
 |             ConnectivityTrial::Result(ConnectivityTrial::kPhaseContent, | 
 |                                       ConnectivityTrial::kStatusFailure)))); | 
 |  | 
 | }  // namespace shill |