PageRenderTime 34ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/test/ruby/shared/spawners/spawner_spec.rb

https://github.com/caroo/passenger
Ruby | 273 lines | 265 code | 8 blank | 0 comment | 6 complexity | 187a1c3e6cb0300f7381e730b73af9a3 MD5 | raw file
  1. require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
  2. require 'yaml'
  3. require 'etc'
  4. module PhusionPassenger
  5. shared_examples_for "a spawner" do
  6. def ping_app(app, connect_password)
  7. if app.server_sockets[:main][1] == "unix"
  8. client = UNIXSocket.new(app.server_sockets[:main][0])
  9. else
  10. addr, port = app.server_sockets[:main][0].split(/:/)
  11. client = TCPSocket.new(addr, port.to_i)
  12. end
  13. begin
  14. channel = MessageChannel.new(client)
  15. channel.write_scalar("REQUEST_METHOD\0PING\0PASSENGER_CONNECT_PASSWORD\0#{connect_password}\0")
  16. return client.read
  17. ensure
  18. client.close
  19. end
  20. end
  21. it "returns a valid AppProcess object" do
  22. app = spawn_some_application
  23. lambda { Process.kill(0, app.pid) }.should_not raise_error
  24. end
  25. it "sets the working directory of the app to its app root" do
  26. before_start %q{
  27. File.touch("cwd.txt")
  28. }
  29. app = spawn_some_application
  30. File.exist?("#{app.app_root}/cwd.txt").should be_true
  31. end
  32. it "sets ENV['RAILS_ENV'] and ENV['RACK_ENV']" do
  33. before_start %q{
  34. File.write("rails_env.txt", ENV['RAILS_ENV'])
  35. File.write("rack_env.txt", ENV['RACK_ENV'])
  36. }
  37. app = spawn_some_application("environment" => "staging")
  38. File.read("#{app.app_root}/rails_env.txt").should == "staging"
  39. File.read("#{app.app_root}/rack_env.txt").should == "staging"
  40. end
  41. it "sets ENV['RAILS_RELATIVE_URL_ROOT'] and ENV['RACK_BASE_URI'] if the 'base_uri' option is set to a valid value" do
  42. before_start %q{
  43. File.write("rails_relative_url_root.txt", ENV['RAILS_RELATIVE_URL_ROOT'])
  44. File.write("rack_base_uri.txt", ENV['RACK_BASE_URI'])
  45. }
  46. app = spawn_some_application("base_uri" => "/foo")
  47. File.read("#{app.app_root}/rails_relative_url_root.txt").should == "/foo"
  48. File.read("#{app.app_root}/rack_base_uri.txt").should == "/foo"
  49. end
  50. it "doesn't set ENV['RAILS_RELATIVE_URL_ROOT'] and ENV['RACK_BASE_URI'] if 'base_uri' is not given" do
  51. before_start %q{
  52. if ENV['RAILS_RELATIVE_URL_ROOT']
  53. File.touch("rails_relative_url_root.txt")
  54. end
  55. if ENV['RACK_BASE_URI']
  56. File.touch("rack_base_uri.txt")
  57. end
  58. }
  59. app = spawn_some_application
  60. File.exist?("#{app.app_root}/rails_relative_url_root.txt").should be_false
  61. File.exist?("#{app.app_root}/rack_base_uri.txt").should be_false
  62. end
  63. it "doesn't set ENV['RAILS_RELATIVE_URL_ROOT'] and ENV['RACK_BASE_URI'] if 'base_uri' is empty" do
  64. before_start %q{
  65. if ENV['RAILS_RELATIVE_URL_ROOT']
  66. File.touch("rails_relative_url_root.txt")
  67. end
  68. if ENV['RACK_BASE_URI']
  69. File.touch("rack_base_uri.txt")
  70. end
  71. }
  72. app = spawn_some_application("base_uri" => "")
  73. File.exist?("#{app.app_root}/rails_relative_url_root.txt").should be_false
  74. File.exist?("#{app.app_root}/rack_base_uri.txt").should be_false
  75. end
  76. it "doesn't set ENV['RAILS_RELATIVE_URL_ROOT'] and ENV['RACK_BASE_URI'] if 'base_uri' is '/'" do
  77. before_start %q{
  78. if ENV['RAILS_RELATIVE_URL_ROOT']
  79. File.touch("rails_relative_url_root.txt")
  80. end
  81. if ENV['RACK_BASE_URI']
  82. File.touch("rack_base_uri.txt")
  83. end
  84. }
  85. app = spawn_some_application("base_uri" => "/")
  86. File.exist?("#{app.app_root}/rails_relative_url_root.txt").should be_false
  87. File.exist?("#{app.app_root}/rack_base_uri.txt").should be_false
  88. end
  89. it "sets the environment variables in the 'environment_variables' option" do
  90. before_start %q{
  91. File.open("env.txt", "w") do |f|
  92. f.puts
  93. ENV.each_pair do |key, value|
  94. f.puts("#{key} = #{value}")
  95. end
  96. end
  97. }
  98. env_vars_string = "PATH\0/usr/bin:/opt/sw/bin\0FOO\0foo bar!\0"
  99. options = { "environment_variables" => [env_vars_string].pack("m") }
  100. app = spawn_some_application(options)
  101. contents = File.read("#{app.app_root}/env.txt")
  102. contents.should =~ %r(\nPATH = /usr/bin:/opt/sw/bin\n)
  103. contents.should =~ %r(\nFOO = foo bar\!\n)
  104. end
  105. it "does not cache things like the connect password" do
  106. app1 = spawn_some_application("connect_password" => "1234")
  107. app2 = spawn_some_application("connect_password" => "5678")
  108. ping_app(app1, "1234").should == "pong"
  109. ping_app(app2, "5678").should == "pong"
  110. end
  111. it "calls the starting_worker_process event after the startup file has been loaded" do
  112. after_start %q{
  113. history_file = "#{PhusionPassenger::Utils.passenger_tmpdir}/history.txt"
  114. PhusionPassenger.on_event(:starting_worker_process) do
  115. ::File.append(history_file, "worker_process_started\n")
  116. end
  117. ::File.append(history_file, "end of startup file\n");
  118. }
  119. spawn_some_application.close
  120. app = spawn_some_application
  121. app.close
  122. history_file = "#{PhusionPassenger::Utils.passenger_tmpdir}/history.txt"
  123. eventually do
  124. contents = File.read(history_file)
  125. lines = contents.split("\n")
  126. lines[0] == "end of startup file" &&
  127. lines.count("worker_process_started") == 2
  128. end
  129. end
  130. it "calls the stopping_worker_process event" do
  131. after_start %q{
  132. history_file = "#{PhusionPassenger::Utils.passenger_tmpdir}/history.txt"
  133. PhusionPassenger.on_event(:stopping_worker_process) do
  134. ::File.append(history_file, "worker_process_stopped\n")
  135. end
  136. ::File.append(history_file, "end of startup file\n");
  137. }
  138. spawn_some_application.close
  139. app = spawn_some_application
  140. app.close
  141. history_file = "#{PhusionPassenger::Utils.passenger_tmpdir}/history.txt"
  142. eventually do
  143. contents = File.read(history_file)
  144. lines = contents.split("\n")
  145. lines[0] == "end of startup file" &&
  146. lines.count("worker_process_stopped") == 2
  147. end
  148. end
  149. it "calls #at_exit blocks upon exiting" do
  150. before_start %q{
  151. history_file = "#{PhusionPassenger::Utils.passenger_tmpdir}/history.txt"
  152. at_exit do
  153. File.open(history_file, "a") do |f|
  154. f.puts "at_exit 1"
  155. end
  156. end
  157. at_exit do
  158. File.open(history_file, "a") do |f|
  159. f.puts "at_exit 2"
  160. end
  161. end
  162. }
  163. spawn_some_application.close
  164. history_file = "#{PhusionPassenger::Utils.passenger_tmpdir}/history.txt"
  165. eventually do
  166. File.exist?(history_file) &&
  167. File.read(history_file) ==
  168. "at_exit 2\n" +
  169. "at_exit 1\n"
  170. end
  171. end
  172. it "lowers privilege using Utils#lower_privilege" do
  173. filename = "#{PhusionPassenger::Utils.passenger_tmpdir}/called.txt"
  174. PhusionPassenger::Utils.stub!(:lower_privilege_called).and_return do
  175. File.touch(filename)
  176. end
  177. spawn_some_application.close
  178. eventually do
  179. File.exist?(filename).should be_true
  180. end
  181. end
  182. describe "error handling" do
  183. it "raises an AppInitError if the spawned app raises a standard exception during startup" do
  184. before_start %q{
  185. raise 'This is a dummy exception.'
  186. }
  187. begin
  188. spawn_some_application("print_exceptions" => false)
  189. violated "Spawning the application should have raised an AppInitError."
  190. rescue AppInitError => e
  191. e.child_exception.message.should == "This is a dummy exception."
  192. end
  193. end
  194. it "raises an AppInitError if the spawned app raises a custom-defined exception during startup" do
  195. before_start %q{
  196. class MyError < StandardError
  197. end
  198. raise MyError, "This is a custom exception."
  199. }
  200. begin
  201. spawn_some_application("print_exceptions" => false)
  202. violated "Spawning the application should have raised an AppInitError."
  203. rescue AppInitError => e
  204. e.child_exception.message.should == "This is a custom exception. (MyError)"
  205. end
  206. end
  207. it "raises an AppInitError if the spawned app calls exit() during startup" do
  208. before_start %q{
  209. exit
  210. }
  211. begin
  212. spawn_some_application("print_exceptions" => false).close
  213. violated "Spawning the application should have raised an AppInitError."
  214. rescue AppInitError => e
  215. e.child_exception.class.should == SystemExit
  216. end
  217. end
  218. it "prints the exception to STDERR if the spawned app raised an error" do
  219. old_stderr = STDERR
  220. file = File.new('output.tmp', 'w+')
  221. begin
  222. Object.send(:remove_const, "STDERR") rescue nil
  223. Object.const_set("STDERR", file)
  224. before_start %q{
  225. def dummy_function
  226. raise 'This is a dummy exception.'
  227. end
  228. dummy_function
  229. }
  230. block = lambda { spawn_some_application }
  231. block.should raise_error(AppInitError)
  232. file.rewind
  233. data = file.read
  234. data.should =~ /This is a dummy exception/
  235. data.should =~ /dummy_function/
  236. ensure
  237. Object.send(:remove_const, "STDERR") rescue nil
  238. Object.const_set("STDERR", old_stderr)
  239. file.close rescue nil
  240. File.unlink('output.tmp') rescue nil
  241. end
  242. end
  243. end
  244. end
  245. end # module PhusionPassenger