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

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
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";
7 8
8 part "../../../sdk/lib/io/http.dart"; 9 part "../../../sdk/lib/io/http.dart";
9 part "../../../sdk/lib/io/io_sink.dart"; 10 part "../../../sdk/lib/io/io_sink.dart";
11 part "../../../sdk/lib/io/string_transformer.dart";
10 part "../../../sdk/lib/io/websocket.dart"; 12 part "../../../sdk/lib/io/websocket.dart";
11 part "../../../sdk/lib/io/websocket_impl.dart"; 13 part "../../../sdk/lib/io/websocket_impl.dart";
12 14
13 class WebSocketFrame { 15 class WebSocketFrame {
14 WebSocketFrame(int opcode, List<int> data); 16 WebSocketFrame(int opcode, List<int> data);
15 } 17 }
16 18
17 // Class that when hooked up to the web socket protocol processor will 19 // Class that when hooked up to the web socket protocol transformer will
18 // collect the message and expect it to be equal to the 20 // collect the message and expect it to be equal to the
19 // expectedMessage field when fully received. 21 // expectedMessage field when fully received.
20 class WebSocketMessageCollector { 22 class WebSocketMessageCollector {
21 WebSocketMessageCollector(_WebSocketProtocolProcessor this.processor, 23 List<int> expectedMessage;
24
25 int messageCount = 0;
26 int closeCount = 0;
27
28 var data;
29
30 WebSocketMessageCollector(_WebSocketProtocolTransformer transformer,
22 [List<int> this.expectedMessage = null]) { 31 [List<int> this.expectedMessage = null]) {
23 processor.onMessageStart = onMessageStart; 32 transformer.listen(onMessageData, onDone: onClosed, onError: onError);
24 processor.onMessageData = onMessageData;
25 processor.onMessageEnd = onMessageEnd;
26 processor.onClosed = onClosed;
27 } 33 }
28 34
29 void onMessageStart(int type) { 35 void onMessageData(buffer) {
30 data = new List<int>(); 36 if (buffer is String) {
31 } 37 buffer = _encodeString(buffer);
32 38 }
33 void onMessageData(List<int> buffer, int index, int count) { 39 Expect.listEquals(expectedMessage, buffer);
34 data.addAll(buffer.getRange(index, count));
35 }
36
37 void onMessageEnd() {
38 messageCount++; 40 messageCount++;
39 Expect.listEquals(expectedMessage, data); 41 data = buffer;
40 data = null;
41 } 42 }
42 43
43 void onClosed(int status, String reason) { 44 void onClosed(int status, String reason) {
44 closeCount++; 45 closeCount++;
45 } 46 }
46 47
47 void onError(e) { 48 void onError(e) {
48 Expect.fail("Unexpected error $e"); 49 Expect.fail("Unexpected error $e");
49 } 50 }
50 51
51 _WebSocketProtocolProcessor processor;
52 List<int> expectedMessage;
53
54 List<int> data;
55 int messageCount = 0;
56 int closeCount = 0;
57 } 52 }
58 53
59 54
60 // Web socket constants. 55 // Web socket constants.
61 const int FRAME_OPCODE_TEXT = 1; 56 const int FRAME_OPCODE_TEXT = 1;
62 const int FRAME_OPCODE_BINARY = 2; 57 const int FRAME_OPCODE_BINARY = 2;
63 58
64 59
65 // Function for building a web socket frame. 60 // Function for building a web socket frame.
66 List<int> createFrame(bool fin, 61 List<int> createFrame(bool fin,
(...skipping 23 matching lines...) Expand all
90 frame[frameIndex++] = count >> ((7 - i) * 8) & 0xFF; 85 frame[frameIndex++] = count >> ((7 - i) * 8) & 0xFF;
91 } 86 }
92 } 87 }
93 frame.setRange(frameIndex, count, data, offset); 88 frame.setRange(frameIndex, count, data, offset);
94 return frame; 89 return frame;
95 } 90 }
96 91
97 92
98 // Test processing messages which are sent in a single frame. 93 // Test processing messages which are sent in a single frame.
99 void testFullMessages() { 94 void testFullMessages() {
100 // Use the same web socket protocol processor for all frames. 95 void testMessage(int opcode, List<int> message) {
101 _WebSocketProtocolProcessor processor = new _WebSocketProtocolProcessor(); 96 int messageCount = 0;
102 WebSocketMessageCollector mc = new WebSocketMessageCollector(processor); 97 // Use the same web socket protocol transformer for all frames.
98 var transformer = new _WebSocketProtocolTransformer();
99 var controller = new StreamController();
100 WebSocketMessageCollector mc = new WebSocketMessageCollector(
101 controller.stream.transform(transformer),
102 message);
103 103
104 int messageCount = 0;
105
106 void testMessage(int opcode, List<int> message) {
107 mc.expectedMessage = message;
108 List<int> frame = createFrame( 104 List<int> frame = createFrame(
109 true, opcode, null, message, 0, message.length); 105 true, opcode, null, message, 0, message.length);
110 106
111 // Update the processor with one big chunk. 107 // Update the transformer with one big chunk.
112 messageCount++; 108 messageCount++;
113 processor.update(frame, 0, frame.length); 109 controller.add(frame);
114 Expect.isNull(mc.data); 110 Expect.isNotNull(mc.data);
115 Expect.equals(0, processor._state); 111 Expect.equals(0, transformer._state);
112
113 mc.data = null;
116 114
117 // Only run this part on small messages. 115 // Only run this part on small messages.
118 if (message.length < 1000) { 116 if (message.length < 1000) {
119 // Update the processor one byte at the time. 117 // Update the transformer one byte at the time.
120 messageCount++; 118 messageCount++;
121 for (int i = 0; i < frame.length; i++) { 119 for (int i = 0; i < frame.length; i++) {
122 processor.update(frame, i, 1); 120 controller.add(frame.getRange(i, 1));
123 } 121 }
124 Expect.equals(0, processor._state); 122 Expect.equals(0, transformer._state);
125 Expect.isNull(mc.data); 123 Expect.isNotNull(mc.data);
124 mc.data = null;
126 125
127 // Update the processor two bytes at the time. 126 // Update the transformer two bytes at the time.
128 messageCount++; 127 messageCount++;
129 for (int i = 0; i < frame.length; i += 2) { 128 for (int i = 0; i < frame.length; i += 2) {
130 processor.update(frame, i, i + 1 < frame.length ? 2 : 1); 129 controller.add(frame.getRange(i, i + 1 < frame.length ? 2 : 1));
131 } 130 }
132 Expect.equals(0, processor._state); 131 Expect.equals(0, transformer._state);
133 Expect.isNull(mc.data); 132 Expect.isNotNull(mc.data);
134 } 133 }
134 Expect.equals(messageCount, mc.messageCount);
135 Expect.equals(0, mc.closeCount);
136 print("Messages test, messages $messageCount");
135 } 137 }
136 138
137 void runTest(int from, int to, int step) { 139 void runTest(int from, int to, int step) {
138 for (int messageLength = from; messageLength < to; messageLength += step) { 140 for (int messageLength = from; messageLength < to; messageLength += step) {
139 List<int> message = new List<int>(messageLength); 141 List<int> message = new List<int>(messageLength);
140 for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF; 142 for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
141 testMessage(FRAME_OPCODE_TEXT, message); 143 testMessage(FRAME_OPCODE_TEXT, message);
142 testMessage(FRAME_OPCODE_BINARY, message); 144 testMessage(FRAME_OPCODE_BINARY, message);
143 } 145 }
144 } 146 }
145 147
146 // Test different message sizes. 148 // Test different message sizes.
147 runTest(0, 10, 1); 149 runTest(0, 10, 1);
148 runTest(120, 130, 1); 150 runTest(120, 130, 1);
149 runTest(0, 1000, 100); 151 runTest(0, 1000, 100);
150 runTest(65534, 65537, 1); 152 runTest(65534, 65537, 1);
151 print("Messages test, messages $messageCount");
152 Expect.equals(messageCount, mc.messageCount);
153 Expect.equals(0, mc.closeCount);
154 } 153 }
155 154
156 155
157 // Test processing of frames which are split into fragments. 156 // Test processing of frames which are split into fragments.
158 void testFragmentedMessages() { 157 void testFragmentedMessages() {
159 // Use the same web socket protocol processor for all frames. 158 // Use the same web socket protocol transformer for all frames.
160 _WebSocketProtocolProcessor processor = new _WebSocketProtocolProcessor(); 159 var transformer = new _WebSocketProtocolTransformer();
161 WebSocketMessageCollector mc = new WebSocketMessageCollector(processor); 160 var controller = new StreamController();
161 WebSocketMessageCollector mc = new WebSocketMessageCollector(
162 controller.stream.transform(transformer));
162 163
163 int messageCount = 0; 164 int messageCount = 0;
164 int frameCount = 0; 165 int frameCount = 0;
165 166
166 void testFragmentMessage(int opcode, List<int> message, int fragmentSize) { 167 void testFragmentMessage(int opcode, List<int> message, int fragmentSize) {
167 messageCount++; 168 messageCount++;
168 int messageIndex = 0; 169 int messageIndex = 0;
169 int remaining = message.length; 170 int remaining = message.length;
170 bool firstFrame = true; 171 bool firstFrame = true;
171 bool lastFrame = false; 172 bool lastFrame = false;
172 while (!lastFrame) { 173 while (!lastFrame) {
173 int payloadSize = min(fragmentSize, remaining); 174 int payloadSize = min(fragmentSize, remaining);
174 lastFrame = payloadSize == remaining; 175 lastFrame = payloadSize == remaining;
175 List<int> frame = createFrame(lastFrame, 176 List<int> frame = createFrame(lastFrame,
176 firstFrame ? opcode : 0x00, 177 firstFrame ? opcode : 0x00,
177 null, 178 null,
178 message, 179 message,
179 messageIndex, 180 messageIndex,
180 payloadSize); 181 payloadSize);
181 frameCount++; 182 frameCount++;
182 messageIndex += payloadSize; 183 messageIndex += payloadSize;
183 processor.update(frame, 0, frame.length); 184 controller.add(frame);
184 remaining -= payloadSize; 185 remaining -= payloadSize;
185 firstFrame = false; 186 firstFrame = false;
186 } 187 }
187 } 188 }
188 189
189 void testMessageFragmentation(int opcode, List<int> message) { 190 void testMessageFragmentation(int opcode, List<int> message) {
190 mc.expectedMessage = message; 191 mc.expectedMessage = message;
191 192
192 // Test with fragmenting the message in different fragment sizes. 193 // Test with fragmenting the message in different fragment sizes.
193 if (message.length <= 10) { 194 if (message.length <= 10) {
194 for (int i = 1; i < 10; i++) { 195 for (int i = 1; i < 10; i++) {
195 testFragmentMessage(opcode, message, i); 196 testFragmentMessage(opcode, message, i);
196 } 197 }
197 } else { 198 } else {
198 testFragmentMessage(opcode, message, 10); 199 testFragmentMessage(opcode, message, 10);
199 testFragmentMessage(opcode, message, 100); 200 testFragmentMessage(opcode, message, 100);
200 } 201 }
201 } 202 }
202 203
203 void runTest(int from, int to, int step) { 204 void runTest(int from, int to, int step) {
204 for (int messageLength = from; messageLength < to; messageLength += step) { 205 for (int messageLength = from; messageLength < to; messageLength += step) {
205 List<int> message = new List<int>(messageLength); 206 List<int> message = new List<int>(messageLength);
206 for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF; 207 for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F;
Søren Gjesse 2013/03/05 09:32:29 Maybe keep the FF for binary messages.
Anders Johnsen 2013/03/05 09:38:34 Done.
207 testMessageFragmentation(FRAME_OPCODE_TEXT, message); 208 testMessageFragmentation(FRAME_OPCODE_TEXT, message);
208 testMessageFragmentation(FRAME_OPCODE_BINARY, message); 209 testMessageFragmentation(FRAME_OPCODE_BINARY, message);
209 } 210 }
210 } 211 }
211 212
212 // Test different message sizes. 213 // Test different message sizes.
213 runTest(0, 10, 1); 214 runTest(0, 10, 1);
214 runTest(120, 130, 1); 215 runTest(120, 130, 1);
215 runTest(0, 1000, 100); 216 runTest(0, 1000, 100);
216 runTest(65534, 65537, 1); 217 runTest(65534, 65537, 1);
217 print("Fragment messages test, messages $messageCount, frames $frameCount"); 218 print("Fragment messages test, messages $messageCount, frames $frameCount");
218 Expect.equals(messageCount, mc.messageCount); 219 Expect.equals(messageCount, mc.messageCount);
219 Expect.equals(0, mc.closeCount); 220 Expect.equals(0, mc.closeCount);
220 } 221 }
221 222
222 void main() { 223 void main() {
223 testFullMessages(); 224 testFullMessages();
224 testFragmentedMessages(); 225 testFragmentedMessages();
225 } 226 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698