1 // Copyright (c) 2012 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 "base/memory/ref_counted.h" 6 #include "base/message_loop/message_loop.h" 7 #include "chrome/browser/extensions/api/dial/dial_device_data.h" 8 #include "chrome/browser/extensions/api/dial/dial_service.h" 9 #include "net/base/capturing_net_log.h" 10 #include "net/base/ip_endpoint.h" 11 #include "testing/gmock/include/gmock/gmock.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 using base::Time; 15 using base::TimeDelta; 16 using ::testing::A; 17 using ::testing::AtLeast; 18 using ::testing::Return; 19 20 namespace { 21 22 const char kValidResponse[] = 23 "HTTP/1.1 OK\r\n" 24 "LOCATION: http://127.0.0.1/dd.xml\r\n" 25 "USN: some_id\r\n" 26 "CACHE-CONTROL: max-age=1800\r\n" 27 "CONFIGID.UPNP.ORG: 1\r\n\r\n"; 28 29 } // namespace 30 31 namespace extensions { 32 33 class MockObserver : public DialService::Observer { 34 public: 35 MOCK_METHOD1(OnDiscoveryRequest, void(DialService*)); 36 MOCK_METHOD2(OnDeviceDiscovered, void(DialService*, const DialDeviceData&)); 37 MOCK_METHOD1(OnDiscoveryFinished, void(DialService*)); 38 MOCK_METHOD2(OnError, void(DialService*, 39 const DialService::DialServiceErrorCode&)); 40 }; 41 42 class DialServiceTest : public testing::Test { 43 public: 44 DialServiceTest() : dial_service_(&capturing_net_log_) { 45 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &mock_ip_)); 46 dial_service_.AddObserver(&mock_observer_); 47 } 48 protected: 49 net::CapturingNetLog capturing_net_log_; 50 net::IPAddressNumber mock_ip_; 51 DialServiceImpl dial_service_; 52 MockObserver mock_observer_; 53 }; 54 55 TEST_F(DialServiceTest, TestSendMultipleRequests) { 56 base::MessageLoop loop(base::MessageLoop::TYPE_IO); 57 // Setting the finish delay to zero disables the timer that invokes 58 // FinishDiscovery(). 59 dial_service_.finish_delay_ = TimeDelta::FromSeconds(0); 60 dial_service_.request_interval_ = TimeDelta::FromSeconds(0); 61 dial_service_.max_requests_ = 4; 62 dial_service_.discovery_active_ = true; 63 EXPECT_CALL(mock_observer_, OnDiscoveryRequest(A<DialService*>())).Times(4); 64 EXPECT_CALL(mock_observer_, OnDiscoveryFinished(A<DialService*>())).Times(1); 65 dial_service_.BindSocketAndSendRequest(mock_ip_); 66 loop.RunUntilIdle(); 67 dial_service_.FinishDiscovery(); 68 } 69 70 TEST_F(DialServiceTest, TestOnDiscoveryRequest) { 71 dial_service_.discovery_active_ = true; 72 dial_service_.num_requests_sent_ = 1; 73 dial_service_.max_requests_ = 1; 74 size_t num_bytes = dial_service_.send_buffer_->size(); 75 EXPECT_CALL(mock_observer_, OnDiscoveryRequest(A<DialService*>())).Times(1); 76 dial_service_.OnSocketWrite(num_bytes); 77 } 78 79 TEST_F(DialServiceTest, TestOnDeviceDiscovered) { 80 dial_service_.discovery_active_ = true; 81 int response_size = arraysize(kValidResponse) - 1; 82 dial_service_.recv_buffer_ = new net::IOBufferWithSize(response_size); 83 strncpy(dial_service_.recv_buffer_->data(), kValidResponse, response_size); 84 dial_service_.recv_address_ = net::IPEndPoint(mock_ip_, 12345); 85 86 DialDeviceData expected_device; 87 expected_device.set_device_id("some_id"); 88 89 EXPECT_CALL(mock_observer_, 90 OnDeviceDiscovered(A<DialService*>(), expected_device)) 91 .Times(1); 92 dial_service_.OnSocketRead(response_size); 93 }; 94 95 TEST_F(DialServiceTest, TestOnDiscoveryFinished) { 96 dial_service_.discovery_active_ = true; 97 98 EXPECT_CALL(mock_observer_, OnDiscoveryFinished(A<DialService*>())).Times(1); 99 dial_service_.FinishDiscovery(); 100 EXPECT_FALSE(dial_service_.discovery_active_); 101 } 102 103 TEST_F(DialServiceTest, TestResponseParsing) { 104 Time now = Time::Now(); 105 106 // Successful case 107 DialDeviceData parsed; 108 EXPECT_TRUE(DialServiceImpl::ParseResponse(kValidResponse, 109 now, &parsed)); 110 EXPECT_EQ("some_id", parsed.device_id()); 111 EXPECT_EQ("http://127.0.0.1/dd.xml", parsed.device_description_url().spec()); 112 EXPECT_EQ(1, parsed.config_id()); 113 EXPECT_EQ(now, parsed.response_time()); 114 115 // Failure cases 116 DialDeviceData not_parsed; 117 118 // Empty, garbage 119 EXPECT_FALSE(DialServiceImpl::ParseResponse(std::string(), now, ¬_parsed)); 120 EXPECT_FALSE(DialServiceImpl::ParseResponse( 121 "\r\n\r\n", 122 now, ¬_parsed)); 123 EXPECT_FALSE(DialServiceImpl::ParseResponse( 124 "xyzzy", 125 now, ¬_parsed)); 126 127 // No headers 128 EXPECT_FALSE(DialServiceImpl::ParseResponse( 129 "HTTP/1.1 OK\r\n\r\n", 130 now, ¬_parsed)); 131 132 // Missing LOCATION 133 EXPECT_FALSE(DialServiceImpl::ParseResponse( 134 "HTTP/1.1 OK\r\n" 135 "USN: some_id\r\n\r\n", 136 now, ¬_parsed)); 137 138 // Empty LOCATION 139 EXPECT_FALSE(DialServiceImpl::ParseResponse( 140 "HTTP/1.1 OK\r\n" 141 "LOCATION:\r\n" 142 "USN: some_id\r\n\r\n", 143 now, ¬_parsed)); 144 145 // Missing USN 146 EXPECT_FALSE(DialServiceImpl::ParseResponse( 147 "HTTP/1.1 OK\r\n" 148 "LOCATION: http://127.0.0.1/dd.xml\r\n\r\n", 149 now, ¬_parsed)); 150 151 // Empty USN 152 EXPECT_FALSE(DialServiceImpl::ParseResponse( 153 "HTTP/1.1 OK\r\n" 154 "LOCATION: http://127.0.0.1/dd.xml\r\n" 155 "USN:\r\n\r\n", 156 now, ¬_parsed)); 157 } 158 159 } // namespace extensions 160