Home | History | Annotate | Download | only in cast_channel
      1 // Copyright 2013 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/bind.h"
      6 #include "base/command_line.h"
      7 #include "base/files/file_path.h"
      8 #include "chrome/browser/extensions/api/cast_channel/cast_channel_api.h"
      9 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h"
     10 #include "chrome/browser/extensions/extension_apitest.h"
     11 #include "chrome/browser/extensions/extension_service.h"
     12 #include "chrome/common/extensions/api/cast_channel.h"
     13 #include "content/public/browser/browser_thread.h"
     14 #include "extensions/common/switches.h"
     15 #include "net/base/capturing_net_log.h"
     16 #include "net/base/completion_callback.h"
     17 #include "net/base/net_errors.h"
     18 #include "testing/gmock/include/gmock/gmock.h"
     19 #include "testing/gmock_mutant.h"
     20 
     21 namespace cast_channel =  extensions::api::cast_channel;
     22 using cast_channel::CastSocket;
     23 using cast_channel::ChannelError;
     24 using cast_channel::MessageInfo;
     25 using cast_channel::ReadyState;
     26 
     27 using ::testing::_;
     28 using ::testing::A;
     29 using ::testing::DoAll;
     30 using ::testing::Invoke;
     31 using ::testing::InSequence;
     32 using ::testing::Return;
     33 
     34 namespace {
     35 
     36 const char kTestExtensionId[] = "ddchlicdkolnonkihahngkmmmjnjlkkf";
     37 
     38 static void FillMessageInfo(MessageInfo* message_info,
     39                             const std::string& message) {
     40   message_info->namespace_ = "foo";
     41   message_info->source_id = "src";
     42   message_info->destination_id = "dest";
     43   message_info->data.reset(new base::StringValue(message));
     44 }
     45 
     46 ACTION_TEMPLATE(InvokeCompletionCallback,
     47                 HAS_1_TEMPLATE_PARAMS(int, k),
     48                 AND_1_VALUE_PARAMS(result)) {
     49   ::std::tr1::get<k>(args).Run(result);
     50 }
     51 
     52 ACTION_P2(InvokeDelegateOnError, api_test, api) {
     53   api_test->CallOnError(api);
     54 }
     55 
     56 class MockCastSocket : public CastSocket {
     57  public:
     58   explicit MockCastSocket(CastSocket::Delegate* delegate,
     59                           net::IPEndPoint ip_endpoint,
     60                           net::NetLog* net_log)
     61     : CastSocket(kTestExtensionId, ip_endpoint,
     62                  cast_channel::CHANNEL_AUTH_TYPE_SSL, delegate, net_log) {}
     63   virtual ~MockCastSocket() {}
     64 
     65   virtual bool CalledOnValidThread() const OVERRIDE {
     66     // Always return true in testing.
     67     return true;
     68   }
     69 
     70   MOCK_METHOD1(Connect, void(const net::CompletionCallback& callback));
     71   MOCK_METHOD2(SendMessage, void(const MessageInfo& message,
     72                                  const net::CompletionCallback& callback));
     73   MOCK_METHOD1(Close, void(const net::CompletionCallback& callback));
     74   MOCK_CONST_METHOD0(ready_state, cast_channel::ReadyState());
     75   MOCK_CONST_METHOD0(error_state, cast_channel::ChannelError());
     76 };
     77 
     78 }  // namespace
     79 
     80 class CastChannelAPITest : public ExtensionApiTest {
     81  public:
     82   CastChannelAPITest() {}
     83 
     84   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     85     ExtensionApiTest::SetUpCommandLine(command_line);
     86     command_line->AppendSwitchASCII(
     87         extensions::switches::kWhitelistedExtensionID,
     88         kTestExtensionId);
     89   }
     90 
     91   void SetUpMockCastSocket() {
     92     extensions::CastChannelAPI* api = GetApi();
     93     net::IPAddressNumber ip_number;
     94     net::ParseIPLiteralToNumber("192.168.1.1", &ip_number);
     95     net::IPEndPoint ip_endpoint(ip_number, 8009);
     96     mock_cast_socket_ = new MockCastSocket(api, ip_endpoint,
     97                                            &capturing_net_log_);
     98     // Transfers ownership of the socket.
     99     api->SetSocketForTest(
    100         make_scoped_ptr<CastSocket>(mock_cast_socket_).Pass());
    101 
    102     // Set expectations on error_state().
    103     EXPECT_CALL(*mock_cast_socket_, error_state())
    104       .WillRepeatedly(Return(cast_channel::CHANNEL_ERROR_NONE));
    105   }
    106 
    107   extensions::CastChannelAPI* GetApi() {
    108     return extensions::CastChannelAPI::Get(profile());
    109   }
    110 
    111   void CallOnError(extensions::CastChannelAPI* api) {
    112     api->OnError(mock_cast_socket_,
    113                  cast_channel::CHANNEL_ERROR_CONNECT_ERROR);
    114   }
    115 
    116  protected:
    117   void CallOnMessage(const std::string& message) {
    118     content::BrowserThread::PostTask(
    119         content::BrowserThread::IO,
    120         FROM_HERE,
    121         base::Bind(&CastChannelAPITest::DoCallOnMessage, this,
    122                    GetApi(), mock_cast_socket_, message));
    123   }
    124 
    125   void DoCallOnMessage(extensions::CastChannelAPI* api,
    126                        MockCastSocket* cast_socket,
    127                        const std::string& message) {
    128     MessageInfo message_info;
    129     FillMessageInfo(&message_info, message);
    130     api->OnMessage(cast_socket, message_info);
    131   }
    132 
    133   MockCastSocket* mock_cast_socket_;
    134   net::CapturingNetLog capturing_net_log_;
    135 };
    136 
    137 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
    138 // always return true without actually running the test. Remove when fixed.
    139 #if defined(OS_WIN) && !defined(NDEBUG)
    140 #define MAYBE_TestOpenSendClose DISABLED_TestOpenSendClose
    141 #else
    142 #define MAYBE_TestOpenSendClose TestOpenSendClose
    143 #endif
    144 // Test loading extension, opening a channel with ConnectInfo, adding a
    145 // listener, writing, reading, and closing.
    146 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, MAYBE_TestOpenSendClose) {
    147   SetUpMockCastSocket();
    148 
    149   {
    150     InSequence dummy;
    151     EXPECT_CALL(*mock_cast_socket_, Connect(_))
    152         .WillOnce(InvokeCompletionCallback<0>(net::OK));
    153     EXPECT_CALL(*mock_cast_socket_, ready_state())
    154         .WillOnce(Return(cast_channel::READY_STATE_OPEN));
    155     EXPECT_CALL(*mock_cast_socket_, SendMessage(A<const MessageInfo&>(), _))
    156         .WillOnce(InvokeCompletionCallback<1>(net::OK));
    157     EXPECT_CALL(*mock_cast_socket_, ready_state())
    158         .WillOnce(Return(cast_channel::READY_STATE_OPEN));
    159     EXPECT_CALL(*mock_cast_socket_, Close(_))
    160         .WillOnce(InvokeCompletionCallback<0>(net::OK));
    161     EXPECT_CALL(*mock_cast_socket_, ready_state())
    162         .WillOnce(Return(cast_channel::READY_STATE_CLOSED));
    163   }
    164 
    165   EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
    166                                   "test_open_send_close.html"));
    167 }
    168 
    169 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
    170 // always return true without actually running the test. Remove when fixed.
    171 #if defined(OS_WIN) && !defined(NDEBUG)
    172 #define MAYBE_TestOpenSendCloseWithUrl DISABLED_TestOpenSendCloseWithUrl
    173 #else
    174 #define MAYBE_TestOpenSendCloseWithUrl TestOpenSendCloseWithUrl
    175 #endif
    176 // Test loading extension, opening a channel with a URL, adding a listener,
    177 // writing, reading, and closing.
    178 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, MAYBE_TestOpenSendCloseWithUrl) {
    179   SetUpMockCastSocket();
    180 
    181   {
    182     InSequence dummy;
    183     EXPECT_CALL(*mock_cast_socket_, Connect(_))
    184         .WillOnce(InvokeCompletionCallback<0>(net::OK));
    185     EXPECT_CALL(*mock_cast_socket_, ready_state())
    186         .WillOnce(Return(cast_channel::READY_STATE_OPEN));
    187     EXPECT_CALL(*mock_cast_socket_, SendMessage(A<const MessageInfo&>(), _))
    188         .WillOnce(InvokeCompletionCallback<1>(net::OK));
    189     EXPECT_CALL(*mock_cast_socket_, ready_state())
    190         .WillOnce(Return(cast_channel::READY_STATE_OPEN));
    191     EXPECT_CALL(*mock_cast_socket_, Close(_))
    192         .WillOnce(InvokeCompletionCallback<0>(net::OK));
    193     EXPECT_CALL(*mock_cast_socket_, ready_state())
    194         .WillOnce(Return(cast_channel::READY_STATE_CLOSED));
    195   }
    196 
    197   EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
    198                                   "test_open_send_close_url.html"));
    199 }
    200 
    201 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
    202 // always return true without actually running the test. Remove when fixed.
    203 #if defined(OS_WIN) && !defined(NDEBUG)
    204 #define MAYBE_TestOpenReceiveClose DISABLED_TestOpenReceiveClose
    205 #else
    206 #define MAYBE_TestOpenReceiveClose TestOpenReceiveClose
    207 #endif
    208 // Test loading extension, opening a channel, adding a listener,
    209 // writing, reading, and closing.
    210 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, MAYBE_TestOpenReceiveClose) {
    211   SetUpMockCastSocket();
    212 
    213   {
    214     InSequence dummy;
    215     EXPECT_CALL(*mock_cast_socket_, Connect(_))
    216         .WillOnce(InvokeCompletionCallback<0>(net::OK));
    217     EXPECT_CALL(*mock_cast_socket_, ready_state())
    218         .Times(3)
    219         .WillRepeatedly(Return(cast_channel::READY_STATE_OPEN));
    220     EXPECT_CALL(*mock_cast_socket_, Close(_))
    221         .WillOnce(InvokeCompletionCallback<0>(net::OK));
    222     EXPECT_CALL(*mock_cast_socket_, ready_state())
    223         .WillOnce(Return(cast_channel::READY_STATE_CLOSED));
    224   }
    225 
    226   EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
    227                                   "test_open_receive_close.html"));
    228 
    229   ResultCatcher catcher;
    230   CallOnMessage("some-message");
    231   CallOnMessage("some-message");
    232   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    233 }
    234 
    235 // TODO(munjal): Win Dbg has a workaround that makes RunExtensionSubtest
    236 // always return true without actually running the test. Remove when fixed.
    237 #if defined(OS_WIN) && !defined(NDEBUG)
    238 #define MAYBE_TestOpenError DISABLED_TestOpenError
    239 #else
    240 #define MAYBE_TestOpenError TestOpenError
    241 #endif
    242 // Test the case when socket open results in an error.
    243 IN_PROC_BROWSER_TEST_F(CastChannelAPITest, MAYBE_TestOpenError) {
    244   SetUpMockCastSocket();
    245 
    246   EXPECT_CALL(*mock_cast_socket_, Connect(_))
    247       .WillOnce(DoAll(
    248           InvokeDelegateOnError(this, GetApi()),
    249           InvokeCompletionCallback<0>(net::ERR_FAILED)));
    250   EXPECT_CALL(*mock_cast_socket_, ready_state())
    251       .WillRepeatedly(Return(cast_channel::READY_STATE_CLOSED));
    252   EXPECT_CALL(*mock_cast_socket_, Close(_));
    253 
    254   EXPECT_TRUE(RunExtensionSubtest("cast_channel/api",
    255                                   "test_open_error.html"));
    256 
    257   ResultCatcher catcher;
    258   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    259 }
    260 
    261