12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/single_thread_task_runner.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/net/sync_websocket_impl.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/net/test_http_server.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/net/url_request_context_getter.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncWebSocketImplTest : public testing::Test {
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected:
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncWebSocketImplTest()
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : client_thread_("ClientThread"),
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        long_timeout_(base::TimeDelta::FromMinutes(1)) {}
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SyncWebSocketImplTest() {}
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(client_thread_.StartWithOptions(options));
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_getter_ = new URLRequestContextGetter(
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client_thread_.message_loop_proxy());
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(server_.Start());
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    server_.Stop();
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Thread client_thread_;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestHttpServer server_;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<URLRequestContextGetter> context_getter_;
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::TimeDelta long_timeout_;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncWebSocketImplTest, CreateDestroy) {
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncWebSocketImplTest, Connect) {
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncWebSocketImplTest, ConnectFail) {
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(sock.Connect(GURL("ws://127.0.0.1:33333")));
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncWebSocketImplTest, SendReceive) {
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Send("hi"));
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string message;
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SyncWebSocket::kOk,
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sock.ReceiveNextMessage(&message, long_timeout_));
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("hi", message.c_str());
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(SyncWebSocketImplTest, SendReceiveTimeout) {
767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(sock.Send("hi"));
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string message;
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SyncWebSocket::kTimeout,
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sock.ReceiveNextMessage(
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          &message, base::TimeDelta()));
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(SyncWebSocketImplTest, SendReceiveLarge) {
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string wrote_message(10 << 20, 'a');
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Send(wrote_message));
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string message;
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SyncWebSocket::kOk,
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sock.ReceiveNextMessage(&message, long_timeout_));
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(wrote_message.length(), message.length());
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(wrote_message, message);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncWebSocketImplTest, SendReceiveMany) {
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Send("1"));
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Send("2"));
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string message;
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SyncWebSocket::kOk,
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sock.ReceiveNextMessage(&message, long_timeout_));
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("1", message.c_str());
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Send("3"));
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SyncWebSocket::kOk,
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sock.ReceiveNextMessage(&message, long_timeout_));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("2", message.c_str());
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SyncWebSocket::kOk,
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sock.ReceiveNextMessage(&message, long_timeout_));
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("3", message.c_str());
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncWebSocketImplTest, CloseOnReceive) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  server_.SetMessageAction(TestHttpServer::kCloseOnMessage);
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Send("1"));
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string message;
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SyncWebSocket::kDisconnected,
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sock.ReceiveNextMessage(&message, long_timeout_));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("", message.c_str());
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncWebSocketImplTest, CloseOnSend) {
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  server_.Stop();
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(sock.Send("1"));
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncWebSocketImplTest, Reconnect) {
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SyncWebSocketImpl sock(context_getter_.get());
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Send("1"));
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wait for SyncWebSocket to receive the response from the server.
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::TimeTicks deadline =
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::TimeTicks::Now() + base::TimeDelta::FromSeconds(20);
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  while (base::TimeTicks::Now() < deadline) {
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (sock.IsConnected() && !sock.HasNextMessage())
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  server_.Stop();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(sock.Send("2"));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(sock.IsConnected());
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  server_.Start();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.HasNextMessage());
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(sock.HasNextMessage());
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(sock.Send("3"));
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string message;
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SyncWebSocket::kOk,
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sock.ReceiveNextMessage(&message, long_timeout_));
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STREQ("3", message.c_str());
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(sock.HasNextMessage());
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
167