passenger 2.1.3 → 2.2.0

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 (398) hide show
  1. data/DEVELOPERS.TXT +2 -0
  2. data/INSTALL +3 -1
  3. data/LICENSE +19 -355
  4. data/NEWS +3 -0
  5. data/README +11 -4
  6. data/Rakefile +435 -236
  7. data/bin/passenger-config +20 -14
  8. data/bin/passenger-install-apache2-module +67 -201
  9. data/bin/passenger-install-nginx-module +477 -0
  10. data/bin/passenger-make-enterprisey +17 -12
  11. data/bin/passenger-memory-stats +33 -23
  12. data/bin/passenger-spawn-server +17 -12
  13. data/bin/passenger-status +18 -13
  14. data/bin/passenger-stress-test +17 -12
  15. data/doc/{Users guide.html → Users guide Apache.html } +79 -61
  16. data/doc/{Users guide.txt → Users guide Apache.txt } +43 -939
  17. data/doc/Users guide Nginx.html +2276 -0
  18. data/doc/Users guide Nginx.txt +776 -0
  19. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +9 -4
  20. data/doc/cxxapi/ApplicationPool_8h-source.html +9 -4
  21. data/doc/cxxapi/Application_8h-source.html +26 -21
  22. data/doc/cxxapi/Bucket_8h-source.html +54 -44
  23. data/doc/cxxapi/CachedFileStat_8h-source.html +9 -4
  24. data/doc/cxxapi/Configuration_8h-source.html +357 -339
  25. data/doc/cxxapi/DirectoryMapper_8h-source.html +294 -280
  26. data/doc/cxxapi/DummySpawnManager_8h-source.html +9 -4
  27. data/doc/cxxapi/Exceptions_8h-source.html +9 -4
  28. data/doc/cxxapi/FileChecker_8h-source.html +9 -4
  29. data/doc/cxxapi/Hooks_8h-source.html +50 -40
  30. data/doc/cxxapi/Logging_8h-source.html +9 -4
  31. data/doc/cxxapi/MessageChannel_8h-source.html +20 -15
  32. data/doc/cxxapi/PoolOptions_8h-source.html +10 -5
  33. data/doc/cxxapi/SpawnManager_8h-source.html +9 -4
  34. data/doc/cxxapi/StandardApplicationPool_8h-source.html +10 -5
  35. data/doc/cxxapi/SystemTime_8h-source.html +9 -4
  36. data/doc/cxxapi/Utils_8h-source.html +242 -214
  37. data/doc/cxxapi/annotated.html +4 -28
  38. data/doc/cxxapi/classClient-members.html +4 -4
  39. data/doc/cxxapi/classClient.html +14 -11
  40. data/doc/cxxapi/classHooks-members.html +4 -5
  41. data/doc/cxxapi/classHooks.html +26 -24
  42. data/doc/cxxapi/classPassenger_1_1Application-members.html +4 -4
  43. data/doc/cxxapi/classPassenger_1_1Application.html +40 -37
  44. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +4 -4
  45. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +95 -92
  46. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +4 -4
  47. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +26 -23
  48. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.map +1 -1
  49. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.md5 +1 -1
  50. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  51. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +17 -17
  52. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +139 -136
  53. data/doc/cxxapi/classPassenger_1_1BufferedUpload-members.html +4 -4
  54. data/doc/cxxapi/classPassenger_1_1BufferedUpload.html +13 -10
  55. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +4 -4
  56. data/doc/cxxapi/classPassenger_1_1BusyException.html +11 -8
  57. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +4 -4
  58. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +11 -8
  59. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +4 -5
  60. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +45 -43
  61. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +4 -4
  62. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +13 -10
  63. data/doc/cxxapi/classPassenger_1_1FileChecker-members.html +4 -4
  64. data/doc/cxxapi/classPassenger_1_1FileChecker.html +22 -19
  65. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +4 -4
  66. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +12 -9
  67. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.map +1 -1
  68. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.md5 +1 -1
  69. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  70. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +4 -4
  71. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +14 -11
  72. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.map +1 -1
  73. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.md5 +1 -1
  74. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  75. data/doc/cxxapi/classPassenger_1_1IOException-members.html +4 -4
  76. data/doc/cxxapi/classPassenger_1_1IOException.html +12 -9
  77. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.map +1 -1
  78. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.md5 +1 -1
  79. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  80. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +4 -4
  81. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +228 -225
  82. data/doc/cxxapi/classPassenger_1_1RuntimeException-members.html +4 -4
  83. data/doc/cxxapi/classPassenger_1_1RuntimeException.html +11 -8
  84. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +4 -4
  85. data/doc/cxxapi/classPassenger_1_1SpawnException.html +14 -11
  86. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +4 -4
  87. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +50 -47
  88. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +4 -4
  89. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +73 -70
  90. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.map +1 -1
  91. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.md5 +1 -1
  92. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  93. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +4 -4
  94. data/doc/cxxapi/classPassenger_1_1SystemException.html +17 -14
  95. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.map +1 -1
  96. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.md5 +1 -1
  97. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  98. data/doc/cxxapi/classPassenger_1_1SystemTime-members.html +4 -4
  99. data/doc/cxxapi/classPassenger_1_1SystemTime.html +14 -11
  100. data/doc/cxxapi/classes.html +35 -0
  101. data/doc/cxxapi/definitions_8h-source.html +9 -4
  102. data/doc/cxxapi/doxygen.css +311 -303
  103. data/doc/cxxapi/files.html +9 -18
  104. data/doc/cxxapi/functions.html +5 -224
  105. data/doc/cxxapi/functions_func.html +5 -185
  106. data/doc/cxxapi/functions_type.html +4 -4
  107. data/doc/cxxapi/functions_vars.html +4 -4
  108. data/doc/cxxapi/graph_legend.dot +19 -19
  109. data/doc/cxxapi/graph_legend.html +5 -5
  110. data/doc/cxxapi/graph_legend.png +0 -0
  111. data/doc/cxxapi/group__Configuration.html +11 -13
  112. data/doc/cxxapi/group__Configuration.png +0 -0
  113. data/doc/cxxapi/group__Core.html +10 -12
  114. data/doc/cxxapi/group__Core.png +0 -0
  115. data/doc/cxxapi/group__Exceptions.html +5 -7
  116. data/doc/cxxapi/group__Hooks.html +5 -7
  117. data/doc/cxxapi/group__Hooks.png +0 -0
  118. data/doc/cxxapi/group__Support.html +5 -624
  119. data/doc/cxxapi/hierarchy.html +6 -6
  120. data/doc/cxxapi/inherit__graph__0.map +1 -1
  121. data/doc/cxxapi/inherit__graph__0.md5 +1 -1
  122. data/doc/cxxapi/inherit__graph__0.png +0 -0
  123. data/doc/cxxapi/inherit__graph__1.map +1 -1
  124. data/doc/cxxapi/inherit__graph__1.md5 +1 -1
  125. data/doc/cxxapi/inherit__graph__1.png +0 -0
  126. data/doc/cxxapi/inherit__graph__10.map +1 -1
  127. data/doc/cxxapi/inherit__graph__10.md5 +1 -1
  128. data/doc/cxxapi/inherit__graph__10.png +0 -0
  129. data/doc/cxxapi/inherit__graph__11.map +1 -1
  130. data/doc/cxxapi/inherit__graph__11.md5 +1 -1
  131. data/doc/cxxapi/inherit__graph__11.png +0 -0
  132. data/doc/cxxapi/inherit__graph__12.map +1 -1
  133. data/doc/cxxapi/inherit__graph__12.md5 +1 -1
  134. data/doc/cxxapi/inherit__graph__12.png +0 -0
  135. data/doc/cxxapi/inherit__graph__13.map +1 -2
  136. data/doc/cxxapi/inherit__graph__13.md5 +1 -1
  137. data/doc/cxxapi/inherit__graph__13.png +0 -0
  138. data/doc/cxxapi/inherit__graph__14.map +2 -1
  139. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  140. data/doc/cxxapi/inherit__graph__14.png +0 -0
  141. data/doc/cxxapi/inherit__graph__15.map +1 -1
  142. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  143. data/doc/cxxapi/inherit__graph__15.png +0 -0
  144. data/doc/cxxapi/inherit__graph__16.map +1 -1
  145. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  146. data/doc/cxxapi/inherit__graph__16.png +0 -0
  147. data/doc/cxxapi/inherit__graph__17.map +1 -1
  148. data/doc/cxxapi/inherit__graph__17.md5 +1 -1
  149. data/doc/cxxapi/inherit__graph__17.png +0 -0
  150. data/doc/cxxapi/inherit__graph__18.map +1 -1
  151. data/doc/cxxapi/inherit__graph__18.md5 +1 -1
  152. data/doc/cxxapi/inherit__graph__18.png +0 -0
  153. data/doc/cxxapi/inherit__graph__19.map +1 -1
  154. data/doc/cxxapi/inherit__graph__19.md5 +1 -1
  155. data/doc/cxxapi/inherit__graph__19.png +0 -0
  156. data/doc/cxxapi/inherit__graph__2.map +1 -1
  157. data/doc/cxxapi/inherit__graph__2.md5 +1 -1
  158. data/doc/cxxapi/inherit__graph__2.png +0 -0
  159. data/doc/cxxapi/inherit__graph__20.map +2 -2
  160. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  161. data/doc/cxxapi/inherit__graph__20.png +0 -0
  162. data/doc/cxxapi/inherit__graph__21.map +1 -1
  163. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  164. data/doc/cxxapi/inherit__graph__21.png +0 -0
  165. data/doc/cxxapi/inherit__graph__3.map +1 -1
  166. data/doc/cxxapi/inherit__graph__3.md5 +1 -1
  167. data/doc/cxxapi/inherit__graph__3.png +0 -0
  168. data/doc/cxxapi/inherit__graph__4.map +1 -1
  169. data/doc/cxxapi/inherit__graph__4.md5 +1 -1
  170. data/doc/cxxapi/inherit__graph__4.png +0 -0
  171. data/doc/cxxapi/inherit__graph__5.map +1 -2
  172. data/doc/cxxapi/inherit__graph__5.md5 +1 -1
  173. data/doc/cxxapi/inherit__graph__5.png +0 -0
  174. data/doc/cxxapi/inherit__graph__6.map +2 -1
  175. data/doc/cxxapi/inherit__graph__6.md5 +1 -1
  176. data/doc/cxxapi/inherit__graph__6.png +0 -0
  177. data/doc/cxxapi/inherit__graph__7.map +1 -1
  178. data/doc/cxxapi/inherit__graph__7.md5 +1 -1
  179. data/doc/cxxapi/inherit__graph__7.png +0 -0
  180. data/doc/cxxapi/inherit__graph__8.map +1 -1
  181. data/doc/cxxapi/inherit__graph__8.md5 +1 -1
  182. data/doc/cxxapi/inherit__graph__8.png +0 -0
  183. data/doc/cxxapi/inherit__graph__9.map +1 -1
  184. data/doc/cxxapi/inherit__graph__9.md5 +1 -1
  185. data/doc/cxxapi/inherit__graph__9.png +0 -0
  186. data/doc/cxxapi/inherits.html +41 -41
  187. data/doc/cxxapi/main.html +4 -4
  188. data/doc/cxxapi/modules.html +4 -5
  189. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +4 -4
  190. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +13 -10
  191. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +5 -5
  192. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +16 -13
  193. data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +4 -4
  194. data/doc/cxxapi/structPassenger_1_1PoolOptions.html +63 -60
  195. data/doc/cxxapi/tabs.css +5 -2
  196. data/doc/cxxapi/tree.html +7 -81
  197. data/doc/rdoc/classes/ConditionVariable.html +59 -59
  198. data/doc/rdoc/classes/Exception.html +11 -11
  199. data/doc/rdoc/classes/GC.html +4 -4
  200. data/doc/rdoc/classes/IO.html +14 -14
  201. data/doc/rdoc/classes/PhusionPassenger.html +75 -20
  202. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +153 -0
  203. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +125 -130
  204. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +236 -236
  205. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +213 -213
  206. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +28 -28
  207. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +91 -75
  208. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +10 -10
  209. data/doc/rdoc/classes/PhusionPassenger/Application.html +64 -64
  210. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +34 -34
  211. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +13 -13
  212. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +30 -30
  213. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +10 -10
  214. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +136 -136
  215. data/doc/rdoc/classes/PhusionPassenger/NativeSupport.html +24 -24
  216. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +42 -42
  217. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +55 -53
  218. data/doc/rdoc/classes/PhusionPassenger/Railz.html +1 -1
  219. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +25 -30
  220. data/doc/rdoc/classes/PhusionPassenger/Railz/CGIFixed.html +23 -23
  221. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +116 -117
  222. data/doc/rdoc/classes/PhusionPassenger/Railz/RequestHandler.html +22 -22
  223. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +118 -124
  224. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +10 -10
  225. data/doc/rdoc/classes/PhusionPassenger/Utils.html +354 -354
  226. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +9 -9
  227. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +37 -37
  228. data/doc/rdoc/classes/PlatformInfo.html +282 -261
  229. data/doc/rdoc/classes/RakeExtensions.html +7 -7
  230. data/doc/rdoc/classes/Signal.html +26 -26
  231. data/doc/rdoc/created.rid +1 -1
  232. data/doc/rdoc/files/DEVELOPERS_TXT.html +6 -1
  233. data/doc/rdoc/files/README.html +15 -6
  234. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
  235. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +129 -0
  236. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +20 -13
  237. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +19 -13
  238. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +19 -13
  239. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +31 -1
  240. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +31 -1
  241. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +19 -13
  242. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +19 -13
  243. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +21 -12
  244. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +19 -13
  245. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +19 -13
  246. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +19 -13
  247. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +19 -13
  248. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +19 -13
  249. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +122 -0
  250. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +19 -13
  251. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +22 -12
  252. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +21 -12
  253. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +19 -13
  254. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
  255. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +19 -13
  256. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +21 -12
  257. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +19 -13
  258. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +19 -13
  259. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +27 -21
  260. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +21 -12
  261. data/doc/rdoc/files/misc/rake/extensions_rb.html +21 -12
  262. data/doc/rdoc/fr_class_index.html +1 -0
  263. data/doc/rdoc/fr_file_index.html +2 -0
  264. data/doc/rdoc/fr_method_index.html +116 -112
  265. data/doc/users_guide_snippets/analysis_and_system_maintenance_tools.txt +144 -0
  266. data/doc/users_guide_snippets/appendix_a_about.txt +13 -0
  267. data/doc/users_guide_snippets/appendix_b_terminology.txt +63 -0
  268. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +304 -0
  269. data/doc/users_guide_snippets/global_queueing_explained.txt +78 -0
  270. data/doc/users_guide_snippets/rackup_specifications.txt +75 -0
  271. data/doc/users_guide_snippets/rails_spawn_method.txt +48 -0
  272. data/doc/users_guide_snippets/tips.txt +173 -0
  273. data/ext/apache2/Bucket.cpp +17 -12
  274. data/ext/apache2/Bucket.h +17 -12
  275. data/ext/apache2/Configuration.cpp +17 -12
  276. data/ext/apache2/Configuration.h +27 -14
  277. data/ext/apache2/DirectoryMapper.h +21 -12
  278. data/ext/apache2/Hooks.cpp +67 -21
  279. data/ext/apache2/Hooks.h +17 -12
  280. data/ext/apache2/mod_passenger.c +17 -12
  281. data/ext/{apache2 → common}/Application.h +19 -14
  282. data/ext/{apache2 → common}/ApplicationPool.h +17 -12
  283. data/ext/{apache2 → common}/ApplicationPoolServer.h +18 -72
  284. data/ext/{apache2 → common}/ApplicationPoolServerExecutable.cpp +45 -104
  285. data/ext/common/ApplicationPoolStatusReporter.h +212 -0
  286. data/ext/{apache2 → common}/CachedFileStat.cpp +17 -12
  287. data/ext/{apache2 → common}/CachedFileStat.h +17 -12
  288. data/ext/{apache2 → common}/DummySpawnManager.h +17 -12
  289. data/ext/{apache2 → common}/Exceptions.h +17 -12
  290. data/ext/{apache2 → common}/FileChecker.h +17 -12
  291. data/ext/common/Logging.cpp +65 -0
  292. data/ext/{apache2 → common}/Logging.h +17 -12
  293. data/ext/{apache2 → common}/MessageChannel.h +17 -12
  294. data/ext/{apache2 → common}/PoolOptions.h +17 -12
  295. data/ext/{apache2 → common}/SpawnManager.h +17 -12
  296. data/ext/{apache2 → common}/StandardApplicationPool.h +17 -12
  297. data/ext/common/StaticString.h +147 -0
  298. data/ext/common/SystemTime.cpp +33 -0
  299. data/ext/{apache2 → common}/SystemTime.h +17 -12
  300. data/ext/{apache2 → common}/Utils.cpp +69 -12
  301. data/ext/{apache2 → common}/Utils.h +41 -12
  302. data/ext/nginx/Configuration.c +1091 -0
  303. data/ext/nginx/Configuration.h +71 -0
  304. data/ext/nginx/ContentHandler.c +1154 -0
  305. data/ext/nginx/ContentHandler.h +64 -0
  306. data/ext/nginx/HelperServer.cpp +857 -0
  307. data/ext/nginx/HttpStatusExtractor.h +161 -0
  308. data/ext/nginx/ScgiRequestParser.h +317 -0
  309. data/ext/nginx/StaticContentHandler.c +222 -0
  310. data/ext/nginx/StaticContentHandler.h +37 -0
  311. data/ext/nginx/config +41 -0
  312. data/ext/nginx/ngx_http_passenger_module.c +572 -0
  313. data/ext/nginx/ngx_http_passenger_module.h +72 -0
  314. data/ext/oxt/backtrace.cpp +8 -1
  315. data/ext/oxt/system_calls.cpp +40 -0
  316. data/ext/oxt/system_calls.hpp +14 -7
  317. data/ext/phusion_passenger/extconf.rb +17 -12
  318. data/ext/phusion_passenger/native_support.c +19 -12
  319. data/lib/phusion_passenger/abstract_installer.rb +196 -0
  320. data/lib/phusion_passenger/abstract_request_handler.rb +19 -24
  321. data/lib/phusion_passenger/abstract_server.rb +17 -12
  322. data/lib/phusion_passenger/abstract_server_collection.rb +17 -12
  323. data/lib/phusion_passenger/admin_tools.rb +23 -0
  324. data/lib/phusion_passenger/admin_tools/control_process.rb +39 -13
  325. data/lib/phusion_passenger/application.rb +17 -12
  326. data/lib/phusion_passenger/console_text_template.rb +17 -12
  327. data/lib/phusion_passenger/constants.rb +22 -11
  328. data/lib/phusion_passenger/dependencies.rb +47 -12
  329. data/lib/phusion_passenger/events.rb +17 -12
  330. data/lib/phusion_passenger/exceptions.rb +17 -12
  331. data/lib/phusion_passenger/html_template.rb +17 -12
  332. data/lib/phusion_passenger/message_channel.rb +17 -12
  333. data/lib/phusion_passenger/packaging.rb +39 -0
  334. data/lib/phusion_passenger/platform_info.rb +48 -22
  335. data/lib/phusion_passenger/rack/application_spawner.rb +22 -11
  336. data/lib/phusion_passenger/rack/request_handler.rb +21 -12
  337. data/lib/phusion_passenger/railz/application_spawner.rb +23 -23
  338. data/lib/phusion_passenger/railz/framework_spawner.rb +18 -14
  339. data/lib/phusion_passenger/railz/request_handler.rb +18 -11
  340. data/lib/phusion_passenger/simple_benchmarking.rb +17 -12
  341. data/lib/phusion_passenger/spawn_manager.rb +17 -20
  342. data/lib/phusion_passenger/templates/{apache_must_be_compiled_with_compatible_mpm.txt.erb → apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb} +0 -0
  343. data/lib/phusion_passenger/templates/{apache2_config_snippets.txt.erb → apache2/config_snippets.txt.erb} +0 -0
  344. data/lib/phusion_passenger/templates/{deployment_example.txt.erb → apache2/deployment_example.txt.erb} +0 -0
  345. data/lib/phusion_passenger/templates/{no_write_permission_to_passenger_root.txt.erb → apache2/no_write_permission_to_passenger_root.txt.erb} +0 -0
  346. data/lib/phusion_passenger/templates/{possible_solutions_for_compilation_and_installation_problems.txt.erb → apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb} +0 -0
  347. data/lib/phusion_passenger/templates/{run_installer_as_root.txt.erb → apache2/run_installer_as_root.txt.erb} +0 -0
  348. data/lib/phusion_passenger/templates/{welcome.txt.erb → apache2/welcome.txt.erb} +0 -0
  349. data/lib/phusion_passenger/templates/nginx/ask_for_extra_configure_flags.txt.erb +8 -0
  350. data/lib/phusion_passenger/templates/nginx/cannot_write_to_dir.txt.erb +11 -0
  351. data/lib/phusion_passenger/templates/nginx/config_snippets.txt.erb +17 -0
  352. data/lib/phusion_passenger/templates/nginx/config_snippets_inserted.txt.erb +20 -0
  353. data/lib/phusion_passenger/templates/nginx/confirm_extra_configure_flags.txt.erb +5 -0
  354. data/lib/phusion_passenger/templates/nginx/deployment_example.txt.erb +22 -0
  355. data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_downloaded.txt.erb +11 -0
  356. data/lib/phusion_passenger/templates/nginx/pcre_could_not_be_extracted.txt.erb +11 -0
  357. data/lib/phusion_passenger/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +11 -0
  358. data/lib/phusion_passenger/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +20 -0
  359. data/lib/phusion_passenger/templates/nginx/query_download_and_install.txt.erb +21 -0
  360. data/lib/phusion_passenger/templates/nginx/run_installer_as_root.txt.erb +8 -0
  361. data/lib/phusion_passenger/templates/nginx/welcome.txt.erb +15 -0
  362. data/lib/phusion_passenger/utils.rb +20 -15
  363. data/lib/phusion_passenger/wsgi/application_spawner.rb +18 -11
  364. data/lib/phusion_passenger/wsgi/request_handler.py +23 -0
  365. data/misc/copy_boost_headers.rb +23 -0
  366. data/misc/find_owner_pipe_leaks.rb +18 -11
  367. data/misc/rake/cplusplus.rb +18 -11
  368. data/misc/rake/extensions.rb +21 -14
  369. data/misc/render_error_pages.rb +18 -11
  370. data/test/ApplicationPoolServerTest.cpp +1 -3
  371. data/test/ApplicationPoolServer_ApplicationPoolTest.cpp +1 -1
  372. data/test/CxxTestMain.cpp +19 -3
  373. data/test/HttpStatusExtractorTest.cpp +181 -0
  374. data/test/ScgiRequestParserTest.cpp +337 -0
  375. data/test/StaticStringTest.cpp +51 -0
  376. data/test/UtilsTest.cpp +32 -0
  377. data/test/config.yml.example +5 -0
  378. data/test/{integration_tests.rb → integration_tests/apache2_tests.rb} +7 -299
  379. data/test/integration_tests/hello_world_rack_spec.rb +36 -0
  380. data/test/integration_tests/hello_world_wsgi_spec.rb +41 -0
  381. data/test/integration_tests/mycook_spec.rb +192 -0
  382. data/test/integration_tests/nginx_tests.rb +98 -0
  383. data/test/ruby/rack/application_spawner_spec.rb +40 -0
  384. data/test/stub/nginx/koi-utf +109 -0
  385. data/test/stub/nginx/koi-win +103 -0
  386. data/test/stub/nginx/mime.types +70 -0
  387. data/test/stub/nginx/nginx.conf.erb +57 -0
  388. data/test/stub/nginx/win-utf +126 -0
  389. data/test/stub/rails_apps/mycook/app/controllers/uploads_controller.rb +4 -0
  390. data/test/stub/rails_apps/mycook/config/routes.rb +1 -1
  391. data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
  392. data/test/support/Support.h +40 -0
  393. data/test/support/nginx_controller.rb +98 -0
  394. data/test/support/test_helper.rb +79 -0
  395. metadata +1091 -1028
  396. data/benchmark/DummyRequestHandler.cpp +0 -101
  397. data/ext/apache2/Logging.cpp +0 -60
  398. data/ext/apache2/SystemTime.cpp +0 -28
