passenger 3.0.8 → 3.0.9

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 (42) hide show
  1. data/NEWS +9 -0
  2. data/bin/passenger-install-nginx-module +1 -1
  3. data/build/basics.rb +0 -1
  4. data/build/cxx_tests.rb +5 -0
  5. data/build/rpm.rb +1 -1
  6. data/doc/Users guide Apache.html +1 -1
  7. data/doc/Users guide Nginx.html +1 -1
  8. data/ext/apache2/Configuration.cpp +12 -0
  9. data/ext/apache2/Configuration.hpp +12 -1
  10. data/ext/apache2/Hooks.cpp +2 -0
  11. data/ext/common/AgentsStarter.cpp +4 -0
  12. data/ext/common/AgentsStarter.h +2 -0
  13. data/ext/common/AgentsStarter.hpp +4 -0
  14. data/ext/common/Constants.h +1 -1
  15. data/ext/common/Logging.h +481 -261
  16. data/ext/common/LoggingAgent/LoggingServer.h +10 -4
  17. data/ext/common/LoggingAgent/Main.cpp +7 -2
  18. data/ext/common/LoggingAgent/RemoteSender.h +25 -3
  19. data/ext/common/MessageChannel.h +18 -227
  20. data/ext/common/MessageClient.h +95 -92
  21. data/ext/common/Utils/IOUtils.cpp +114 -1
  22. data/ext/common/Utils/IOUtils.h +57 -1
  23. data/ext/common/Utils/MessageIO.h +576 -0
  24. data/ext/nginx/Configuration.c +35 -0
  25. data/ext/nginx/Configuration.h +2 -0
  26. data/ext/nginx/ContentHandler.c +17 -6
  27. data/ext/nginx/ngx_http_passenger_module.c +8 -0
  28. data/lib/phusion_passenger.rb +2 -2
  29. data/lib/phusion_passenger/analytics_logger.rb +174 -117
  30. data/lib/phusion_passenger/app_process.rb +14 -2
  31. data/test/cxx/CxxTestMain.cpp +14 -19
  32. data/test/cxx/IOUtilsTest.cpp +68 -18
  33. data/test/cxx/LoggingTest.cpp +20 -24
  34. data/test/cxx/MessageChannelTest.cpp +1 -1
  35. data/test/cxx/MessageIOTest.cpp +310 -0
  36. data/test/cxx/TestSupport.cpp +47 -0
  37. data/test/cxx/TestSupport.h +8 -0
  38. data/test/ruby/analytics_logger_spec.rb +20 -28
  39. data/test/tut/tut.h +2 -0
  40. metadata +11 -11
  41. data/build/rdoctask.rb +0 -209
  42. data/test/cxx/HttpStatusExtractorTest.cpp +0 -198
@@ -70,7 +70,7 @@ class AppProcess
70
70
  return nil
71
71
  end
72
72
 
73
- search_results = Gem.cache.search(Gem::Dependency.new('rails', gem_version_spec), true)
73
+ search_results = search_gem('rails', gem_version_spec)
74
74
  found_version = search_results.map do |x|
75
75
  x.version.version
76
76
  end.sort.last
@@ -79,7 +79,7 @@ class AppProcess
79
79
  # date because the Rails version may have been installed now.
80
80
  # So we reload the RubyGems cache and try again.
81
81
  Gem.clear_paths
82
- search_results = Gem.cache.search(Gem::Dependency.new('rails', gem_version_spec), true)
82
+ search_results = search_gem('rails', gem_version_spec)
83
83
  found_version = search_results.map do |x|
84
84
  x.version.version
85
85
  end.sort.last
@@ -94,6 +94,18 @@ class AppProcess
94
94
  end
95
95
  end
96
96
 
97
+ def self.search_gem(gem_name, gem_version_spec)
98
+ if defined?(Gem::Specification) && Gem::Specification.respond_to?(:find_all_by_name)
99
+ return Gem::Specification.find_all_by_name(gem_name, gem_version_spec)
100
+ elsif Gem.respond_to?(:source_index)
101
+ dep = Gem::Dependency.new(gem_name, gem_version_spec)
102
+ return Gem.source_index.search(dep, true)
103
+ else
104
+ dep = Gem::Dependency.new(gem_name, gem_version_spec)
105
+ return Gem.cache.search(dep, true)
106
+ end
107
+ end
108
+
97
109
  # Construct an AppProcess by reading information from the given MessageChannel.
98
110
  # The other side of the channel must be writing AppProcess information using
