public
Description: Phusion Passenger (mod_rails)
Homepage: http://www.modrails.com/
Clone URL: git://github.com/FooBarWidget/passenger.git
Search Repo:
Click here to lend your support to: passenger and make a donation at www.pledgie.com !
- Make DummyRequestHandler faster.
- DummySpawnManager now checks for errors.
- Update the Makefile and add more dependency information.
- Improve documentation.
- Add tests for ApplicationPool. These set of tests will test both 
StandardApplicationPool as well as ApplicationPoolServer.
- Add empty test methods which are to be written later.
FooBarWidget (author)
Sun Feb 03 08:50:28 -0800 2008
commit  b39e6c012f6a10af78e61068b2367e74271fc975
tree    c9e66e833b564f3d0e47e565cc9e18a8a90631cf
parent  08b64503a7c50e84332abc4e7111ecaa3fff2f03
...
15
16
17
18
 
 
 
19
20
21
22
...
25
26
27
28
29
 
 
 
30
31
32
 
33
34
35
...
15
16
17
 
18
19
20
21
22
23
24
...
27
28
29
 
 
30
31
32
33
 
 
34
35
36
37
0
@@ -15,7 +15,9 @@
0
   }
0
   P_TRACE("Done reading request headers");
0
   
0
- string content("<b>Using C++ DummyRequestHandler</b><br>\n");
0
+ string content;
0
+ content.reserve(1024 * 7);
0
+ content += "<b>Using C++ DummyRequestHandler</b><br>\n";
0
   unsigned int i;
0
   for (i = 0; i < headers.size(); i += 2) {
0
     content += "<tt>";
0
0
@@ -25,11 +27,11 @@
0
     content += "</tt><br>\n";
0
   }
0
   
0
- string header(
0
- "Status: 200 OK\r\n"
0
+ string header;
0
+ header.reserve(512);
0
+ header += "Status: 200 OK\r\n"
0
     "Content-Type: text/html\r\n"
0
- "Content-Length: "
0
- );
0
+ "Content-Length: ";
0
   header += toString(content.size());
0
   header += "\r\n\r\n";
0
   P_TRACE("Sending response header");
...
7
8
9
 
10
 
11
12
 
13
14
15
...
34
35
36
37
38
 
 
 
 
 
 
 
 
39
40
41
42
43
...
47
48
49
 
 
 
50
 
 
 
 
51
52
53
 
 
 
 
 
 
54
55
56
...
7
8
9
10
11
12
13
14
15
16
17
18
...
37
38
39
 
 
40
41
42
43
44
45
46
47
48
49
50
51
52
...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
0
@@ -7,9 +7,12 @@
0
 
0
 #include <sys/types.h>
0
 #include <sys/wait.h>
0
+#include <cstdio>
0
 #include <unistd.h>
0
+#include <errno.h>
0
 
0
 #include "Application.h"
0
+#include "Exceptions.h"
0
 