@@ -0,0 +1,337 @@
1
+ #include "tut.h"
2
+ #include "ScgiRequestParser.h"
3
+
4
+ using namespace Passenger;
5
+ using namespace std;
6
+
7
+ namespace tut {
8
+ struct ScgiRequestParserTest {
9
+ ScgiRequestParser parser;
10
+ };
11
+
12
+ DEFINE_TEST_GROUP(ScgiRequestParserTest);
13
+
14
+ TEST_METHOD(1) {
15
+ // It has an initial state of READING_LENGTH_STRING and does
16
+ // not have anything in its header data buffer.
17
+ ensure_equals(parser.getState(), ScgiRequestParser::READING_LENGTH_STRING);
18
+ ensure(parser.getHeaderData().empty());
19
+ }
20
+
21
+ /***** Test parsing a complete SCGI request in a single pass. *****/
22
+
23
+ TEST_METHOD(2) {
24
+ // Parsing a request with a single header and no body.
25
+ static const char data[] = "12:hello\0world\0,";
26
+ ensure_equals("It accepted all input.",
27
+ parser.feed(data, sizeof(data) - 1),
28
+ sizeof(data) - 1);
29
+ ensure_equals("It is in the accepting state.",
30
+ parser.getState(), ScgiRequestParser::DONE);
31
+ ensure_equals("It parsed the header data.",
32
+ parser.getHeaderData(),
33
+ string("hello\0world\0", 12));
34
+ ensure(parser.getHeader("hello") == "world");
35
+ }
36
+
37
+ TEST_METHOD(3) {
38
+ // Parsing a request with a single header and a body.
39
+ static const char data[] = "12:hello\0world\0,data";
40
+ ensure_equals("It accepted all input.",
41
+ parser.feed(data, sizeof(data) - 1 - 4),
42
+ sizeof(data) - 1 - 4);
43
+ ensure_equals("It is in the accepting state.",
44
+ parser.getState(), ScgiRequestParser::DONE);
45
+ ensure_equals("It parsed the header data.",
46
+ parser.getHeaderData(),
47
+ string("hello\0world\0", 12));
48
+ ensure(parser.getHeader("hello") == "world");
49
+ }
50
+
51
+ TEST_METHOD(4) {
52
+ // Parsing a request with multiple headers and no body.
53
+ static const char data[] = "19:hello\0world\0SCGI\0001\0,";
54
+ ensure_equals("It accepted all input.",
55
+ parser.feed(data, sizeof(data) - 1),
56
+ sizeof(data) - 1);
57
+ ensure_equals("It is in the accepting state.",
58
+ parser.getState(), ScgiRequestParser::DONE);
59
+ ensure_equals("It parsed the header data.",
60
+ parser.getHeaderData(),
61
+ string("hello\0world\0SCGI\0001\0", 19));
62
+ ensure(parser.getHeader("hello") == "world");
63
+ ensure(parser.getHeader("SCGI") == "1");
64
+ }
65
+
66
+ TEST_METHOD(5) {
67
+ // Parsing a request with multiple headers and a body.
68
+ static const char data[] = "19:hello\0world\0SCGI\0001\0,body";
69
+ ensure_equals("It accepted all input.",
70
+ parser.feed(data, sizeof(data) - 1 - 4),
71
+ sizeof(data) - 1 - 4);
72
+ ensure_equals("It is in the accepting state.",
73
+ parser.getState(), ScgiRequestParser::DONE);
74
+ ensure_equals("It parsed the header data.",
75
+ parser.getHeaderData(),
76
+ string("hello\0world\0SCGI\0001\0", 19));
77
+ ensure(parser.getHeader("hello") == "world");
78
+ ensure(parser.getHeader("SCGI") == "1");
79
+ }
80
+
81
+ /***** Test parsing a complete SCGI request in multiple passes. *****/
82
+
83
+ TEST_METHOD(8) {
84
+ // Parsing a request with multiple headers and a body.
85
+ // 1 byte per pass.
86
+ static const char data[] = "20:hello\0world\0foo\0bar\0,data";
87
+ for (unsigned int i = 0; i < sizeof(data) - 1 - 4; i++) {
88
+ ensure_equals(parser.feed(&data[i], 1), 1u);
89
+ }
90
+ ensure_equals("It is in the accepting state.",
91
+ parser.getState(), ScgiRequestParser::DONE);
92
+ ensure_equals("It parsed the header data.",
93
+ parser.getHeaderData(),
94
+ string("hello\0world\0foo\0bar\0", 20));
95
+ ensure(parser.getHeader("hello") == "world");
96
+ ensure(parser.getHeader("foo") == "bar");
97
+ }
98
+
99
+ TEST_METHOD(9) {
100
+ // Parsing a request with multiple headers and a body.
101
+ // Half element per pass.
102
+ ensure_equals(parser.feed("2", 1), 1u);
103
+ ensure_equals(parser.feed("0", 1), 1u);
104
+ ensure_equals(parser.feed(":", 1), 1u);
105
+ ensure_equals(parser.feed("hello\0world\0", 12), 12u);
106
+ ensure_equals(parser.feed("foo\0bar\0", 8), 8u);
107
+ ensure_equals(parser.feed(",", 1), 1u);
108
+ ensure_equals(parser.feed("da", 2), 0u);
109
+ ensure_equals(parser.feed("ta", 2), 0u);
110
+ ensure_equals("It is in the accepting state.",
111
+ parser.getState(), ScgiRequestParser::DONE);
112
+ ensure_equals("It parsed the header data.",
113
+ parser.getHeaderData(),
114
+ string("hello\0world\0foo\0bar\0", 20));
115
+ ensure(parser.getHeader("hello") == "world");
116
+ ensure(parser.getHeader("foo") == "bar");
117
+ }
118
+
119
+ TEST_METHOD(10) {
120
+ // Parsing a request with multiple headers and a body.
121
+ // 1 element per pass.
122
+ ensure_equals(parser.feed("20", 2), 2u);
123
+ ensure_equals(parser.feed(":", 1), 1u);
124
+ ensure_equals(parser.feed("hello\0world\0foo\0bar\0", 20), 20u);
125
+ ensure_equals(parser.feed(",", 1), 1u);
126
+ ensure_equals(parser.feed("data", 4), 0u);
127
+ ensure_equals("It is in the accepting state.",
128
+ parser.getState(), ScgiRequestParser::DONE);
129
+ ensure_equals("It parsed the header data.",
130
+ parser.getHeaderData(),
131
+ string("hello\0world\0foo\0bar\0", 20));
132
+ ensure(parser.getHeader("hello") == "world");
133
+ ensure(parser.getHeader("foo") == "bar");
134
+ }
135
+
136
+ TEST_METHOD(11) {
137
+ // Parsing a request with multiple headers and a body.
138
+ // 2 elements per pass.
139
+ ensure_equals(parser.feed("20:", 3), 3u);
140
+ ensure_equals(parser.feed("hello\0world\0foo\0bar\0,", 21), 21u);
141
+ ensure_equals(parser.feed("data", 4), 0u);
142
+ ensure_equals("It is in the accepting state.",
143
+ parser.getState(), ScgiRequestParser::DONE);
144
+ ensure_equals("It parsed the header data.",
145
+ parser.getHeaderData(),
146
+ string("hello\0world\0foo\0bar\0", 20));
147
+ ensure(parser.getHeader("hello") == "world");
148
+ ensure(parser.getHeader("foo") == "bar");
149
+ }
150
+
151
+ TEST_METHOD(12) {
152
+ // Parsing a request with multiple headers and a body.
153
+ // Variable number of elements per pass.
154
+ ensure_equals(parser.feed("20:h", 4), 4u);
155
+ ensure_equals(parser.feed("ello\0world\0foo\0bar", 18), 18u);
156
+ ensure_equals(parser.feed("\0,data", 6), 2u);
157
+ ensure_equals("It is in the accepting state.",
158
+ parser.getState(), ScgiRequestParser::DONE);
159
+ ensure_equals("It parsed the header data.",
160
+ parser.getHeaderData(),
161
+ string("hello\0world\0foo\0bar\0", 20));
162
+ ensure(parser.getHeader("hello") == "world");
163
+ ensure(parser.getHeader("foo") == "bar");
164
+ }
165
+
166
+ /***** Test parsing invalid SCGI requests in one pass. *****/
167
+
168
+ TEST_METHOD(16) {
169
+ // Invalid first character for length string.
170
+ ensure_equals("Parser did not accept anything.",
171
+ parser.feed("hello world!", 12), 0u);
172
+ ensure_equals("Parser is in the error state.",
173
+ parser.getState(), ScgiRequestParser::ERROR);
174
+ }
175
+
176
+ TEST_METHOD(17) {
177
+ // Invalid character inside length string.
178
+ ensure_equals(parser.feed("12x:hello world!", 16), 2u);
179
+ ensure_equals("Parser is in the error state.",
180
+ parser.getState(), ScgiRequestParser::ERROR);
181
+ }
182
+
183
+ TEST_METHOD(18) {
184
+ // Invalid character in place of colon.
185
+ ensure_equals(parser.feed("12#hello world!", 15), 2u);
186
+ ensure_equals("Parser is in the error state.",
187
+ parser.getState(), ScgiRequestParser::ERROR);
188
+ }
189
+
190
+ TEST_METHOD(19) {
191
+ // Invalid character in place of comma.
192
+ ensure_equals(parser.feed("12:hello\0world\0!", 16), 15u);
193
+ ensure_equals("Parser is in the error state.",
194
+ parser.getState(), ScgiRequestParser::ERROR);
195
+ }
196
+
197
+ TEST_METHOD(20) {
198
+ // Only a header name, without even a null terminator.
199
+ ensure_equals(parser.feed("5:hello,", 8), 7u);
200
+ ensure_equals("Parser is in the error state.",
201
+ parser.getState(), ScgiRequestParser::ERROR);
202
+ }
203
+
204
+ TEST_METHOD(21) {
205
+ // Only a header name, with a null terminator.
206
+ ensure_equals(parser.feed("6:hello\0,", 9), 8u);
207
+ ensure_equals("Parser is in the error state.",
208
+ parser.getState(), ScgiRequestParser::ERROR);
209
+ }
210
+
211
+ TEST_METHOD(22) {
212
+ // A header name with its value not having a null terminator.
213
+ ensure_equals(parser.feed("7:foo\0bar,", 10), 9u);
214
+ ensure_equals("Parser is in the error state.",
215
+ parser.getState(), ScgiRequestParser::ERROR);
216
+ }
217
+
218
+ TEST_METHOD(23) {
219
+ // A header name without corresponding value.
220
+ ensure_equals(parser.feed("10:foo\0bar\0a\0,", 14), 13u);
221
+ ensure_equals("Parser is in the error state.",
222
+ parser.getState(), ScgiRequestParser::ERROR);
223
+ }
224
+
225
+ TEST_METHOD(24) {
226
+ // Length string is too large.
227
+ static const char data[] = "999999999999999999999";
228
+ ensure(parser.feed(data, sizeof(data) - 1) < sizeof(data) - 1);
229
+ ensure_equals("Parser is in the error state.",
230
+ parser.getState(), ScgiRequestParser::ERROR);
231
+ }
232
+
233
+ /***** Test parsing invalid SCGI requests in multiple passes. *****/
234
+
235
+ TEST_METHOD(27) {
236
+ // Once the parser has entered the error state, it stays there.
237
+ ensure_equals(parser.feed("hello world!", 12), 0u);
238
+ ensure_equals(parser.feed("1", 1), 0u);
239
+ ensure_equals("Parser is in the error state.",
240
+ parser.getState(), ScgiRequestParser::ERROR);
241
+ }
242
+
243
+ TEST_METHOD(28) {
244
+ // Invalid character inside length string.
245
+ ensure_equals(parser.feed("12", 2), 2u);
246
+ ensure_equals(parser.feed("x:", 2), 0u);
247
+ ensure_equals("Parser is in the error state.",
248
+ parser.getState(), ScgiRequestParser::ERROR);
249
+ }
250
+
251
+ TEST_METHOD(29) {
252
+ // Invalid character in place of colon.
253
+ ensure_equals(parser.feed("12", 2), 2u);
254
+ ensure_equals(parser.feed("#", 1), 0u);
255
+ ensure_equals("Parser is in the error state.",
256
+ parser.getState(), ScgiRequestParser::ERROR);
257
+ }
258
+
259
+ TEST_METHOD(30) {
260
+ // Invalid character in place of comma.
261
+ ensure_equals(parser.feed("12:hello\0world\0", 15), 15u);
262
+ ensure_equals(parser.feed("!", 1), 0u);
263
+ ensure_equals("Parser is in the error state.",
264
+ parser.getState(), ScgiRequestParser::ERROR);
265
+ }
266
+
267
+ TEST_METHOD(31) {
268
+ // Only a header name, without even a null terminator.
269
+ ensure_equals(parser.feed("5:hell", 6), 6u);
270
+ ensure_equals(parser.feed("o,", 1), 1u);
271
+ ensure_equals("Parser is in the error state.",
272
+ parser.getState(), ScgiRequestParser::ERROR);
273
+ }
274
+
275
+ TEST_METHOD(32) {
276
+ // Only a header name, with a null terminator.
277
+ ensure_equals(parser.feed("6:hello", 7), 7u);
278
+ ensure_equals(parser.feed("\0,", 1), 1u);
279
+ ensure_equals("Parser is in the error state.",
280
+ parser.getState(), ScgiRequestParser::ERROR);
281
+ }
282
+
283
+ TEST_METHOD(33) {
284
+ // A header name with its value not having a null terminator.
285
+ ensure_equals(parser.feed("7:foo\0ba", 8), 8u);
286
+ ensure_equals(parser.feed("r,", 2), 1u);
287
+ ensure_equals("Parser is in the error state.",
288
+ parser.getState(), ScgiRequestParser::ERROR);
289
+ }
290
+
291
+ TEST_METHOD(34) {
292
+ // A header name without corresponding value.
293
+ ensure_equals(parser.feed("10:foo\0bar\0a", 12), 12u);
294
+ ensure_equals(parser.feed("\0,", 2), 1u);
295
+ ensure_equals("Parser is in the error state.",
296
+ parser.getState(), ScgiRequestParser::ERROR);
297
+ }
298
+
299
+ TEST_METHOD(35) {
300
+ // Length string is too large.
301
+ static const char data[] = "999999999999999999999";
302
+ ensure_equals(parser.feed("99", 2), 2u);
303
+ ensure(parser.feed(data, sizeof(data) - 1) < sizeof(data) - 1);
304
+ ensure_equals("Parser is in the error state.",
305
+ parser.getState(), ScgiRequestParser::ERROR);
306
+ }
307
+
308
+ /***** Test parsing incomplete SCGI requests. *****/
309
+
310
+ TEST_METHOD(40) {
311
+ // Incomplete length string.
312
+ ensure_equals(parser.feed("2", 1), 1u);
313
+ ensure_equals("Parser is still waiting for length string input.",
314
+ parser.getState(), ScgiRequestParser::READING_LENGTH_STRING);
315
+ }
316
+
317
+ TEST_METHOD(41) {
318
+ // Incomplete header.
319
+ ensure_equals(parser.feed("21:", 3), 3u);
320
+ ensure_equals("Parser is waiting for header data input.",
321
+ parser.getState(), ScgiRequestParser::READING_HEADER_DATA);
322
+ }
323
+
324
+ TEST_METHOD(42) {
325
+ // Incomplete header.
326
+ ensure_equals(parser.feed("20:hel", 6), 6u);
327
+ ensure_equals("Parser is waiting for header data input.",
328
+ parser.getState(), ScgiRequestParser::READING_HEADER_DATA);
329
+ }
330
+
331
+ TEST_METHOD(43) {
332
+ // Complete header but no comma.
333
+ ensure_equals(parser.feed("8:foo\0bar\0", 10), 10u);
334
+ ensure_equals("Parser is waiting for comma.",
335
+ parser.getState(), ScgiRequestParser::EXPECTING_COMMA);
336
+ }
337
+ }
@@ -0,0 +1,51 @@
1
+ #include "tut.h"
2
+ #include "StaticString.h"
3
+
4
+ using namespace Passenger;
5
+ using namespace std;
6
+
7
+ namespace tut {
8
+ struct StaticStringTest {
9
+ };
10
+
11
+ DEFINE_TEST_GROUP(StaticStringTest);
12
+
13
+ TEST_METHOD(1) {
14
+ // Test == operator.
15
+ ensure(StaticString("") == "");
16
+ ensure(StaticString("foo") == "foo");
17
+ ensure(!(StaticString("foo") == "bar"));
18
+ }
19
+
20
+ TEST_METHOD(2) {
21
+ // Test < operator.
22
+ ensure_equals("Assertion 1",
23
+ StaticString("") < "",
24
+ string("") < string("")
25
+ );
26
+ ensure_equals("Assertion 2",
27
+ StaticString("abc") < "abc",
28
+ string("abc") < string("abc")
29
+ );
30
+ ensure_equals("Assertion 3",
31
+ StaticString("foo") < "bar",
32
+ string("foo") < string("bar")
33
+ );
34
+ ensure_equals("Assertion 4",
35
+ StaticString("foo") < "bar!",
36
+ string("foo") < string("bar!")
37
+ );
38
+ ensure_equals("Assertion 5",
39
+ StaticString("bar!") < "foo",
40
+ string("bar!") < string("foo")
41
+ );
42
+ ensure_equals("Assertion 6",
43
+ StaticString("hello") < "hello world",
44
+ string("hello") < string("hello world")
45
+ );
46
+ ensure_equals("Assertion 7",
47
+ StaticString("hello world") < "hello",
48
+ string("hello world") < string("hello")
49
+ );
50
+ }
51
+ }
data/test/UtilsTest.cpp CHANGED
@@ -1,5 +1,6 @@
1
1
  #include "tut.h"
