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 <string>
6
7#include "base/compiler_specific.h"
8#include "base/memory/ref_counted.h"
9#include "base/message_loop/message_loop.h"
10#include "base/message_loop/message_loop_proxy.h"
11#include "base/single_thread_task_runner.h"
12#include "base/threading/platform_thread.h"
13#include "base/threading/thread.h"
14#include "base/time/time.h"
15#include "chrome/test/chromedriver/net/sync_websocket_impl.h"
16#include "chrome/test/chromedriver/net/test_http_server.h"
17#include "chrome/test/chromedriver/net/url_request_context_getter.h"
18#include "testing/gtest/include/gtest/gtest.h"
19#include "url/gurl.h"
20
21namespace {
22
23class SyncWebSocketImplTest : public testing::Test {
24 protected:
25  SyncWebSocketImplTest()
26      : client_thread_("ClientThread"),
27        long_timeout_(base::TimeDelta::FromMinutes(1)) {}
28  virtual ~SyncWebSocketImplTest() {}
29
30  virtual void SetUp() OVERRIDE {
31    base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
32    ASSERT_TRUE(client_thread_.StartWithOptions(options));
33    context_getter_ = new URLRequestContextGetter(
34        client_thread_.message_loop_proxy());
35    ASSERT_TRUE(server_.Start());
36  }
37
38  virtual void TearDown() OVERRIDE {
39    server_.Stop();
40  }
41
42  base::Thread client_thread_;
43  TestHttpServer server_;
44  scoped_refptr<URLRequestContextGetter> context_getter_;
45  const base::TimeDelta long_timeout_;
46};
47
48}  // namespace
49
50TEST_F(SyncWebSocketImplTest, CreateDestroy) {
51  SyncWebSocketImpl sock(context_getter_.get());
52}
53
54TEST_F(SyncWebSocketImplTest, Connect) {
55  SyncWebSocketImpl sock(context_getter_.get());
56  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
57}
58
59TEST_F(SyncWebSocketImplTest, ConnectFail) {
60  SyncWebSocketImpl sock(context_getter_.get());
61  ASSERT_FALSE(sock.Connect(GURL("ws://127.0.0.1:33333")));
62}
63
64TEST_F(SyncWebSocketImplTest, SendReceive) {
65  SyncWebSocketImpl sock(context_getter_.get());
66  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
67  ASSERT_TRUE(sock.Send("hi"));
68  std::string message;
69  ASSERT_EQ(
70      SyncWebSocket::kOk,
71      sock.ReceiveNextMessage(&message, long_timeout_));
72  ASSERT_STREQ("hi", message.c_str());
73}
74
75TEST_F(SyncWebSocketImplTest, SendReceiveTimeout) {
76  SyncWebSocketImpl sock(context_getter_.get());
77  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
78  ASSERT_TRUE(sock.Send("hi"));
79  std::string message;
80  ASSERT_EQ(
81      SyncWebSocket::kTimeout,
82      sock.ReceiveNextMessage(
83          &message, base::TimeDelta()));
84}
85
86TEST_F(SyncWebSocketImplTest, SendReceiveLarge) {
87  SyncWebSocketImpl sock(context_getter_.get());
88  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
89  std::string wrote_message(10 << 20, 'a');
90  ASSERT_TRUE(sock.Send(wrote_message));
91  std::string message;
92  ASSERT_EQ(
93      SyncWebSocket::kOk,
94      sock.ReceiveNextMessage(&message, long_timeout_));
95  ASSERT_EQ(wrote_message.length(), message.length());
96  ASSERT_EQ(wrote_message, message);
97}
98
99TEST_F(SyncWebSocketImplTest, SendReceiveMany) {
100  SyncWebSocketImpl sock(context_getter_.get());
101  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
102  ASSERT_TRUE(sock.Send("1"));
103  ASSERT_TRUE(sock.Send("2"));
104  std::string message;
105  ASSERT_EQ(
106      SyncWebSocket::kOk,
107      sock.ReceiveNextMessage(&message, long_timeout_));
108  ASSERT_STREQ("1", message.c_str());
109  ASSERT_TRUE(sock.Send("3"));
110  ASSERT_EQ(
111      SyncWebSocket::kOk,
112      sock.ReceiveNextMessage(&message, long_timeout_));
113  ASSERT_STREQ("2", message.c_str());
114  ASSERT_EQ(
115      SyncWebSocket::kOk,
116      sock.ReceiveNextMessage(&message, long_timeout_));
117  ASSERT_STREQ("3", message.c_str());
118}
119
120TEST_F(SyncWebSocketImplTest, CloseOnReceive) {
121  server_.SetMessageAction(TestHttpServer::kCloseOnMessage);
122  SyncWebSocketImpl sock(context_getter_.get());
123  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
124  ASSERT_TRUE(sock.Send("1"));
125  std::string message;
126  ASSERT_EQ(
127      SyncWebSocket::kDisconnected,
128      sock.ReceiveNextMessage(&message, long_timeout_));
129  ASSERT_STREQ("", message.c_str());
130}
131
132TEST_F(SyncWebSocketImplTest, CloseOnSend) {
133  SyncWebSocketImpl sock(context_getter_.get());
134  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
135  server_.Stop();
136  ASSERT_FALSE(sock.Send("1"));
137}
138
139TEST_F(SyncWebSocketImplTest, Reconnect) {
140  SyncWebSocketImpl sock(context_getter_.get());
141  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
142  ASSERT_TRUE(sock.Send("1"));
143  // Wait for SyncWebSocket to receive the response from the server.
144  base::TimeTicks deadline =
145      base::TimeTicks::Now() + base::TimeDelta::FromSeconds(20);
146  while (base::TimeTicks::Now() < deadline) {
147    if (sock.IsConnected() && !sock.HasNextMessage())
148      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
149    else
150      break;
151  }
152  server_.Stop();
153  ASSERT_FALSE(sock.Send("2"));
154  ASSERT_FALSE(sock.IsConnected());
155  server_.Start();
156  ASSERT_TRUE(sock.HasNextMessage());
157  ASSERT_TRUE(sock.Connect(server_.web_socket_url()));
158  ASSERT_FALSE(sock.HasNextMessage());
159  ASSERT_TRUE(sock.Send("3"));
160  std::string message;
161  ASSERT_EQ(
162      SyncWebSocket::kOk,
163      sock.ReceiveNextMessage(&message, long_timeout_));
164  ASSERT_STREQ("3", message.c_str());
165  ASSERT_FALSE(sock.HasNextMessage());
166}
167