blob: cdb9aa94f82750aeaf16431158379c2855d948ff [file] [log] [blame]
[email protected]6d9fc742009-10-21 07:59:361// Copyright (c) 2009 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#include <vector>
7
8#include "base/task.h"
9#include "net/base/completion_callback.h"
10#include "net/base/mock_host_resolver.h"
11#include "net/base/test_completion_callback.h"
12#include "net/socket/socket_test_util.h"
13#include "net/url_request/url_request_unittest.h"
14#include "net/websockets/websocket.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "testing/platform_test.h"
17
18struct WebSocketEvent {
19 enum EventType {
20 EVENT_OPEN, EVENT_MESSAGE, EVENT_CLOSE,
21 };
22
23 WebSocketEvent(EventType type, net::WebSocket* websocket,
24 const std::string& websocket_msg)
25 : event_type(type), socket(websocket), msg(websocket_msg) {}
26
27 EventType event_type;
28 net::WebSocket* socket;
29 std::string msg;
30};
31
32class WebSocketEventRecorder : public net::WebSocketDelegate {
33 public:
34 explicit WebSocketEventRecorder(net::CompletionCallback* callback)
35 : onopen_(NULL),
36 onmessage_(NULL),
37 onclose_(NULL),
38 callback_(callback) {}
39 virtual ~WebSocketEventRecorder() {
40 delete onopen_;
41 delete onmessage_;
42 delete onclose_;
43 }
44
45 void SetOnOpen(Callback1<WebSocketEvent*>::Type* callback) {
46 onopen_ = callback;
47 }
48 void SetOnMessage(Callback1<WebSocketEvent*>::Type* callback) {
49 onmessage_ = callback;
50 }
51 void SetOnClose(Callback1<WebSocketEvent*>::Type* callback) {
52 onclose_ = callback;
53 }
54
55 virtual void OnOpen(net::WebSocket* socket) {
56 events_.push_back(
57 WebSocketEvent(WebSocketEvent::EVENT_OPEN, socket, std::string()));
58 if (onopen_)
59 onopen_->Run(&events_.back());
60 }
61
62 virtual void OnMessage(net::WebSocket* socket, const std::string& msg) {
63 events_.push_back(
64 WebSocketEvent(WebSocketEvent::EVENT_MESSAGE, socket, msg));
65 if (onmessage_)
66 onmessage_->Run(&events_.back());
67 }
68 virtual void OnClose(net::WebSocket* socket) {
69 events_.push_back(
70 WebSocketEvent(WebSocketEvent::EVENT_CLOSE, socket, std::string()));
71 if (onclose_)
72 onclose_->Run(&events_.back());
73 if (callback_)
74 callback_->Run(net::OK);
75 }
76
77 void DoClose(WebSocketEvent* event) {
78 event->socket->Close();
79 }
80
81 const std::vector<WebSocketEvent>& GetSeenEvents() const {
82 return events_;
83 }
84
85 private:
86 std::vector<WebSocketEvent> events_;
87 Callback1<WebSocketEvent*>::Type* onopen_;
88 Callback1<WebSocketEvent*>::Type* onmessage_;
89 Callback1<WebSocketEvent*>::Type* onclose_;
90 net::CompletionCallback* callback_;
91
92 DISALLOW_COPY_AND_ASSIGN(WebSocketEventRecorder);
93};
94
95class WebSocketTest : public PlatformTest {
96};
97
98TEST_F(WebSocketTest, Connect) {
99 net::MockClientSocketFactory mock_socket_factory;
100 net::MockRead data_reads[] = {
101 net::MockRead("HTTP/1.1 101 Web Socket Protocol\r\n"
102 "Upgrade: WebSocket\r\n"
103 "Connection: Upgrade\r\n"
104 "WebSocket-Origin: http://example.com\r\n"
105 "WebSocket-Location: ws://example.com/demo\r\n"
106 "WebSocket-Protocol: sample\r\n"
107 "\r\n"),
108 // Server doesn't close the connection after handshake.
109 net::MockRead(true, net::ERR_IO_PENDING),
110 };
111 net::MockWrite data_writes[] = {
112 net::MockWrite("GET /demo HTTP/1.1\r\n"
113 "Upgrade: WebSocket\r\n"
114 "Connection: Upgrade\r\n"
115 "Host: example.com\r\n"
116 "Origin: http://example.com\r\n"
117 "WebSocket-Protocol: sample\r\n"
118 "\r\n"),
119 };
120 net::StaticMockSocket data(data_reads, data_writes);
121 mock_socket_factory.AddMockSocket(&data);
122
123 net::WebSocket::Request* request(
124 new net::WebSocket::Request(GURL("ws://example.com/demo"),
125 "sample",
126 "http://example.com",
127 "ws://example.com/demo",
128 new TestURLRequestContext()));
129 request->SetHostResolver(new net::MockHostResolver());
130 request->SetClientSocketFactory(&mock_socket_factory);
131
132 TestCompletionCallback callback;
133
134 scoped_ptr<WebSocketEventRecorder> delegate(
135 new WebSocketEventRecorder(&callback));
136 delegate->SetOnOpen(NewCallback(delegate.get(),
137 &WebSocketEventRecorder::DoClose));
138
139 scoped_refptr<net::WebSocket> websocket(
140 new net::WebSocket(request, delegate.get()));
141
142 EXPECT_EQ(net::WebSocket::INITIALIZED, websocket->ready_state());
143 websocket->Connect();
144
145 callback.WaitForResult();
146
147 const std::vector<WebSocketEvent>& events = delegate->GetSeenEvents();
148 EXPECT_EQ(2U, events.size());
149
150 EXPECT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
151 EXPECT_EQ(WebSocketEvent::EVENT_CLOSE, events[1].event_type);
152}
153
154TEST_F(WebSocketTest, ServerSentData) {
155 net::MockClientSocketFactory mock_socket_factory;
156 static const char kMessage[] = "Hello";
157 static const char kFrame[] = "\x00Hello\xff";
158 static const int kFrameLen = sizeof(kFrame) - 1;
159 net::MockRead data_reads[] = {
160 net::MockRead("HTTP/1.1 101 Web Socket Protocol\r\n"
161 "Upgrade: WebSocket\r\n"
162 "Connection: Upgrade\r\n"
163 "WebSocket-Origin: http://example.com\r\n"
164 "WebSocket-Location: ws://example.com/demo\r\n"
165 "WebSocket-Protocol: sample\r\n"
166 "\r\n"),
167 net::MockRead(true, kFrame, kFrameLen),
168 // Server doesn't close the connection after handshake.
169 net::MockRead(true, net::ERR_IO_PENDING),
170 };
171 net::MockWrite data_writes[] = {
172 net::MockWrite("GET /demo HTTP/1.1\r\n"
173 "Upgrade: WebSocket\r\n"
174 "Connection: Upgrade\r\n"
175 "Host: example.com\r\n"
176 "Origin: http://example.com\r\n"
177 "WebSocket-Protocol: sample\r\n"
178 "\r\n"),
179 };
180 net::StaticMockSocket data(data_reads, data_writes);
181 mock_socket_factory.AddMockSocket(&data);
182
183 net::WebSocket::Request* request(
184 new net::WebSocket::Request(GURL("ws://example.com/demo"),
185 "sample",
186 "http://example.com",
187 "ws://example.com/demo",
188 new TestURLRequestContext()));
189 request->SetHostResolver(new net::MockHostResolver());
190 request->SetClientSocketFactory(&mock_socket_factory);
191
192 TestCompletionCallback callback;
193
194 scoped_ptr<WebSocketEventRecorder> delegate(
195 new WebSocketEventRecorder(&callback));
196 delegate->SetOnMessage(NewCallback(delegate.get(),
197 &WebSocketEventRecorder::DoClose));
198
199 scoped_refptr<net::WebSocket> websocket(
200 new net::WebSocket(request, delegate.get()));
201
202 EXPECT_EQ(net::WebSocket::INITIALIZED, websocket->ready_state());
203 websocket->Connect();
204
205 callback.WaitForResult();
206
207 const std::vector<WebSocketEvent>& events = delegate->GetSeenEvents();
208 EXPECT_EQ(3U, events.size());
209
210 EXPECT_EQ(WebSocketEvent::EVENT_OPEN, events[0].event_type);
211 EXPECT_EQ(WebSocketEvent::EVENT_MESSAGE, events[1].event_type);
212 EXPECT_EQ(kMessage, events[1].msg);
213 EXPECT_EQ(WebSocketEvent::EVENT_CLOSE, events[2].event_type);
214}