passenger 4.0.27 → 4.0.28

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (156) hide show
  1. data.tar.gz.asc +7 -7
  2. data/.gitignore +1 -0
  3. data/NEWS +22 -0
  4. data/build/preprocessor.rb +10 -0
  5. data/build/rpm.rb +74 -65
  6. data/debian.template/rules.template +8 -0
  7. data/dev/copy_boost_headers.rb +11 -2
  8. data/doc/Users guide Apache.idmap.txt +161 -145
  9. data/doc/Users guide Apache.txt +12 -1
  10. data/doc/Users guide Nginx.idmap.txt +142 -126
  11. data/doc/Users guide Nginx.txt +14 -1
  12. data/doc/Users guide Standalone.txt +1 -0
  13. data/doc/users_guide_snippets/environment_variables.txt +1 -1
  14. data/doc/users_guide_snippets/installation.txt +2 -0
  15. data/doc/users_guide_snippets/tips.txt +118 -0
  16. data/ext/apache2/Configuration.cpp +0 -6
  17. data/ext/apache2/Configuration.hpp +0 -5
  18. data/ext/apache2/ConfigurationCommands.cpp +7 -0
  19. data/ext/apache2/ConfigurationFields.hpp +2 -0
  20. data/ext/apache2/ConfigurationSetters.cpp +24 -0
  21. data/ext/apache2/CreateDirConfig.cpp +1 -0
  22. data/ext/apache2/Hooks.cpp +0 -1
  23. data/ext/apache2/MergeDirConfig.cpp +7 -0
  24. data/ext/apache2/SetHeaders.cpp +5 -1
  25. data/ext/boost/cregex.hpp +39 -0
  26. data/ext/boost/libs/regex/src/c_regex_traits.cpp +193 -0
  27. data/ext/boost/libs/regex/src/cpp_regex_traits.cpp +117 -0
  28. data/ext/boost/libs/regex/src/cregex.cpp +660 -0
  29. data/ext/boost/libs/regex/src/instances.cpp +32 -0
  30. data/ext/boost/libs/regex/src/internals.hpp +35 -0
  31. data/ext/boost/libs/regex/src/posix_api.cpp +296 -0
  32. data/ext/boost/libs/regex/src/regex.cpp +227 -0
  33. data/ext/boost/libs/regex/src/regex_debug.cpp +59 -0
  34. data/ext/boost/libs/regex/src/regex_raw_buffer.cpp +72 -0
  35. data/ext/boost/libs/regex/src/regex_traits_defaults.cpp +692 -0
  36. data/ext/boost/libs/regex/src/static_mutex.cpp +179 -0
  37. data/ext/boost/libs/regex/src/wc_regex_traits.cpp +301 -0
  38. data/ext/boost/libs/regex/src/wide_posix_api.cpp +315 -0
  39. data/ext/boost/libs/regex/src/winstances.cpp +35 -0
  40. data/ext/boost/regex.h +100 -0
  41. data/ext/boost/regex.hpp +37 -0
  42. data/ext/boost/regex/concepts.hpp +1128 -0
  43. data/ext/boost/regex/config.hpp +435 -0
  44. data/ext/boost/regex/config/borland.hpp +72 -0
  45. data/ext/boost/regex/config/cwchar.hpp +207 -0
  46. data/ext/boost/regex/mfc.hpp +190 -0
  47. data/ext/boost/regex/pattern_except.hpp +100 -0
  48. data/ext/boost/regex/pending/object_cache.hpp +165 -0
  49. data/ext/boost/regex/pending/static_mutex.hpp +179 -0
  50. data/ext/boost/regex/pending/unicode_iterator.hpp +776 -0
  51. data/ext/boost/regex/regex_traits.hpp +35 -0
  52. data/ext/boost/regex/user.hpp +93 -0
  53. data/ext/boost/regex/v4/basic_regex.hpp +782 -0
  54. data/ext/boost/regex/v4/basic_regex_creator.hpp +1571 -0
  55. data/ext/boost/regex/v4/basic_regex_parser.hpp +2874 -0
  56. data/ext/boost/regex/v4/c_regex_traits.hpp +211 -0
  57. data/ext/boost/regex/v4/char_regex_traits.hpp +81 -0
  58. data/ext/boost/regex/v4/cpp_regex_traits.hpp +1099 -0
  59. data/ext/boost/regex/v4/cregex.hpp +330 -0
  60. data/ext/boost/regex/v4/error_type.hpp +59 -0
  61. data/ext/boost/regex/v4/fileiter.hpp +455 -0
  62. data/ext/boost/regex/v4/instances.hpp +222 -0
  63. data/ext/boost/regex/v4/iterator_category.hpp +91 -0
  64. data/ext/boost/regex/v4/iterator_traits.hpp +135 -0
  65. data/ext/boost/regex/v4/match_flags.hpp +138 -0
  66. data/ext/boost/regex/v4/match_results.hpp +702 -0
  67. data/ext/boost/regex/v4/mem_block_cache.hpp +99 -0
  68. data/ext/boost/regex/v4/perl_matcher.hpp +587 -0
  69. data/ext/boost/regex/v4/perl_matcher_common.hpp +996 -0
  70. data/ext/boost/regex/v4/perl_matcher_non_recursive.hpp +1642 -0
  71. data/ext/boost/regex/v4/perl_matcher_recursive.hpp +991 -0
  72. data/ext/boost/regex/v4/primary_transform.hpp +146 -0
  73. data/ext/boost/regex/v4/protected_call.hpp +81 -0
  74. data/ext/boost/regex/v4/regbase.hpp +180 -0
  75. data/ext/boost/regex/v4/regex.hpp +202 -0
  76. data/ext/boost/regex/v4/regex_format.hpp +1156 -0
  77. data/ext/boost/regex/v4/regex_fwd.hpp +73 -0
  78. data/ext/boost/regex/v4/regex_grep.hpp +155 -0
  79. data/ext/boost/regex/v4/regex_iterator.hpp +201 -0
  80. data/ext/boost/regex/v4/regex_match.hpp +382 -0
  81. data/ext/boost/regex/v4/regex_merge.hpp +93 -0
  82. data/ext/boost/regex/v4/regex_raw_buffer.hpp +210 -0
  83. data/ext/boost/regex/v4/regex_replace.hpp +99 -0
  84. data/ext/boost/regex/v4/regex_search.hpp +217 -0
  85. data/ext/boost/regex/v4/regex_split.hpp +172 -0
  86. data/ext/boost/regex/v4/regex_token_iterator.hpp +342 -0
  87. data/ext/boost/regex/v4/regex_traits.hpp +189 -0
  88. data/ext/boost/regex/v4/regex_traits_defaults.hpp +371 -0
  89. data/ext/boost/regex/v4/regex_workaround.hpp +232 -0
  90. data/ext/boost/regex/v4/states.hpp +301 -0
  91. data/ext/boost/regex/v4/sub_match.hpp +512 -0
  92. data/ext/boost/regex/v4/syntax_type.hpp +105 -0
  93. data/ext/boost/regex/v4/u32regex_iterator.hpp +193 -0
  94. data/ext/boost/regex/v4/u32regex_token_iterator.hpp +377 -0
  95. data/ext/boost/regex/v4/w32_regex_traits.hpp +741 -0
  96. data/ext/boost/regex_fwd.hpp +33 -0
  97. data/ext/common/AgentsStarter.h +0 -11
  98. data/ext/common/ApplicationPool2/Common.h +1 -7
  99. data/ext/common/ApplicationPool2/DirectSpawner.h +3 -3
  100. data/ext/common/ApplicationPool2/Group.h +166 -69
  101. data/ext/common/ApplicationPool2/Implementation.cpp +55 -10
  102. data/ext/common/ApplicationPool2/Options.h +45 -10
  103. data/ext/common/ApplicationPool2/PipeWatcher.h +1 -2
  104. data/ext/common/ApplicationPool2/Pool.h +29 -7
  105. data/ext/common/ApplicationPool2/Process.h +22 -3
  106. data/ext/common/ApplicationPool2/Session.h +1 -0
  107. data/ext/common/ApplicationPool2/SmartSpawner.h +5 -10
  108. data/ext/common/ApplicationPool2/Spawner.h +10 -15
  109. data/ext/common/ApplicationPool2/SuperGroup.h +10 -9
  110. data/ext/common/Constants.h +1 -3
  111. data/ext/common/Hooks.h +193 -0
  112. data/ext/common/Logging.cpp +67 -2
  113. data/ext/common/Logging.h +23 -1
  114. data/ext/common/Utils.cpp +0 -21
  115. data/ext/common/Utils.h +0 -42
  116. data/ext/common/Utils/CachedFileStat.hpp +1 -1
  117. data/ext/common/Utils/StrIntUtils.h +61 -14
  118. data/ext/common/Utils/StringMap.h +4 -0
  119. data/ext/common/agents/HelperAgent/AgentOptions.h +4 -4
  120. data/ext/common/agents/HelperAgent/Main.cpp +2 -3
  121. data/ext/common/agents/HelperAgent/RequestHandler.h +65 -2
  122. data/ext/common/agents/LoggingAgent/FilterSupport.h +3 -1
  123. data/ext/common/agents/Watchdog/Main.cpp +8 -72
  124. data/ext/nginx/CacheLocationConfig.c +29 -1
  125. data/ext/nginx/Configuration.c +0 -12
  126. data/ext/nginx/Configuration.h +0 -1
  127. data/ext/nginx/ConfigurationCommands.c +10 -0
  128. data/ext/nginx/ConfigurationFields.h +2 -0
  129. data/ext/nginx/CreateLocationConfig.c +4 -0
  130. data/ext/nginx/MergeLocationConfig.c +6 -0
  131. data/ext/oxt/system_calls.cpp +7 -1
  132. data/ext/oxt/system_calls.hpp +7 -7
  133. data/helper-scripts/node-loader.js +6 -2
  134. data/helper-scripts/rack-loader.rb +5 -2
  135. data/helper-scripts/rack-preloader.rb +5 -2
  136. data/lib/phusion_passenger.rb +1 -1
  137. data/lib/phusion_passenger/apache2/config_options.rb +8 -0
  138. data/lib/phusion_passenger/constants.rb +0 -1
  139. data/lib/phusion_passenger/nginx/config_options.rb +9 -2
  140. data/lib/phusion_passenger/platform_info/apache.rb +2 -1
  141. data/lib/phusion_passenger/platform_info/compiler.rb +15 -1
  142. data/lib/phusion_passenger/platform_info/cxx_portability.rb +2 -0
  143. data/node_lib/phusion_passenger/httplib_emulation.js +85 -17
  144. data/node_lib/phusion_passenger/request_handler.js +10 -2
  145. data/rpm/Vagrantfile +32 -0
  146. data/rpm/get_distro_id.py +4 -0
  147. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +2 -2
  148. data/test/cxx/ApplicationPool2/PoolTest.cpp +60 -9
  149. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +2 -6
  150. data/test/cxx/CachedFileStatTest.cpp +5 -5
  151. data/test/cxx/RequestHandlerTest.cpp +3 -6
  152. data/test/cxx/UtilsTest.cpp +30 -0
  153. data/test/node/httplib_emulation_spec.js +491 -0
  154. data/test/node/spec_helper.js +25 -0
  155. metadata +78 -2
  156. metadata.gz.asc +7 -7