0
 namespace Passenger {
0
 
0
@@ -34,8 +37,14 @@
0
     int fd1[2], fd2[2];
0
     pid_t pid;
0
     
0
- pipe(fd1);
0
- pipe(fd2);
0
+ if (pipe(fd1) == -1) {
0
+ throw SystemException("Cannot create a pipe", errno);
0
+ }
0
+ if (pipe(fd2) == -1) {
0
+ close(fd1[0]);
0
+ close(fd1[1]);
0
+ throw SystemException("Cannot create a pipe", errno);
0
+ }
0
     pid = fork();
0
     if (pid == 0) {
0
       pid = fork();
0
0
0
@@ -47,10 +56,23 @@
0
         close(fd2[0]);
0
         close(fd2[1]);
0
         execlp(DUMMY_REQUEST_HANDLER_EXECUTABLE, DUMMY_REQUEST_HANDLER_EXECUTABLE, NULL);
0
+ int e = errno;
0
+ fprintf(stderr, "Unable to run %s: %s\n", DUMMY_REQUEST_HANDLER_EXECUTABLE, strerror(e));
0
+ fflush(stderr);
0
         _exit(1);
0
+ } else if (pid == -1) {
0
+ perror("Cannot fork a new process");
0
+ fflush(stderr);
0
+ _exit(1);
0
       } else {
0
         _exit(0);
0
       }
0
+ } else if (pid == -1) {
0
+ close(fd1[0]);
0
+ close(fd1[1]);
0
+ close(fd2[0]);
0
+ close(fd2[1]);
0
+ throw SystemException("Cannot fork a new process", errno);
0
     } else {
0
       int reader, writer;
0
       
...
19
20
21
22
 
23
24
25
...
19
20
21
 
22
23
24
25
0
@@ -19,7 +19,7 @@
0
 Hooks.o: Hooks.cpp Hooks.h Types.h DispatcherBucket.h ApplicationPool.h ApplicationPoolClientServer.h SpawnManager.h Exceptions.h Application.h MessageChannel.h Utils.h
0
   $(CXX) $(CXXFLAGS) -c Hooks.cpp
0
 
0
-DispatcherBucket.o: DispatcherBucket.h DispatcherBucket.cpp Utils.h.h
0
+DispatcherBucket.o: DispatcherBucket.h DispatcherBucket.cpp Utils.h Application.h
0
   $(CXX) $(CXXFLAGS) -c DispatcherBucket.cpp
0
 
0
 Utils.o: Utils.cpp Utils.h
...
123
124
125
 
126
 
127
128
129
...
164
165
166
 
167
168
169
170
...
183
184
185
 
 
 
 
 
 
186
187
188
189
 
 
 
 
 
 
 
 
190
191
192
...
123
124
125
126
127
128
129
130
131
...
166
167
168
169
170
171
172
173
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
0
@@ -123,7 +123,9 @@
0
    * Send an array message, which consists of the given elements, over the underlying
0
    * file descriptor.
0
    *
0
+ * @param args The message elements.
0
    * @throws SystemException An error occured while writing the data to the file descriptor.
0
+ * @pre None of the message elements may contain a NUL character ('\0').
0
    */
0
   void write(const list<string> &args) {
0
     list<string>::const_iterator it;
0
@@ -164,6 +166,7 @@
0
    * @param ... Other elements of the message. These *must* be strings, i.e. of type char*.
0
    * It is also required to terminate this list with a NULL.
0
    * @throws SystemException An error occured while writing the data to the file descriptor.
0
+ * @pre None of the message elements may contain a NUL character ('\0').
0
    */
0
   void write(const char *name, ...) {
0
     list<string> args;
0
0
@@ -183,10 +186,24 @@
0
     write(args);
0
   }
0
   
0
+ /**
0
+ * Send a scalar message over the underlying file descriptor.
0
+ *
0
+ * @param str The scalar message's content.
0
+ * @throws SystemException An error occured while writing the data to the file descriptor.
0
+ */
0
   void writeScalar(const string &str) {
0
     writeScalar(str.c_str(), str.size());
0
   }
0
   
0
+ /**
0
+ * Send a scalar message over the underlying file descriptor.
0
+ *
0
+ * @param data The scalar message's content.
0
+ * @param size The number of bytes in <tt>data</tt>.
0
+ * @pre <tt>data != NULL</tt>
0
+ * @throws SystemException An error occured while writing the data to the file descriptor.
0
+ */
0
   void writeScalar(const char *data, unsigned short size) {
0
     writeLength(size);
0
     
...
120
121
122
 
123
124
125
...
120
121
122
123
124
125
126
0
@@ -120,6 +120,7 @@
0
       execlp(rubyCommand.c_str(), rubyCommand.c_str(), spawnServerCommand.c_str(), NULL);
0
       int e = errno;
0
       fprintf(stderr, "Unable to run %s: %s\n", rubyCommand.c_str(), strerror(e));
0
+ fflush(stderr);
0
       _exit(1);
0
     } else if (pid == -1) {
0
       int e = errno;
...
1
2
3
 
4
5
6
7
...
9
10
11
 
12
13
14
15
 
16
17
18
...
20
21
22
 
 
 
23
24
25
...
41
42
43
 
44
45
46
47
...
81
82
83
 
 
 
84
 
 
 
 
85
...
1
2
 
3
4
5
6
7
...
9
10
11
12
13
14
15
16
17
18
19
20
...
22
23
24
25
26
27
28
29
30
...
46
47
48
49
50
51
52
53
...
87
88
89
90
91
92
93
94
95
96
97
98
0
@@ -1,6 +1,6 @@
0
 #include "tut.h"
0
 #include "ApplicationPoolClientServer.h"
0
-#include "Utils.cpp"
0
+#include "Utils.h"
0
 #include <cstring>
0
 #include <unistd.h>
0
 #include <errno.h>
0
0
@@ -9,10 +9,12 @@
0
 
0
 namespace tut {
0
   static bool firstRun = true;
0
+ static bool timeToTestThePoolItself = false;
0
   static unsigned int initialFileDescriptors;
0
 
0
   struct ApplicationPoolClientServerTest {
0
     ApplicationPoolServerPtr server;
0
+ ApplicationPoolPtr pool;
0
     
0
     ApplicationPoolClientServerTest() {
0
       if (firstRun) {
0
@@ -20,6 +22,9 @@
0
         firstRun = false;
0
       }
0
       server = ptr(new ApplicationPoolServer("support/spawn_server_mock.rb"));
0
+ if (timeToTestThePoolItself) {
0
+ pool = server->connect();
0
+ }
0
     }
0
     
0
     unsigned int countOpenFileDescriptors() {
0
@@ -41,6 +46,7 @@
0
 
0
   TEST_METHOD(1) {
0
     // Constructor and destructor should not crash.
0
+ // (And yes, this test method is intended to be blank.)
0
   }
0
   
0
   TEST_METHOD(2) {
0
0
@@ -81,6 +87,13 @@
0
     // of the above tests.
0
     server = ApplicationPoolServerPtr();
0
     ensure_equals(countOpenFileDescriptors(), initialFileDescriptors);
0
+
0
+ // A flag for the test methods in ApplicationPoolTestTemplate.cpp
0
+ timeToTestThePoolItself = true;
0
   }
0
+
0
+ #define APPLICATION_POOL_TEST_START 5
0
+ #define USE_TEMPLATE
0
+ #include "ApplicationPoolTestTemplate.cpp"
0
 }
...
1
2
3
4
 
 
5
6
7
8
...
20
21
22
23
 
24
 
 
 
25
26
27
...
1
2
3
 
4
5
6
7
8
9
...
21
22
23
 
24
25
26
27
28
29
30
31
0
@@ -1,7 +1,8 @@
0
 CXX=g++
0
 CXXFLAGS=-Isupport -DVALGRIND_FRIENDLY -g -Wall `pkg-config --cflags apr-1 apr-util-1`
0
 AP2_FLAGS=-I../ext/apache2
0
-AP2_OBJECTS=CxxTestMain.o MessageChannelTest.o SpawnManagerTest.o ApplicationPoolClientServerTest.o
0
+AP2_OBJECTS=CxxTestMain.o MessageChannelTest.o SpawnManagerTest.o ApplicationPoolClientServerTest.o \
0
+ StandardApplicationPoolTest.o
0
 
0
 .PHONY: test_all clean
0
 
0
0
@@ -20,8 +21,11 @@
0
 SpawnManagerTest.o: SpawnManagerTest.cpp ../ext/apache2/SpawnManager.h
0
   $(CXX) $(CXXFLAGS) $(AP2_FLAGS) -c SpawnManagerTest.cpp
0
 
0
-ApplicationPoolClientServerTest.o: ApplicationPoolClientServerTest.cpp .cpp ../ext/apache2/ApplicationPoolClientServer.h
0
+ApplicationPoolClientServerTest.o: ApplicationPoolClientServerTest.cpp ApplicationPoolTestTemplate.cpp ../ext/apache2/ApplicationPoolClientServer.h
0
   $(CXX) $(CXXFLAGS) $(AP2_FLAGS) -c ApplicationPoolClientServerTest.cpp
0
+
0
+StandardApplicationPoolTest.o: StandardApplicationPoolTest.cpp ApplicationPoolTestTemplate.cpp ../ext/apache2/ApplicationPool.h
0
+ $(CXX) $(CXXFLAGS) $(AP2_FLAGS) -c StandardApplicationPoolTest.cpp
0
 
0
 clean:
0
   rm -f Apache2ModuleTests *.o
...
71
72
73
 
74
75
76
77
...
121
122
123
124
125
126
127
128
129
 
 
 
 
 
130
131
132
...
161
162
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
165
...
71
72
73
74
75
76
77
78
...
122
123
124
 
 
 
 
125
126
127
128
129
130
131
132
133
134
...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
0
@@ -71,6 +71,7 @@
0
   
0
   TEST_METHOD(4) {
0
     // read() should be able to read messages constructed by the Ruby implementation.
0
+ // write() should be able to construct messages that can be read by the Ruby implementation.
0
     // Multiple read() and write() calls should work (i.e. the MessageChannel should have stream properties).
0
     int p1[2], p2[2];
0
     pid_t pid;
0
0
@@ -121,12 +122,13 @@
0
     }
0
   }
0
   
0
- TEST_METHOD(5) {
0
- // write() should be able to construct messages that can be read by the Ruby implementation.
0
- }
0
-
0
   TEST_METHOD(6) {
0
     // write(name) should generate a correct message even if there are no additional arguments.
0
+ writer.write("hello", NULL);
0
+ vector<string> args;
0
+ reader.read(args);
0
+ ensure_equals(args.size(), 1u);
0
+ ensure_equals(args[0], "hello");
0
   }
0
   
0
   TEST_METHOD(7) {
0
@@ -161,6 +163,24 @@
0
     reader.read(args);
0
     ensure_equals(args.size(), 1u);
0
     ensure_equals(args[0], "");
0
+ }
0
+
0
+ TEST_METHOD(9) {
0
+ // TODO:
0
+ // readScalar() should be able to read messages constructed by writeScalar().
0
+ }
0
+
0
+ TEST_METHOD(10) {
0
+ // TODO:
0
+ // writeScalar() should be able to produce messages that are compatible with the Ruby implementation.
0
+ // readScalar() should be able to read messages produced by the Ruby implementation.
0
+ }
0
+
0
+ TEST_METHOD(11) {
0
+ // TODO:
0
+ // If we send a lot of different messages (including file descriptor passing),
0
+ // and the other side sends the same stuff back to us, then MessageChannel
0
+ // should be able to read them all, if done in the correct order.
0
   }
0
 }

Comments

    No one has commented yet.