2
2
  #include "Utils.h"
3
+ #include "support/Support.h"
3
4
  #include <sys/types.h>
4
5
  #include <sys/stat.h>
5
6
  #include <stdio.h>
@@ -10,6 +11,7 @@
10
11
 
11
12
  using namespace Passenger;
12
13
  using namespace std;
14
+ using namespace Test;
13
15
 
14
16
  namespace tut {
15
17
  struct UtilsTest {
@@ -245,4 +247,34 @@ namespace tut {
245
247
  ensure_equals(escapeForXml("hello\xFF\xCCworld"), "hello&#255;&#204;world");
246
248
  ensure_equals(escapeForXml("hello\xFFworld\xCC"), "hello&#255;world&#204;");
247
249
  }
250
+
251
+ /***** Test extractDirName() *****/
252
+
253
+ TEST_METHOD(26) {
254
+ ensure_equals("Test 1", extractDirName("/usr/lib"), "/usr");
255
+ ensure_equals("Test 2", extractDirName("/usr/lib/"), "/usr");
256
+ ensure_equals("Test 3", extractDirName("/usr/"), "/");
257
+ ensure_equals("Test 4", extractDirName("usr"), ".");
258
+ ensure_equals("Test 5", extractDirName("/"), "/");
259
+ ensure_equals("Test 6", extractDirName("///"), "/");
260
+ ensure_equals("Test 7", extractDirName("."), ".");
261
+ ensure_equals("Test 8", extractDirName(".."), ".");
262
+ ensure_equals("Test 9", extractDirName("./foo"), ".");
263
+ ensure_equals("Test 10", extractDirName("../foo"), "..");
264
+ }
265
+
266
+ /***** Test resolveSymlink() *****/
267
+
268
+ TEST_METHOD(27) {
269
+ TempDir d("tmp.symlinks");
270
+ system("touch tmp.symlinks/foo.txt");
271
+ system("ln -s /usr/bin tmp.symlinks/absolute_symlink");
272
+ system("ln -s foo.txt tmp.symlinks/file");
273
+ system("ln -s file tmp.symlinks/file2");
274
+ system("ln -s file2 tmp.symlinks/file3");
275
+ ensure_equals(resolveSymlink("tmp.symlinks/file"), "tmp.symlinks/foo.txt");
276
+ ensure_equals(resolveSymlink("tmp.symlinks/file2"), "tmp.symlinks/file");
277
+ ensure_equals(resolveSymlink("tmp.symlinks/file3"), "tmp.symlinks/file2");
278
+ ensure_equals(resolveSymlink("tmp.symlinks/absolute_symlink"), "/usr/bin");
279
+ }
248
280
  }
@@ -23,3 +23,8 @@ nonexistant_user: xxxxxxxxxxxxxxxxxxx
23
23
  # A nonexistant user ID.
24
24
  nonexistant_uid: 9999
25
25
 
26
+
27
+ # If you want to run the Nginx integration tests, then set the following
28
+ # config option to the full path of the Nginx binary. This Nginx binary *must*
29
+ # be compiled with Phusion Passenger support!
30
+ # nginx: /usr/local/sbin/nginx
@@ -1,254 +1,17 @@
1
- require 'net/http'
2
- require 'uri'
3
- require 'resolv'
4
1
  require 'socket'
5
2
  require 'fileutils'
6
- require 'timeout'
7
3
  require 'support/config'
8
4
  require 'support/test_helper'
9
- require 'support/multipart'
10
5
  require 'support/apache2_controller'
11
6
  require 'phusion_passenger/platform_info'
12
7
 
8
+ require 'integration_tests/mycook_spec'
9
+ require 'integration_tests/hello_world_rack_spec'
10
+ require 'integration_tests/hello_world_wsgi_spec'
11
+
13
12
  # TODO: test the 'RailsUserSwitching' and 'RailsDefaultUser' option.
14
13
  # TODO: test custom page caching directory
15
14
 
16
- shared_examples_for "MyCook(tm) beta" do
17
- it "is possible to fetch static assets" do
18
- get('/images/rails.png').should == public_file('images/rails.png')
19
- end
20
-
21
- it "supports page caching on non-index URIs" do
22
- get('/welcome/cached').should =~ %r{This is the cached version of /welcome/cached}
23
- end
24
-
25
- it "supports page caching on index URIs" do
26
- get('/uploads').should =~ %r{This is the cached version of /uploads}
27
- end
28
-
29
- it "doesn't use page caching if the HTTP request is not GET" do
30
- post('/welcome/cached').should =~ %r{This content should never be displayed}
31
- end
32
-
33
- it "isn't interfered by Rails's default .htaccess dispatcher rules" do
34
- get('/welcome/in_passenger').should == 'true'
35
- end
36
-
37
- it "is possible to GET a regular Rails page" do
38
- get('/').should =~ /Welcome to MyCook/
39
- end
40
-
41
- it "is possible to pass GET parameters to a Rails page" do
42
- result = get('/welcome/parameters_test?hello=world&recipe[name]=Green+Bananas')
43
- result.should =~ %r{<hello>world</hello>}
44
- result.should =~ %r{<recipe>}
45
- result.should =~ %r{<name>Green Bananas</name>}
46
- end
47
-
48
- it "is possible to POST to a Rails page" do
49
- result = post('/recipes', {
50
- 'recipe[name]' => 'Banana Pancakes',
51
- 'recipe[instructions]' => 'Call 0900-BANANAPANCAKES'
52
- })
53
- result.should =~ %r{HTTP method: post}
54
- result.should =~ %r{Name: Banana Pancakes}
55
- result.should =~ %r{Instructions: Call 0900-BANANAPANCAKES}
56
- end
57
-
58
- it "is possible to upload a file" do
59
- rails_png = File.open("#{@stub.app_root}/public/images/rails.png", 'rb')
60
- params = {
61
- 'upload[name1]' => 'Kotonoha',
62
- 'upload[name2]' => 'Sekai',
63
- 'upload[data]' => rails_png
64
- }
65
- begin
66
- response = post('/uploads', params)
67
- rails_png.rewind
68
- response.should ==
69
- "name 1 = Kotonoha\n" <<
70
- "name 2 = Sekai\n" <<
71
- "data = " << rails_png.read
72
- ensure
73
- rails_png.close
74
- end
75
- end
76
-
77
- it "can properly handle custom headers" do
78
- response = get_response('/welcome/headers_test')
79
- response["X-Foo"].should == "Bar"
80
- end
81
-
82
- it "supports %2f in URIs" do
83
- get('/welcome/show_id/foo%2fbar').should == 'foo/bar'
84
- end
85
-
86
- it "has AbstractRequest which returns a request_uri without hostname, with query_string" do
87
- get('/welcome/request_uri?foo=bar%20escaped').should =~ %r{/welcome/request_uri\?foo=bar%20escaped}
88
- end
89
-
90
- it "supports restarting via restart.txt" do
91
- begin
92
- controller = "#{@stub.app_root}/app/controllers/test_controller.rb"
93
- restart_file = "#{@stub.app_root}/tmp/restart.txt"
94
- now = Time.now
95
-
96
- File.open(controller, 'w') do |f|
97
- f.write %q{
98
- class TestController < ApplicationController
99
- layout nil
100
- def index
101
- render :text => "foo"
102
- end
103
- end
104
- }
105
- end
106
- File.open(restart_file, 'w').close
107
- File.utime(now - 10, now - 10, restart_file)
108
- get('/test').should == "foo"
109
-
110
- File.open(controller, 'w') do |f|
111
- f.write %q{
112
- class TestController < ApplicationController
113
- layout nil
114
- def index
115
- render :text => "bar"
116
- end
117
- end
118
- }
119
- end
120
-
121
- File.utime(now - 5, now - 5, restart_file)
122
- get('/test').should == 'bar'
123
- ensure
124
- File.unlink(controller) rescue nil
125
- File.unlink(restart_file) rescue nil
126
- end
127
- end
128
-
129
- it "does not make the web server crash if the app crashes" do
130
- post('/welcome/terminate')
131
- sleep(0.25) # Give the app the time to terminate itself.
132
- get('/').should =~ /Welcome to MyCook/
133
- end
134
-
135
- it "does not conflict with Phusion Passenger if there's a model named 'Passenger'" do
136
- Dir.mkdir("#{@stub.app_root}/app/models") rescue nil
137
- File.open("#{@stub.app_root}/app/models/passenger.rb", 'w') do |f|
138
- f.write(%q{
139
- class Passenger
140
- def name
141
- return "Gourry Gabriev"
142
- end
143
- end
144
- })
145
- end
146
- begin
147
- system "touch '#{@stub.app_root}/tmp/restart.txt'"
148
- get('/welcome/passenger_name').should == 'Gourry Gabriev'
149
- ensure
150
- File.unlink("#{@stub.app_root}/app/models/passenger.rb") rescue nil
151
- end
152
- end
153
-
154
- it "sets the 'Status' header" do
155
- response = get_response('/nonexistant')
156
- response["Status"].should == "404 Not Found"
157
- end
158
-
159
- if Process.uid == 0
160
- it "runs as an unprivileged user" do
161
- post('/welcome/touch')
162
- begin
163
- stat = File.stat("#{@stub.app_root}/public/touch.txt")
164
- stat.uid.should_not == 0
165
- stat.gid.should_not == 0
166
- ensure
167
- File.unlink("#{@stub.app_root}/public/touch.txt") rescue nil
168
- end
169
- end
170
- end
171
- end
172
-
173
- shared_examples_for "HelloWorld Rack application" do
174
- it "is possible to fetch static assets" do
175
- get('/rack.jpg').should == public_file('rack.jpg')
176
- end
177
-
178
- it "is possible to GET a regular Rack page" do
179
- get('/').should =~ /hello/
180
- end
181
-
182
- it "supports restarting via restart.txt" do
183
- get('/').should =~ /hello/
184
- File.write("#{@stub.app_root}/config.ru", %q{
185
- app = lambda do |env|
186
- [200, { "Content-Type" => "text/html" }, "changed"]
187
- end
188
- run app
189
- })
190
- File.new("#{@stub.app_root}/tmp/restart.txt", "w").close
191
- File.utime(2, 2, "#{@stub.app_root}/tmp/restart.txt")
192
- get('/').should == "changed"
193
- end
194
-
195
- if Process.uid == 0
196
- it "runs as an unprivileged user" do
197
- File.prepend("#{@stub.app_root}/config.ru", %q{
198
- File.new('foo.txt', 'w').close
199
- })
200
- File.new("#{@stub.app_root}/tmp/restart.txt", "w").close
201
- File.utime(1, 1, "#{@stub.app_root}/tmp/restart.txt")
202
- get('/')
203
- stat = File.stat("#{@stub.app_root}/foo.txt")
204
- stat.uid.should_not == 0
205
- stat.gid.should_not == 0
206
- end
207
- end
208
- end
209
-
210
- shared_examples_for "HelloWorld WSGI application" do
211
- after :each do
212
- File.unlink("#{@stub.app_root}/passenger_wsgi.pyc") rescue nil
213
- end
214
-
215
- it "is possible to fetch static assets" do
216
- get('/wsgi-snake.jpg').should == public_file('wsgi-snake.jpg')
217
- end
218
-
219
- it "is possible to GET a regular WSGI page" do
220
- get('/').should =~ /Hello World/
221
- end
222
-
223
- it "supports restarting via restart.txt" do
224
- get('/').should =~ /Hello World/
225
-
226
- code = %q{
227
- def application(env, start_response):
228
- start_response('200 OK', [('Content-Type', 'text/html')])
229
- return ["changed"]
230
- }.gsub(/^\t\t\t/, '')
231
-
232
- File.write("#{@stub.app_root}/passenger_wsgi.py", code)
233
- File.new("#{@stub.app_root}/tmp/restart.txt", "w").close
234
- File.utime(2, 2, "#{@stub.app_root}/tmp/restart.txt")
235
- get('/').should == "changed"
236
- end
237
-
238
- if Process.uid == 0
239
- it "runs as an unprivileged user" do
240
- File.prepend("#{@stub.app_root}/passenger_wsgi.py",
241
- "file('foo.txt', 'w').close()\n")
242
- File.new("#{@stub.app_root}/tmp/restart.txt", "w").close
243
- File.utime(1, 1, "#{@stub.app_root}/tmp/restart.txt")
244
- get('/')
245
- stat = File.stat("#{@stub.app_root}/foo.txt")
246
- stat.uid.should_not == 0
247
- stat.gid.should_not == 0
248
- end
249
- end
250
- end
251
-
252
15
  describe "mod_passenger running in Apache 2" do
253
16
  include TestHelper
254
17
 
@@ -269,6 +32,7 @@ describe "mod_passenger running in Apache 2" do
269
32
 
270
33
  describe ": MyCook(tm) beta running on root URI" do
271
34
  before :all do
35
+ @web_server_supports_chunked_transfer_encoding = true
272
36
  @server = "http://passenger.test:#{@apache2.port}"
273
37
  @stub = setup_rails_stub('mycook')
274
38
  @apache2 << "RailsMaxPoolSize 1"
@@ -333,6 +97,7 @@ describe "mod_passenger running in Apache 2" do
333
97
 
334
98
  describe ": MyCook(tm) beta running in a sub-URI" do
335
99
  before :all do
100
+ @web_server_supports_chunked_transfer_encoding = true
336
101
  @stub = setup_rails_stub('mycook')
337
102
  FileUtils.rm_rf('tmp.webdir')
338
103
  FileUtils.mkdir_p('tmp.webdir')
@@ -733,66 +498,9 @@ describe "mod_passenger running in Apache 2" do
733
498
 
734
499
  ##### Helper methods #####
735
500
 
736
- def get(uri)
737
- if !@apache2.running?
738
- @apache2.start
739
- end
740
- return Net::HTTP.get(URI.parse("#{@server}#{uri}"))
741
- end
742
-
743
- def get_response(uri)
744
- if !@apache2.running?
745
- @apache2.start
746
- end
747
- return Net::HTTP.get_response(URI.parse("#{@server}#{uri}"))
748
- end
749
-
750
- def post(uri, params = {})
501
+ def start_web_server_if_necessary
751
502
  if !@apache2.running?
752
503
  @apache2.start
753
504
  end
754
- url = URI.parse("#{@server}#{uri}")
755
- if params.values.any? { |x| x.respond_to?(:read) }
756
- mp = Multipart::MultipartPost.new
757
- query, headers = mp.prepare_query(params)
758
- Net::HTTP.start(url.host, url.port) do |http|
759
- return http.post(url.path, query, headers).body
760
- end
761
- else
762
- return Net::HTTP.post_form(url, params).body
763
- end
764
- end
765
-
766
- def public_file(name)
767
- return File.read("#{@stub.app_root}/public/#{name}")
768
- end
769
-
770
- def check_hosts_configuration
771
- begin
772
- ok = Resolv.getaddress("passenger.test") == "127.0.0.1"
773
- rescue Resolv::ResolvError, ArgumentError
774
- # There's a bug in Ruby 1.8.6-p287's resolv.rb library, which causes
775
- # an ArgumentError to be raised instead of ResolvError when resolving
776
- # failed.
777
- ok = false
778
- end
779
- if !ok
780
- message = "To run the integration test, you must update " <<
781
- "your hosts file.\n" <<
782
- "Please add these to your /etc/hosts:\n\n" <<
783
- " 127.0.0.1 passenger.test\n" <<
784
- " 127.0.0.1 mycook.passenger.test\n" <<
785
- " 127.0.0.1 zsfa.passenger.test\n" <<
786
- " 127.0.0.1 norails.passenger.test\n"
787
- if RUBY_PLATFORM =~ /darwin/
788
- message << "\n\nThen run:\n\n" <<
789
- " lookupd -flushcache (OS X Tiger)\n\n" <<
790
- "-OR-\n\n" <<
791
- " dscacheutil -flushcache (OS X Leopard)"
792
- end
793
- STDERR.puts "---------------------------"
794
- STDERR.puts message
795
- exit!
796
- end
797
505
  end
798
506
  end