Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: tests/standalone/io/web_socket_protocol_processor_test.dart

Issue 12387085: Improve web-socket implementation by using making _WebSocketProtocolProcessor a StreamTransformer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/io/websocket_impl.dart ('k') | tests/standalone/io/web_socket_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import "dart:utf";
5 import "dart:math"; 6 import "dart:math";
6 import "dart:async"; 7 import "dart:async";
8 import "dart:collection";
9 import "dart:scalarlist";
7 10
8 part "../../../sdk/lib/io/http.dart"; 11 part "../../../sdk/lib/io/http.dart";
12 part "../../../sdk/lib/io/buffer_list.dart";
9 part "../../../sdk/lib/io/io_sink.dart"; 13 part "../../../sdk/lib/io/io_sink.dart";
14 part "../../../sdk/lib/io/string_transformer.dart";
10 part "../../../sdk/lib/io/websocket.dart"; 15 part "../../../sdk/lib/io/websocket.dart";
11 part "../../../sdk/lib/io/websocket_impl.dart"; 16 part "../../../sdk/lib/io/websocket_impl.dart";
12 17
13 class WebSocketFrame { 18 class WebSocketFrame {
14 WebSocketFrame(int opcode, List<int> data); 19 WebSocketFrame(int opcode, List<int> data);
15 } 20 }
16 21
17 // Class that when hooked up to the web socket protocol processor will 22 // Class that when hooked up to the web socket protocol transformer will
18 // collect the message and expect it to be equal to the 23 // collect the message and expect it to be equal to the
19 // expectedMessage field when fully received. 24 // expectedMessage field when fully received.
20 class WebSocketMessageCollector { 25 class WebSocketMessageCollector {
21 WebSocketMessageCollector(_WebSocketProtocolProcessor this.processor, 26 List<int> expectedMessage;
27
28 int messageCount = 0;
29 int closeCount = 0;
30
31 var data;
32
33 WebSocketMessageCollector(_WebSocketProtocolTransformer transformer,
22 [List<int> this.expectedMessage = null]) { 34 [List<int> this.expectedMessage = null]) {
23 processor.onMessageStart = onMessageStart; 35 transformer.listen(onMessageData, onDone: onClosed, onError: onError);
24 processor.onMessageData = onMessageData;
25 processor.onMessageEnd = onMessageEnd;
26 processor.onClosed = onClosed;
27 } 36 }
28 37
29 void onMessageStart(int type) { 38 void onMessageData(buffer) {
30 data = new List<int>(); 39 if (buffer is String) {
31 } 40 buffer = _encodeString(buffer);
32 41 }
33 void onMessageData(List<int> buffer, int index, int count) { 42 Expect.listEquals(expectedMessage, buffer);
34 data.addAll(buffer.getRange(index, count));
35 }
36
37 void onMessageEnd() {
38 messageCount++; 43 messageCount++;
39 Expect.listEquals(expectedMessage, data); 44 data = buffer;
40 data = null;
41 } 45 }
42 46
43 void onClosed(int status, String reason) { 47 void onClosed(int status, String reason) {
44 closeCount++; 48 closeCount++;
45 } 49 }
46 50
47 void onError(e) { 51 void onError(e) {
48 Expect.fail("Unexpected error $e"); 52 Expect.fail("Unexpected error $e");
49 } 53 }
50 54
51 _WebSocketProtocolProcessor processor;
52 List<int> expectedMessage;
53
54 List<int> data;
55 int messageCount = 0;
56 int closeCount = 0;
57 } 55 }
58 56
59 57
60 // Web socket constants. 58 // Web socket constants.
61 const int FRAME_OPCODE_TEXT = 1; 59 const int FRAME_OPCODE_TEXT = 1;
62 const int FRAME_OPCODE_BINARY = 2; 60 const int FRAME_OPCODE_BINARY = 2;
63 61
64 62
65 // Function for building a web socket frame. 63 // Function for building a web socket frame.
66 List<int> createFrame(bool fin, 64 List<int> createFrame(bool fin,
(...skipping 23 matching lines...) Expand all
90 frame[frameIndex++] = count >> ((7 - i) * 8) & 0xFF; 88 frame[frameIndex++] = count >> ((7 - i) * 8) & 0xFF;
91 } 89 }
92 } 90 }
93 frame.setRange(frameIndex, count, data, offset); 91 frame.setRange(frameIndex, count, data, offset);
94 return frame; 92 return frame;
95 } 93 }
96 94
97 95
98 // Test processing messages which are sent in a single frame. 96 // Test processing messages which are sent in a single frame.
99 void testFullMessages() { 97 void testFullMessages() {
100 // Use the same web socket protocol processor for all frames. 98 void testMessage(int opcode, List<int> message) {
101 _WebSocketProtocolProcessor processor = new _WebSocketProtocolProcessor(); 99 int messageCount = 0;
102 WebSocketMessageCollector mc = new WebSocketMessageCollector(processor); 100 // Use the same web socket protocol transformer for all frames.
101 var transformer = new _WebSocketProtocolTransformer();
102 var controller = new StreamController();
103 WebSocketMessageCollector mc = new WebSocketMessageCollector(
104 controller.stream.transform(transformer),
105 message);
103 106
104 int messageCount = 0;
105
106 void testMessage(int opcode, List<int> message) {
107 mc.expectedMessage = message;
108 List<int> frame = createFrame( 107 List<int> frame = createFrame(
109 true, opcode, null, message, 0, message.length); 108 true, opcode, null, message, 0, message.length);
110 109
111 // Update the processor with one big chunk. 110 // Update the transformer with one big chunk.
112 messageCount++; 111 messageCount++;
113 processor.update(frame, 0, frame.length); 112 controller.add(frame);
114 Expect.isNull(mc.data); 113 Expect.isNotNull(mc.data);
115 Expect.equals(0, processor._state); 114 Expect.equals(0, transformer._state);
115
116 mc.data = null;
116 117
117 // Only run this part on small messages. 118 // Only run this part on small messages.
118 if (message.length < 1000) { 119 if (message.length < 1000) {
119 // Update the processor one byte at the time. 120 // Update the transformer one byte at the time.
120 messageCount++; 121 messageCount++;
121 for (int i = 0; i < frame.length; i++) { 122 for (int i = 0; i < frame.length; i++) {
122 processor.update(frame, i, 1); 123 controller.add(frame.getRange(i, 1));
123 } 124 }
124 Expect.equals(0, processor._state); 125 Expect.equals(0, transformer._state);
125 Expect.isNull(mc.data); 126 Expect.isNotNull(mc.data);
127 mc.data = null;
126 128
127 // Update the processor two bytes at the time. 129 // Update the transformer two bytes at the time.
128 messageCount++; 130 messageCount++;
129 for (int i = 0; i < frame.length; i += 2) { 131 for (int i = 0; i < frame.length; i += 2) {
130 processor.update(frame, i, i + 1 < frame.length ? 2 : 1); 132 controller.add(frame.getRange(i, i + 1 < frame.length ? 2 : 1));
131 } 133 }
132 Expect.equals(0, processor._state); 134 Expect.equals(0, transformer._state);
133 Expect.isNull(mc.data); 135 Expect.isNotNull(mc.data);
134 } 136 }
137 Expect.equals(messageCount, mc.messageCount);
138 Expect.equals(0, mc.closeCount);
139 print("Messages test, messages $messageCount");
135 } 140 }
136 141
137 void runTest(int from, int to, int step) { 142 void runTest(int from, int to, int step) {
138 for (int messageLength = from; messageLength < to; messageLength += step) { 143 for (int messageLength = from; messageLength < to; messageLength += step) {
139 List<int> message = new List<int>(messageLength); 144 List<int> message = new List<int>(messageLength);
145 for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
146 testMessage(FRAME_OPCODE_TEXT, message);
140 for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF; 147 for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
141 testMessage(FRAME_OPCODE_TEXT, message);
142 testMessage(FRAME_OPCODE_BINARY, message); 148 testMessage(FRAME_OPCODE_BINARY, message);
143 } 149 }
144 } 150 }
145 151
146 // Test different message sizes. 152 // Test different message sizes.
147 runTest(0, 10, 1); 153 runTest(0, 10, 1);
148 runTest(120, 130, 1); 154 runTest(120, 130, 1);
149 runTest(0, 1000, 100); 155 runTest(0, 1000, 100);
150 runTest(65534, 65537, 1); 156 runTest(65534, 65537, 1);
151 print("Messages test, messages $messageCount");
152 Expect.equals(messageCount, mc.messageCount);
153 Expect.equals(0, mc.closeCount);
154 } 157 }
155 158
156 159
157 // Test processing of frames which are split into fragments. 160 // Test processing of frames which are split into fragments.
158 void testFragmentedMessages() { 161 void testFragmentedMessages() {
159 // Use the same web socket protocol processor for all frames. 162 // Use the same web socket protocol transformer for all frames.
160 _WebSocketProtocolProcessor processor = new _WebSocketProtocolProcessor(); 163 var transformer = new _WebSocketProtocolTransformer();
161 WebSocketMessageCollector mc = new WebSocketMessageCollector(processor); 164 var controller = new StreamController();
165 WebSocketMessageCollector mc = new WebSocketMessageCollector(
166 controller.stream.transform(transformer));
162 167
163 int messageCount = 0; 168 int messageCount = 0;
164 int frameCount = 0; 169 int frameCount = 0;
165 170
166 void testFragmentMessage(int opcode, List<int> message, int fragmentSize) { 171 void testFragmentMessage(int opcode, List<int> message, int fragmentSize) {
167 messageCount++; 172 messageCount++;
168 int messageIndex = 0; 173 int messageIndex = 0;
169 int remaining = message.length; 174 int remaining = message.length;
170 bool firstFrame = true; 175 bool firstFrame = true;
171 bool lastFrame = false; 176 bool lastFrame = false;
172 while (!lastFrame) { 177 while (!lastFrame) {
173 int payloadSize = min(fragmentSize, remaining); 178 int payloadSize = min(fragmentSize, remaining);
174 lastFrame = payloadSize == remaining; 179 lastFrame = payloadSize == remaining;
175 List<int> frame = createFrame(lastFrame, 180 List<int> frame = createFrame(lastFrame,
176 firstFrame ? opcode : 0x00, 181 firstFrame ? opcode : 0x00,
177 null, 182 null,
178 message, 183 message,
179 messageIndex, 184 messageIndex,
180 payloadSize); 185 payloadSize);
181 frameCount++; 186 frameCount++;
182 messageIndex += payloadSize; 187 messageIndex += payloadSize;
183 processor.update(frame, 0, frame.length); 188 controller.add(frame);
184 remaining -= payloadSize; 189 remaining -= payloadSize;
185 firstFrame = false; 190 firstFrame = false;
186 } 191 }
187 } 192 }
188 193
189 void testMessageFragmentation(int opcode, List<int> message) { 194 void testMessageFragmentation(int opcode, List<int> message) {
190 mc.expectedMessage = message; 195 mc.expectedMessage = message;
191 196
192 // Test with fragmenting the message in different fragment sizes. 197 // Test with fragmenting the message in different fragment sizes.
193 if (message.length <= 10) { 198 if (message.length <= 10) {
194 for (int i = 1; i < 10; i++) { 199 for (int i = 1; i < 10; i++) {
195 testFragmentMessage(opcode, message, i); 200 testFragmentMessage(opcode, message, i);
196 } 201 }
197 } else { 202 } else {
198 testFragmentMessage(opcode, message, 10); 203 testFragmentMessage(opcode, message, 10);
199 testFragmentMessage(opcode, message, 100); 204 testFragmentMessage(opcode, message, 100);
200 } 205 }
201 } 206 }
202 207
203 void runTest(int from, int to, int step) { 208 void runTest(int from, int to, int step) {
204 for (int messageLength = from; messageLength < to; messageLength += step) { 209 for (int messageLength = from; messageLength < to; messageLength += step) {
205 List<int> message = new List<int>(messageLength); 210 List<int> message = new List<int>(messageLength);
211 for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
212 testMessageFragmentation(FRAME_OPCODE_TEXT, message);
206 for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF; 213 for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
207 testMessageFragmentation(FRAME_OPCODE_TEXT, message);
208 testMessageFragmentation(FRAME_OPCODE_BINARY, message); 214 testMessageFragmentation(FRAME_OPCODE_BINARY, message);
209 } 215 }
210 } 216 }
211 217
212 // Test different message sizes. 218 // Test different message sizes.
213 runTest(0, 10, 1); 219 runTest(0, 10, 1);
214 runTest(120, 130, 1); 220 runTest(120, 130, 1);
215 runTest(0, 1000, 100); 221 runTest(0, 1000, 100);
216 runTest(65534, 65537, 1); 222 runTest(65534, 65537, 1);
217 print("Fragment messages test, messages $messageCount, frames $frameCount"); 223 print("Fragment messages test, messages $messageCount, frames $frameCount");
218 Expect.equals(messageCount, mc.messageCount); 224 Expect.equals(messageCount, mc.messageCount);
219 Expect.equals(0, mc.closeCount); 225 Expect.equals(0, mc.closeCount);
220 } 226 }
221 227
222 void main() { 228 void main() {
223 testFullMessages(); 229 testFullMessages();
224 testFragmentedMessages(); 230 testFragmentedMessages();
225 } 231 }
OLDNEW
« no previous file with comments | « sdk/lib/io/websocket_impl.dart ('k') | tests/standalone/io/web_socket_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698