blob: 2e1753b0c1ea19c26d5902143b485a481bce5eeb [file] [log] [blame]
// Copyright (c) 2012 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 "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/extensions/api/dial/dial_device_data.h"
#include "chrome/browser/extensions/api/dial/dial_service.h"
#include "net/base/capturing_net_log.h"
#include "net/base/ip_endpoint.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::Time;
using base::TimeDelta;
using ::testing::A;
using ::testing::AtLeast;
using ::testing::Return;
namespace {
const char kValidResponse[] =
"HTTP/1.1 OK\r\n"
"LOCATION: http://127.0.0.1/dd.xml\r\n"
"USN: some_id\r\n"
"CACHE-CONTROL: max-age=1800\r\n"
"CONFIGID.UPNP.ORG: 1\r\n\r\n";
} // namespace
namespace extensions {
class MockObserver : public DialService::Observer {
public:
MOCK_METHOD1(OnDiscoveryRequest, void(DialService*));
MOCK_METHOD2(OnDeviceDiscovered, void(DialService*, const DialDeviceData&));
MOCK_METHOD1(OnDiscoveryFinished, void(DialService*));
MOCK_METHOD2(OnError, void(DialService*,
const DialService::DialServiceErrorCode&));
};
class DialServiceTest : public testing::Test {
public:
DialServiceTest()
: dial_service_(&capturing_net_log_) {
CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &mock_ip_));
dial_service_.AddObserver(&mock_observer_);
dial_socket_ = dial_service_.CreateDialSocket();
}
protected:
net::CapturingNetLog capturing_net_log_;
net::IPAddressNumber mock_ip_;
DialServiceImpl dial_service_;
scoped_ptr<DialServiceImpl::DialSocket> dial_socket_;
MockObserver mock_observer_;
};
TEST_F(DialServiceTest, TestSendMultipleRequests) {
base::MessageLoop loop(base::MessageLoop::TYPE_IO);
// Setting the finish delay to zero disables the timer that invokes
// FinishDiscovery().
dial_service_.finish_delay_ = TimeDelta::FromSeconds(0);
dial_service_.request_interval_ = TimeDelta::FromSeconds(0);
dial_service_.max_requests_ = 4;
dial_service_.discovery_active_ = true;
EXPECT_CALL(mock_observer_, OnDiscoveryRequest(A<DialService*>())).Times(4);
EXPECT_CALL(mock_observer_, OnDiscoveryFinished(A<DialService*>())).Times(1);
dial_service_.BindAndAddSocket(mock_ip_);
dial_service_.SendOneRequest();
loop.RunUntilIdle();
dial_service_.FinishDiscovery();
}
TEST_F(DialServiceTest, TestOnDiscoveryRequest) {
dial_service_.discovery_active_ = true;
dial_service_.num_requests_sent_ = 1;
dial_service_.max_requests_ = 1;
size_t num_bytes = dial_service_.send_buffer_->size();
EXPECT_CALL(mock_observer_, OnDiscoveryRequest(A<DialService*>())).Times(1);
dial_socket_->OnSocketWrite(num_bytes, num_bytes);
}
TEST_F(DialServiceTest, TestOnDeviceDiscovered) {
dial_service_.discovery_active_ = true;
int response_size = arraysize(kValidResponse) - 1;
dial_socket_->recv_buffer_ =
new net::IOBufferWithSize(response_size);
strncpy(dial_socket_->recv_buffer_->data(),
kValidResponse,
response_size);
dial_socket_->recv_address_ = net::IPEndPoint(mock_ip_, 12345);
DialDeviceData expected_device;
expected_device.set_device_id("some_id");
EXPECT_CALL(mock_observer_,
OnDeviceDiscovered(A<DialService*>(), expected_device))
.Times(1);
dial_socket_->OnSocketRead(response_size);
};
TEST_F(DialServiceTest, TestOnDiscoveryFinished) {
dial_service_.discovery_active_ = true;
EXPECT_CALL(mock_observer_, OnDiscoveryFinished(A<DialService*>())).Times(1);
dial_service_.FinishDiscovery();
EXPECT_FALSE(dial_service_.discovery_active_);
}
TEST_F(DialServiceTest, TestResponseParsing) {
Time now = Time::Now();
// Successful case
DialDeviceData parsed;
EXPECT_TRUE(DialServiceImpl::DialSocket::ParseResponse(
kValidResponse, now, &parsed));
EXPECT_EQ("some_id", parsed.device_id());
EXPECT_EQ("http://127.0.0.1/dd.xml", parsed.device_description_url().spec());
EXPECT_EQ(1, parsed.config_id());
EXPECT_EQ(now, parsed.response_time());
// Failure cases
DialDeviceData not_parsed;
// Empty, garbage
EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
std::string(), now, &not_parsed));
EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
"\r\n\r\n",
now, &not_parsed));
EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
"xyzzy",
now, &not_parsed));
// No headers
EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
"HTTP/1.1 OK\r\n\r\n",
now, &not_parsed));
// Missing LOCATION
EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
"HTTP/1.1 OK\r\n"
"USN: some_id\r\n\r\n",
now, &not_parsed));
// Empty LOCATION
EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
"HTTP/1.1 OK\r\n"
"LOCATION:\r\n"
"USN: some_id\r\n\r\n",
now, &not_parsed));
// Missing USN
EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
"HTTP/1.1 OK\r\n"
"LOCATION: http://127.0.0.1/dd.xml\r\n\r\n",
now, &not_parsed));
// Empty USN
EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
"HTTP/1.1 OK\r\n"
"LOCATION: http://127.0.0.1/dd.xml\r\n"
"USN:\r\n\r\n",
now, &not_parsed));
}
} // namespace extensions