@@ -661,4 +661,34 @@ namespace tut {
661
661
  ensure("(13)", !constantTimeCompare("abc", "ab"));
662
662
  ensure("(14)", !constantTimeCompare("abcd", "ab"));
663
663
  }
664
+
665
+ /***** Test integerToOtherBase() *****/
666
+
667
+ TEST_METHOD(56) {
668
+ char buf[20], smallbuf[4];
669
+
670
+ ensure_equals("(1)", integerToOtherBase<int, 10>(0, buf, sizeof(buf)), 1u);
671
+ ensure_equals("(1.1)", buf[0], '0');
672
+ ensure_equals("(1.2)", buf[1], '\0');
673
+
674
+ ensure_equals("(2)", integerToOtherBase<int, 10>(1234, buf, sizeof(buf)), 4u);
675
+ ensure_equals("(2.1)", buf[0], '1');
676
+ ensure_equals("(2.2)", buf[1], '2');
677
+ ensure_equals("(2.3)", buf[2], '3');
678
+ ensure_equals("(2.4)", buf[3], '4');
679
+ ensure_equals("(2.5)", buf[4], '\0');
680
+
681
+ ensure_equals("(3)", integerToOtherBase<int, 10>(123, smallbuf, sizeof(smallbuf)), 3u);
682
+ ensure_equals("(3.1)", smallbuf[0], '1');
683
+ ensure_equals("(3.2)", smallbuf[1], '2');
684
+ ensure_equals("(3.3)", smallbuf[2], '3');
685
+ ensure_equals("(3.4)", smallbuf[3], '\0');
686
+
687
+ try {
688
+ integerToOtherBase<int, 10>(1234, smallbuf, sizeof(smallbuf));
689
+ fail("Exception expected");
690
+ } catch (const std::length_error &) {
691
+ // Pass.
692
+ }
693
+ }
664
694
  }