99
111
  # AppProcess#write_to_channel.
@@ -98,25 +98,20 @@ main(int argc, char *argv[]) {
98
98
  allGroups = tut::runner.get().list_groups();
99
99
  parseOptions(argc, argv);
100
100
 
101
- try {
102
- bool all_ok = true;
103
- if (runMode == RUN_ALL_GROUPS) {
104
- tut::runner.get().run_tests();
105
- all_ok = reporter.all_ok();
106
- } else {
107
- all_ok = true;
108
- for (groupnames_iterator it = groupsToRun.begin(); it != groupsToRun.end(); it++) {
109
- tut::runner.get().run_tests(*it);
110
- all_ok = all_ok && reporter.all_ok();
111
- }
101
+ bool all_ok = true;
102
+ if (runMode == RUN_ALL_GROUPS) {
103
+ tut::runner.get().run_tests();
104
+ all_ok = reporter.all_ok();
105
+ } else {
106
+ all_ok = true;
107
+ for (groupnames_iterator it = groupsToRun.begin(); it != groupsToRun.end(); it++) {
108
+ tut::runner.get().run_tests(*it);
109
+ all_ok = all_ok && reporter.all_ok();
112
110
  }
113
- if (all_ok) {
114
- return 0;
115
- } else {
116
- return 1;
117
- }
118
- } catch (const std::exception &ex) {
119
- cerr << "*** Exception raised: " << ex.what() << endl;
120
- return 2;
111
+ }
112
+ if (all_ok) {
113
+ return 0;
114
+ } else {
115
+ return 1;
121
116
  }
122
117
  }
@@ -1,5 +1,6 @@
1
1
  #include "TestSupport.h"
2
- #include "Utils/IOUtils.h"
2
+ #include <Utils/IOUtils.h>
3
+ #include <Utils/SystemTime.h>
3
4
  #include <oxt/system_calls.hpp>
4
5
  #include <boost/bind.hpp>
5
6
  #include <sys/types.h>
@@ -54,23 +55,6 @@ namespace tut {
54
55
  return p;
55
56
  }
56
57
 
57
- void writeUntilFull(int fd) {
58
- char buf[1024 * 4];
59
- memset(buf, 0, sizeof(buf));
60
- bool done = false;
61
- while (!done) {
62
- ssize_t ret = write(fd, buf, sizeof(buf));
63
- if (ret == -1) {
64
- if (errno == EAGAIN) {
65
- done = true;
66
- } else {
67
- int e = errno;
68
- throw SystemException("Cannot write to pipe", e);
69
- }
70
- }
71
- }
72
- }
73
-
74
58
  static void writeDataAfterSomeTime(int fd, unsigned int sleepTimeInUsec) {
75
59
  try {
76
60
  syscalls::usleep(sleepTimeInUsec);
@@ -485,6 +469,25 @@ namespace tut {
485
469
  ensure_equals(writevData, "hellomyworld!!");
486
470
  }
487
471
 
472
+ TEST_METHOD(45) {
473
+ // Test writev() timeout support.
474
+ setWritevFunction(NULL);
475
+ Pipe p = createPipe();
476
+ unsigned long long startTime = SystemTime::getUsec();
477
+ unsigned long long timeout = 30000;
478
+ try {
479
+ StaticString data[] = { "hello", "world" };
480
+ for (int i = 0; i < 1024 * 1024; i++) {
481
+ gatheredWrite(p[1], data, 2, &timeout);
482
+ }
483
+ fail("TimeoutException expected");
484
+ } catch (const TimeoutException &) {
485
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
486
+ ensure("30 msec have passed", elapsed >= 29000 && elapsed <= 45000);
487
+ ensure(timeout <= 2000);
488
+ }
489
+ }
490
+
488
491
  /***** Test waitUntilReadable() *****/
489
492
 
490
493
  TEST_METHOD(50) {
@@ -793,4 +796,51 @@ namespace tut {
793
796
  // Pass.
794
797
  }
795
798
  }
799
+
800
+ /***** Test readFileDescriptor() and writeFileDescriptor() *****/
801
+
802
+ TEST_METHOD(80) {
803
+ // Test whether it works.
804
+ SocketPair sockets = createUnixSocketPair();
805
+ Pipe pipes = createPipe();
806
+ writeFileDescriptor(sockets[0], pipes[1]);
807
+ FileDescriptor fd = readFileDescriptor(sockets[1]);
808
+ writeExact(fd, "hello");
809
+ char buf[6];
810
+ ensure_equals(readExact(pipes[0], buf, 5), 5u);
811
+ buf[5] = '\0';
812
+ ensure_equals(StaticString(buf), "hello");
813
+ }
814
+
815
+ TEST_METHOD(81) {
816
+ // Test whether timeout works.
817
+ SocketPair sockets = createUnixSocketPair();
818
+ Pipe pipes = createPipe();
819
+
820
+ unsigned long long timeout = 30000;
821
+ unsigned long long startTime = SystemTime::getUsec();
822
+ try {
823
+ FileDescriptor fd = readFileDescriptor(sockets[0], &timeout);
824
+ fail("TimeoutException expected");
825
+ } catch (const TimeoutException &) {
826
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
827
+ ensure("readFileDescriptor() timed out after 30 msec",
828
+ elapsed >= 29000 && elapsed <= 45000);
829
+ ensure(timeout <= 2000);
830
+ }
831
+
832
+ writeUntilFull(sockets[0]);
833
+
834
+ startTime = SystemTime::getUsec();
835
+ timeout = 30000;
836
+ try {
837
+ writeFileDescriptor(sockets[0], pipes[0], &timeout);
838
+ fail("TimeoutException expected");
839
+ } catch (const TimeoutException &) {
840
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
841
+ ensure("writeFileDescriptor() timed out after 30 msec",
842
+ elapsed >= 29000 && elapsed <= 45000);
843
+ ensure(timeout <= 2000);
844
+ }
845
+ }
796
846
  }
@@ -152,7 +152,7 @@ namespace tut {
152
152
  log->getGroupName(), log->getCategory());
153
153
  log2->message("message 2");
154
154
  log2->flushToDiskAfterClose(true);
155
-
155
+
156
156
  log.reset();
157
157
  log2.reset();
158
158
 
@@ -268,24 +268,6 @@ namespace tut {
268
268
  ensure_equals(data, "localhost");
269
269
  }
270
270
 
271
- TEST_METHOD(10) {
272
- // newTransaction() reestablishes the connection to the logging
273
- // server if the logging server crashed and was restarted
274
- SystemTime::forceAll(TODAY);
275
-
276
- logger->newTransaction("foobar");
277
- stopLoggingServer();
278
- startLoggingServer();
279
-
280
- AnalyticsLogPtr log = logger->newTransaction("foobar");
281
- log->message("hello");
282
- log->flushToDiskAfterClose(true);
283
- log.reset();
284
-
285
- string data = readAll(loggingDir + "/1/" FOOBAR_LOCALHOST_PREFIX "/requests/2010/01/13/12/log.txt");
286
- ensure("(1)", data.find("hello\n") != string::npos);
287
- }
288
-
289
271
  TEST_METHOD(11) {
290
272
  // newTransaction() does not reconnect to the server for a short
291
273
  // period of time if connecting failed
@@ -305,22 +287,36 @@ namespace tut {
305
287
  }
306
288
 
307
289
  TEST_METHOD(12) {
308
- // continueTransaction() reestablishes the connection to the logging
309
- // server if the logging server crashed and was restarted
290
+ // If the logging server crashed and was restarted then
291
+ // newTransaction() and continueTransaction() print a warning and return
292
+ // a null log object. One of the next newTransaction()/continueTransaction()
293
+ // calls will reestablish the connection when the connection timeout
294
+ // has passed.
310
295
  SystemTime::forceAll(TODAY);
296
+ AnalyticsLogPtr log, log2;
311
297
 
312
- AnalyticsLogPtr log = logger->newTransaction("foobar");
298
+ log = logger->newTransaction("foobar");
313
299
  logger2->continueTransaction(log->getTxnId(), "foobar");
314
300
  stopLoggingServer();
315
301
  startLoggingServer();
316
302
 
317
- AnalyticsLogPtr log2 = logger2->continueTransaction(log->getTxnId(), "foobar");
303
+ log = logger->newTransaction("foobar");
304
+ ensure("(1)", log->isNull());
305
+ log2 = logger2->continueTransaction("some-id", "foobar");
306
+ ensure("(2)", log2->isNull());
307
+
308
+ SystemTime::forceAll(TODAY + 60000000);
309
+ log = logger->newTransaction("foobar");
310
+ ensure("(3)", !log->isNull());
311
+ log2 = logger2->continueTransaction(log->getTxnId(), "foobar");
312
+ ensure("(4)", !log2->isNull());
318
313
  log2->message("hello");
319
314
  log2->flushToDiskAfterClose(true);
315
+ log.reset();
320
316
  log2.reset();
321
317
 
322
318
  string data = readAll(loggingDir + "/1/" FOOBAR_LOCALHOST_PREFIX "/requests/2010/01/13/12/log.txt");
323
- ensure("(1)", data.find("hello\n") != string::npos);
319
+ ensure("(5)", data.find("hello\n") != string::npos);
324
320
  }
325
321
 
326
322
  TEST_METHOD(13) {
@@ -458,7 +458,7 @@ namespace tut {
458
458
  fail("TimeoutException expected");
459
459
  } catch (const TimeoutException &) {
460
460
  unsigned long long elapsed = timer.elapsed();
461
- ensure("Spent at least 35 msec waiting", elapsed >= 35);
461
+ ensure("Spent at least 35 msec waiting", elapsed >= 34);
462
462
  ensure("Spent at most 60 msec waiting", elapsed <= 60);
463
463
  ensure("The passed time is deducted from timeout", timeout < 5);
464
464
  }
@@ -0,0 +1,310 @@
1
+ #include "TestSupport.h"
2
+ #include <Utils/IOUtils.h>
3
+ #include <Utils/MessageIO.h>
4
+ #include <Utils/SystemTime.h>
5
+
6
+ using namespace Passenger;
7
+ using namespace std;
8
+ using namespace boost;
9
+
10
+ namespace tut {
11
+ struct MessageIOTest {
12
+ Pipe pipes;
13
+
14
+ MessageIOTest() {
15
+ pipes = createPipe();
16
+ }
17
+ };
18
+
19
+ DEFINE_TEST_GROUP(MessageIOTest);
20
+
21
+ /***** Test readUint16() and writeUint16() *****/
22
+
23
+ TEST_METHOD(1) {
24
+ // They work.
25
+ writeUint16(pipes[1], 0x3F56);
26
+ writeUint16(pipes[1], 0x3F57);
27
+ writeUint16(pipes[1], 0x3F58);
28
+
29
+ unsigned char buf[2];
30
+ ensure_equals(readExact(pipes[0], buf, 2), 2u);
31
+ ensure_equals(buf[0], 0x3F);
32
+ ensure_equals(buf[1], 0x56);
33
+
34
+ ensure_equals(readUint16(pipes[0]), 0x3F57u);
35
+
36
+ uint16_t out;
37
+ ensure(readUint16(pipes[0], out));
38
+ ensure_equals(out, 0x3F58);
39
+ }
40
+
41
+ TEST_METHOD(2) {
42
+ // readUint16() throws EOFException on premature EOF.
43
+ writeExact(pipes[1], "x", 1);
44
+ pipes[1].close();
45
+ try {
46
+ readUint16(pipes[0]);
47
+ fail("EOFException expected");
48
+ } catch (const EOFException &) {
49
+ }
50
+ }
51
+
52
+ TEST_METHOD(3) {
53
+ // readUint16(uint32_t &) returns false EOFException on premature EOF.
54
+ writeExact(pipes[1], "x", 1);
55
+ pipes[1].close();
56
+ uint16_t out;
57
+ ensure(!readUint16(pipes[0], out));
58
+ }
59
+
60
+ TEST_METHOD(4) {
61
+ // Test timeout.
62
+ unsigned long long timeout = 30000;
63
+ unsigned long long startTime = SystemTime::getUsec();
64
+ try {
65
+ readUint16(pipes[0], &timeout);
66
+ fail("TimeoutException expected");
67
+ } catch (const TimeoutException &) {
68
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
69
+ ensure("About 30 ms elapsed (1)", elapsed >= 29000 && elapsed <= 50000);
70
+ ensure("Time is correctly deducted from 'timeout' (1)", timeout <= 2000);
71
+ }
72
+
73
+ writeUntilFull(pipes[1]);
74
+
75
+ timeout = 30000;
76
+ startTime = SystemTime::getUsec();
77
+ try {
78
+ writeUint16(pipes[1], 0x12, &timeout);
79
+ fail("TimeoutException expected");
80
+ } catch (const TimeoutException &) {
81
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
82
+ ensure("About 30 ms elapsed (3)", elapsed >= 29000 && elapsed <= 50000);
83
+ ensure("Time is correctly deducted from 'timeout' (4)", timeout <= 2000);
84
+ }
85
+ }
86
+
87
+ /***** Test readUint32() and writeUint32() *****/
88
+
89
+ TEST_METHOD(10) {
90
+ // They work.
91
+ writeUint32(pipes[1], 0x12343F56);
92
+ writeUint32(pipes[1], 0x12343F57);
93
+ writeUint32(pipes[1], 0x12343F58);
94
+
95
+ unsigned char buf[4];
96
+ ensure_equals(readExact(pipes[0], buf, 4), 4u);
97
+ ensure_equals(buf[0], 0x12);
98
+ ensure_equals(buf[1], 0x34);
99
+ ensure_equals(buf[2], 0x3F);
100
+ ensure_equals(buf[3], 0x56);
101
+
102
+ ensure_equals(readUint32(pipes[0]), 0x12343F57u);
103
+
104
+ uint32_t out;
105
+ ensure(readUint32(pipes[0], out));
106
+ ensure_equals(out, 0x12343F58u);
107
+ }
108
+
109
+ TEST_METHOD(11) {
110
+ // readUint32() throws EOFException on premature EOF.
111
+ writeExact(pipes[1], "xyz", 3);
112
+ pipes[1].close();
113
+ try {
114
+ readUint32(pipes[0]);
115
+ fail("EOFException expected");
116
+ } catch (const EOFException &) {
117
+ }
118
+ }
119
+
120
+ TEST_METHOD(12) {
121
+ // readUint16(uint32_t &) returns false EOFException on premature EOF.
122
+ writeExact(pipes[1], "xyz", 3);
123
+ pipes[1].close();
124
+ uint32_t out;
125
+ ensure(!readUint32(pipes[0], out));
126
+ }
127
+
128
+ TEST_METHOD(13) {
129
+ // Test timeout.
130
+ unsigned long long timeout = 30000;
131
+ unsigned long long startTime = SystemTime::getUsec();
132
+ try {
133
+ readUint32(pipes[0], &timeout);
134
+ fail("TimeoutException expected");
135
+ } catch (const TimeoutException &) {
136
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
137
+ ensure(elapsed >= 29000 && elapsed <= 50000);
138
+ ensure(timeout <= 2000);
139
+ }
140
+
141
+ writeUntilFull(pipes[1]);
142
+
143
+ timeout = 30000;
144
+ startTime = SystemTime::getUsec();
145
+ try {
146
+ writeUint32(pipes[1], 0x1234, &timeout);
147
+ fail("TimeoutException expected");
148
+ } catch (const TimeoutException &) {
149
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
150
+ ensure(elapsed >= 29000 && elapsed <= 50000);
151
+ ensure(timeout <= 2000);
152
+ }
153
+ }
154
+
155
+ /***** Test readArrayMessage() and writeArrayMessage() *****/
156
+
157
+ TEST_METHOD(20) {
158
+ // They work.
159
+ writeArrayMessage(pipes[1], "ab", "cd", "efg", NULL);
160
+ writeArrayMessage(pipes[1], "ab", "cd", "efh", NULL);
161
+
162
+ unsigned char buf[12];
163
+ readExact(pipes[0], buf, 12);
164
+ ensure_equals(buf[0], 0u);
165
+ ensure_equals(buf[1], 10u);
166
+ ensure_equals(buf[2], 'a');
167
+ ensure_equals(buf[3], 'b');
168
+ ensure_equals(buf[4], '\0');
169
+ ensure_equals(buf[5], 'c');
170
+ ensure_equals(buf[6], 'd');
171
+ ensure_equals(buf[7], '\0');
172
+ ensure_equals(buf[8], 'e');
173
+ ensure_equals(buf[9], 'f');
174
+ ensure_equals(buf[10], 'g');
175
+ ensure_equals(buf[11], '\0');
176
+
177
+ vector<string> args = readArrayMessage(pipes[0]);
178
+ ensure_equals(args.size(), 3u);
179
+ ensure_equals(args[0], "ab");
180
+ ensure_equals(args[1], "cd");
181
+ ensure_equals(args[2], "efh");
182
+ }
183
+
184
+ TEST_METHOD(21) {
185
+ // readArrayMessage() throws EOFException on premature EOF.
186
+ writeExact(pipes[1], "\x00");
187
+ pipes[1].close();
188
+ try {
189
+ readArrayMessage(pipes[0]);
190
+ fail("EOFException expected (1)");
191
+ } catch (const EOFException &) {
192
+ }
193
+
194
+ pipes = createPipe();
195
+ writeExact(pipes[1], "\x00\x04a\x00b");
196
+ pipes[1].close();
197
+ try {
198
+ readArrayMessage(pipes[0]);
199
+ fail("EOFException expected (2)");
200
+ } catch (const EOFException &) {
201
+ }
202
+ }
203
+
204
+ TEST_METHOD(22) {
205
+ // Test timeout.
206
+ unsigned long long timeout = 30000;
207
+ unsigned long long startTime = SystemTime::getUsec();
208
+ try {
209
+ readArrayMessage(pipes[0], &timeout);
210
+ fail("TimeoutException expected (1)");
211
+ } catch (const TimeoutException &) {
212
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
213
+ ensure(elapsed >= 29000 && elapsed <= 50000);
214
+ ensure(timeout <= 2000);
215
+ }
216
+
217
+ writeUntilFull(pipes[1]);
218
+
219
+ timeout = 30000;
220
+ startTime = SystemTime::getUsec();
221
+ try {
222
+ writeArrayMessage(pipes[1], &timeout, "hi", "ho", NULL);
223
+ fail("TimeoutException expected (2)");
224
+ } catch (const TimeoutException &) {
225
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
226
+ ensure(elapsed >= 29000 && elapsed <= 50000);
227
+ ensure(timeout <= 2000);
228
+ }
229
+ }
230
+
231
+ /***** Test readArrayMessage() and writeArrayMessage() *****/
232
+
233
+ TEST_METHOD(30) {
234
+ // They work.
235
+ writeScalarMessage(pipes[1], "hello");
236
+ writeScalarMessage(pipes[1], "world");
237
+
238
+ unsigned char buf[4 + 5];
239
+ readExact(pipes[0], buf, 4 + 5);
240
+ ensure_equals(buf[0], 0u);
241
+ ensure_equals(buf[1], 0u);
242
+ ensure_equals(buf[2], 0u);
243
+ ensure_equals(buf[3], 5u);
244
+ ensure_equals(buf[4], 'h');
245
+ ensure_equals(buf[5], 'e');
246
+ ensure_equals(buf[6], 'l');
247
+ ensure_equals(buf[7], 'l');
248
+ ensure_equals(buf[8], 'o');
249
+
250
+ ensure_equals(readScalarMessage(pipes[0]), "world");
251
+ }
252
+
253
+ TEST_METHOD(31) {
254
+ // readScalarMessage() throws EOFException on premature EOF.
255
+ writeExact(pipes[1], StaticString("\x00", 1));
256
+ pipes[1].close();
257
+ try {
258
+ readScalarMessage(pipes[0]);
259
+ fail("EOFException expected (1)");
260
+ } catch (const EOFException &) {
261
+ }
262
+
263
+ pipes = createPipe();
264
+ writeExact(pipes[1], StaticString("\x00\x00\x00\x04" "abc", 4 + 3));
265
+ pipes[1].close();
266
+ try {
267
+ readScalarMessage(pipes[0]);
268
+ fail("EOFException expected (2)");
269
+ } catch (const EOFException &) {
270
+ }
271
+ }
272
+
273
+ TEST_METHOD(32) {
274
+ // readScalarMessage() throws SecurityException if the
275
+ // body larger than the limit
276
+ writeExact(pipes[1], StaticString("\x00\x00\x00\x05", 4));
277
+ try {
278
+ readScalarMessage(pipes[0], 4);
279
+ fail("SecurityException expected (1)");
280
+ } catch (const SecurityException &) {
281
+ }
282
+ }
283
+
284
+ TEST_METHOD(33) {
285
+ // Test timeout.
286
+ unsigned long long timeout = 30000;
287
+ unsigned long long startTime = SystemTime::getUsec();
288
+ try {
289
+ readScalarMessage(pipes[0], 0, &timeout);
290
+ fail("TimeoutException expected (1)");
291
+ } catch (const TimeoutException &) {
292
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
293
+ ensure(elapsed >= 29000 && elapsed <= 50000);
294
+ ensure(timeout <= 2000);
295
+ }
296
+
297
+ writeUntilFull(pipes[1]);
298
+
299
+ timeout = 30000;
300
+ startTime = SystemTime::getUsec();
301
+ try {
302
+ writeScalarMessage(pipes[1], "hello", &timeout);
303
+ fail("TimeoutException expected (2)");
304
+ } catch (const TimeoutException &) {
305
+ unsigned long long elapsed = SystemTime::getUsec() - startTime;
306
+ ensure(elapsed >= 29000 && elapsed <= 50000);
307
+ ensure(timeout <= 2000);
308
+ }
309
+ }
310
+ }