@@ -0,0 +1,491 @@
1
+ var Helper = require('./spec_helper').Helper;
2
+ var FakeStream = require('./spec_helper').FakeStream;
3
+ var should = require('should');
4
+ var assert = require('assert');
5
+ var net = require('net');
6
+ var HttplibEmulation = require('phusion_passenger/httplib_emulation');
7
+
8
+ /*
9
+ * Caveat:
10
+ * According to the Node.js source code, when a stream is set to flowing mode,
11
+ * it is supposed to set _readableState.flowing to true. Yet from empirical tests
12
+ * with http.Server, this does not happen. Neither on the IncomingMessage object,
13
+ * nor on the socket object. Therefore, in the flowing mode tests, we only check
14
+ * the flowing mode flag on the request object, not the socket.
15
+ */
16
+ describe('HttplibEmulation', function() {
17
+ this.timeout(1000);
18
+
19
+ beforeEach(function() {
20
+ var state = this.state = {};
21
+
22
+ state.createSocket = function(callback) {
23
+ if (state.server || state.client) {
24
+ throw new Error('createSocket() may only be called once');
25
+ }
26
+
27
+ var server = net.createServer();
28
+
29
+ function maybeDone() {
30
+ if (state.serverSocket && state.client) {
31
+ callback(state.serverSocket, state.client);
32
+ }
33
+ }
34
+
35
+ server.listen(0, '127.0.0.1', function() {
36
+ var client = new net.Socket();
37
+ client.once('connect', function() {
38
+ state.client = client;
39
+ maybeDone();
40
+ });
41
+ client.connect(server.address().port, '127.0.0.1');
42
+ });
43
+ server.once('connection', function(socket) {
44
+ state.server = server;
45
+ state.serverSocket = socket;
46
+ maybeDone();
47
+ });
48
+ }
49
+ });
50
+
51
+ afterEach(function(done) {
52
+ var state = this.state;
53
+ var events = 1;
54
+ var counter = 0;
55
+
56
+ function maybeDone() {
57
+ counter++;
58
+ if (counter == events) {
59
+ done();
60
+ }
61
+ }
62
+
63
+ if (state.server) {
64
+ events += 1;
65
+ state.server.close(maybeDone);
66
+ state.serverSocket.destroy();
67
+ }
68
+ if (state.client) {
69
+ state.client.destroy();
70
+ }
71
+ maybeDone();
72
+ });
73
+
74
+ function createHeaders(object) {
75
+ var key, keys = [];
76
+ var result = {
77
+ 'SERVER_PROTOCOL': 'HTTP/1.1',
78
+ 'REMOTE_ADDR': '127.0.0.1',
79
+ 'REMOTE_PORT': '3000',
80
+ 'REQUEST_METHOD': 'GET',
81
+ 'REQUEST_URI': '/',
82
+ 'PATH_INFO': '/'
83
+ };
84
+ for (key in object) {
85
+ result[key] = object[key];
86
+ }
87
+ for (key in result) {
88
+ keys.push(key);
89
+ }
90
+ result.keys = keys;
91
+ return result;
92
+ }
93
+
94
+ describe('if the request may have a request body', function() {
95
+ beforeEach(function() {
96
+ var state = this.state;
97
+ state.setup = function(headers, callback) {
98
+ if (!callback) {
99
+ callback = headers;
100
+ headers = {
101
+ 'REQUEST_METHOD': 'POST'
102
+ };
103
+ }
104
+ state.headers = createHeaders(headers);
105
+ state.createSocket(function(serverSocket, client) {
106
+ state.req = HttplibEmulation.createIncomingMessage(
107
+ state.headers, serverSocket, "");
108
+ assert.ok(state.req._mayHaveRequestBody);
109
+ callback();
110
+ });
111
+ }
112
+ });
113
+
114
+ it("isn't in flowing mode by default", function(done) {
115
+ var state = this.state;
116
+ state.setup(function() {
117
+ assert.strictEqual(state.req._flowing, undefined);
118
+ done();
119
+ });
120
+ });
121
+
122
+ it("is set to flowing mode upon calling pause", function(done) {
123
+ var state = this.state;
124
+ state.setup(function() {
125
+ state.req.pause();
126
+ assert.strictEqual(state.req._flowing, false);
127
+ done();
128
+ });
129
+ });
130
+
131
+ it("is set to flowing mode upon calling resume", function(done) {
132
+ var state = this.state;
133
+ state.setup(function() {
134
+ state.req.resume();
135
+ assert.strictEqual(state.req._flowing, true);
136
+ done();
137
+ });
138
+ });
139
+
140
+ it("is set to flowing mode upon attaching a data event handler", function(done) {
141
+ var state = this.state;
142
+ state.setup(function() {
143
+ var chunks = [];
144
+ state.req.on('data', function(chunk) {
145
+ chunks.push(chunk.toString('utf-8'));
146
+ });
147
+ assert.strictEqual(state.req._flowing, true);
148
+ state.client.write("hello");
149
+ Helper.eventually(100, function() {
150
+ return chunks.length > 0;
151
+ }, function() {
152
+ chunks.should.eql(['hello']);
153
+ done();
154
+ });
155
+ });
156
+ });
157
+
158
+ describe("when in flowing mode", function() {
159
+ beforeEach(function(done) {
160
+ var state = this.state;
161
+ state.setup(function() {
162
+ state.req.resume();
163
+ assert.ok(state.req._flowing);
164
+ done();
165
+ });
166
+ });
167
+
168
+ it("sends data events as data is received", function(done) {
169
+ var state = this.state;
170
+ var chunks = [];
171
+
172
+ state.req.on('data', function(chunk) {
173
+ chunks.push(chunk.toString('utf-8'));
174
+ });
175
+ state.client.write("hello");
176
+
177
+ Helper.eventually(100, function() {
178
+ return chunks.length > 0;
179
+ }, function() {
180
+ chunks.should.eql(["hello"]);
181
+ done();
182
+ });
183
+ });
184
+
185
+ it("sends the end event after the client closes the socket", function(done) {
186
+ var state = this.state;
187
+ var finished;
188
+
189
+ function endReachedPrematurely() {
190
+ assert.fail("end event received prematurely");
191
+ finished = true;
192
+ done();
193
+ }
194
+ state.req.once('end', endReachedPrematurely);
195
+
196
+ setTimeout(function() {
197
+ if (!finished) {
198
+ state.req.removeListener('end', endReachedPrematurely);
199
+ state.req.once('end', function() {
200
+ done();
201
+ });
202
+ state.client.destroy();
203
+ }
204
+ }, 50);
205
+ });
206
+ });
207
+
208
+ describe("when in non-flowing mode", function() {
209
+ beforeEach(function(done) {
210
+ var state = this.state;
211
+ state.setup(function() {
212
+ assert.ok(!state.req._flowing);
213
+ done();
214
+ });
215
+ });
216
+
217
+ it("emits readable events upon receiving data", function(done) {
218
+ var state = this.state;
219
+ var readable = 0;
220
+ state.req.on('readable', function() {
221
+ readable++;
222
+ });
223
+ setTimeout(function() {
224
+ state.client.write("hello");
225
+ Helper.eventually(100, function() {
226
+ return readable == 1;
227
+ }, done);
228
+ }, 50);
229
+ });
230
+
231
+ it("allows reading from the request object", function(done) {
232
+ var state = this.state;
233
+ state.client.write("hello");
234
+
235
+ setTimeout(function() {
236
+ var chunk = state.req.read(5);
237
+ assert.ok(!!chunk);
238
+ chunk.toString('utf-8').should.eql('hello');
239
+ done();
240
+ }, 50);
241
+ });
242
+
243
+ it("emits a readable event if data was already received before attaching the event listener", function(done) {
244
+ var state = this.state;
245
+ state.client.write("hello");
246
+
247
+ setTimeout(function() {
248
+ var readable = 0;
249
+ state.req.on('readable', function() {
250
+ readable++;
251
+ });
252
+ Helper.eventually(100, function() {
253
+ return readable == 1;
254
+ }, done);
255
+ }, 50);
256
+ });
257
+
258
+ it("pauses the socket data flow if the request buffer becomes too full", function(done) {
259
+ var state = this.state;
260
+ var i, buf;
261
+
262
+ state.client.write("hello");
263
+ buf = new Buffer(1024);
264
+ buf.fill("x");
265
+ for (i = 0; i < 1024; i++) {
266
+ state.client.write(buf);
267
+ }
268
+
269
+ setTimeout(function() {
270
+ var len = state.req._readableState.length;
271
+ assert.ok(len > 0);
272
+
273
+ buf = new Buffer(1024);
274
+ buf.fill("y");
275
+ for (i = 0; i < 1024; i++) {
276
+ state.client.write(buf);
277
+ }
278
+
279
+ setTimeout(function() {
280
+ state.req._readableState.length.should.equal(len);
281
+ var chunk = state.req.read(7);
282
+ assert.ok(!!chunk);
283
+ chunk.toString('utf-8').should.eql("helloxx");
284
+ done();
285
+ }, 100);
286
+ }, 100);
287
+ });
288
+
289
+ it("resumes the socket data flow if the request buffer's size drops to below the high water mark", function(done) {
290
+ var state = this.state;
291
+ var i, buf;
292
+
293
+ buf = new Buffer(1024);
294
+ buf.fill("x");
295
+ for (i = 0; i < 1024; i++) {
296
+ state.client.write(buf);
297
+ }
298
+
299
+ var len = 0;
300
+ var str = buf.slice(0, 512).toString('utf-8');
301
+ state.req.on('readable', function() {
302
+ var chunk;
303
+ while ((chunk = state.req.read(512)) !== null) {
304
+ chunk.toString('utf-8').should.eql(str);
305
+ len += chunk.length;
306
+ }
307
+ });
308
+ Helper.eventually(100, function() {
309
+ return len == 1024 * 1024;
310
+ }, done);
311
+ })
312
+
313
+ it("doesn't emit the end event if the request was never read from", function(done) {
314
+ var state = this.state;
315
+ var finished;
316
+ setTimeout(function() {
317
+ if (!finished) {
318
+ finished = true;
319
+ done();
320
+ }
321
+ }, 50);
322
+ state.req.on('end', function() {
323
+ if (!finished) {
324
+ finished = true;
325
+ assert.fail("unexpected end event");
326
+ }
327
+ });
328
+ });
329
+
330
+ it("emits the end event upon reaching the end of the request body", function(done) {
331
+ var state = this.state;
332
+ var i, buf;
333
+
334
+ state.client.write("hello");
335
+ buf = new Buffer(1024);
336
+ buf.fill("x");
337
+ for (i = 0; i < 1024; i++) {
338
+ state.client.write(buf);
339
+ }
340
+ state.client.end();
341
+
342
+ var len = 0;
343
+ state.req.on('readable', function() {
344
+ while ((buf = state.req.read(512)) !== null) {
345
+ len += buf.length;
346
+ }
347
+ });
348
+ state.req.on('end', function() {
349
+ len.should.equal(1024 * 1024);
350
+ done();
351
+ })
352
+ });
353
+
354
+ it("emits the end event when read() encounters EOF", function(done) {
355
+ var state = this.state;
356
+ var finished;
357
+ state.req.on('end', function() {
358
+ if (!finished) {
359
+ finished = true;
360
+ done();
361
+ }
362
+ });
363
+ state.client.end();
364
+ setTimeout(function() {
365
+ state.req.read(10);
366
+ }, 10);
367
+ });
368
+ });
369
+ });
370
+
371
+ describe("if the request doesn't have a request body", function() {
372
+ beforeEach(function() {
373
+ var state = this.state;
374
+ state.setup = function(headers, callback) {
375
+ if (!callback) {
376
+ callback = headers;
377
+ headers = {};
378
+ }
379
+ state.headers = createHeaders(headers);
380
+ state.createSocket(function(serverSocket, client) {
381
+ state.req = HttplibEmulation.createIncomingMessage(
382
+ state.headers, serverSocket, "");
383
+ assert.ok(!state.req._mayHaveRequestBody);
384
+ callback();
385
+ });
386
+ }
387
+ });
388
+
389
+ it("isn't in flowing mode by default", function(done) {
390
+ var state = this.state;
391
+ state.setup(function() {
392
+ assert.strictEqual(state.req._flowing, undefined);
393
+ done();
394
+ });
395
+ });
396
+
397
+ it("is set to flowing mode upon calling pause", function(done) {
398
+ var state = this.state;
399
+ state.setup(function() {
400
+ state.req.pause();
401
+ assert.strictEqual(state.req._flowing, false);
402
+ done();
403
+ });
404
+ });
405
+
406
+ it("is set to flowing mode upon calling resume", function(done) {
407
+ var state = this.state;
408
+ state.setup(function() {
409
+ state.req.resume();
410
+ assert.strictEqual(state.req._flowing, true);
411
+ done();
412
+ });
413
+ });
414
+
415
+ it("is set to flowing mode upon attaching a data event handler", function(done) {
416
+ var state = this.state;
417
+ state.setup(function() {
418
+ state.req.on('data', function(chunk) {});
419
+ assert.strictEqual(state.req._flowing, true);
420
+ done();
421
+ });
422
+ });
423
+
424
+ describe("when in flowing mode", function() {
425
+ beforeEach(function(done) {
426
+ var state = this.state;
427
+ state.setup(function() {
428
+ state.req.resume();
429
+ assert.ok(state.req._flowing);
430
+ done();
431
+ });
432
+ });
433
+
434
+ it("sends the end event immediately", function(done) {
435
+ var state = this.state;
436
+ var finished;
437
+ setTimeout(function() {
438
+ if (!finished) {
439
+ finished = true;
440
+ assert.fail("end event never sent");
441
+ }
442
+ }, 50);
443
+ state.req.on('end', function() {
444
+ if (!finished) {
445
+ finished = true;
446
+ done();
447
+ }
448
+ });
449
+ });
450
+ });
451
+
452
+ describe("when in non-flowing mode", function() {
453
+ beforeEach(function(done) {
454
+ var state = this.state;
455
+ state.setup(function() {
456
+ assert.ok(!state.req._flowing);
457
+ done();
458
+ });
459
+ });
460
+
461
+ it("doesn't send the end event if the request was never read from", function(done) {
462
+ var state = this.state;
463
+ var finished;
464
+ setTimeout(function() {
465
+ if (!finished) {
466
+ finished = true;
467
+ done();
468
+ }
469
+ }, 50);
470
+ state.req.on('end', function() {
471
+ if (!finished) {
472
+ finished = true;
473
+ assert.fail("unexpected end event");
474
+ }
475
+ });
476
+ });
477
+
478
+ it("sends the end event when read() encounters EOF", function(done) {
479
+ var state = this.state;
480
+ var finished;
481
+ state.req.on('end', function() {
482
+ if (!finished) {
483
+ finished = true;
484
+ done();
485
+ }
486
+ });
487
+ state.req.read(10);
488
+ });
489
+ });
490
+ });
491
+ });