File: daemonizing_spec.rb

package info (click to toggle)
thin 1.2.4-1.1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 1,252 kB
  • ctags: 531
  • sloc: ruby: 4,529; ansic: 725; sh: 21; makefile: 16
file content (192 lines) | stat: -rw-r--r-- 4,417 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
require File.dirname(__FILE__) + '/spec_helper'

class TestServer
  include Logging # Daemonizable should include this?
  include Daemonizable
  
  def stop
  end
  
  def name
    'Thin test server'
  end
end

describe 'Daemonizing' do
  before :all do
    @logfile = File.dirname(__FILE__) + '/../log/daemonizing_test.log'
    @pidfile = 'test.pid'
    File.delete(@logfile) if File.exist?(@logfile)
    File.delete(@pidfile) if File.exist?(@pidfile)
  end
  
  before :each do
    @server = TestServer.new
    @server.log_file = @logfile
    @server.pid_file = @pidfile
    @pid = nil
  end
  
  it 'should have a pid file' do
    @server.should respond_to(:pid_file)
    @server.should respond_to(:pid_file=)
  end
  
  it 'should create a pid file' do
    @pid = fork do
      @server.daemonize
      sleep 1
    end
    
    sleep 1
    Process.wait(@pid)
    File.exist?(@server.pid_file).should be_true
    @pid = @server.pid

    proc { sleep 0.1 while File.exist?(@server.pid_file) }.should take_less_then(5)
  end
  
  it 'should redirect stdio to a log file' do
    @pid = fork do
      @server.log_file = 'daemon_test.log'
      @server.daemonize

      puts "simple puts"
      STDERR.puts "STDERR.puts"
      STDOUT.puts "STDOUT.puts"
    end
    Process.wait(@pid)
    # Wait for the file to close and magical stuff to happen
    proc { sleep 0.1 until File.exist?('daemon_test.log') }.should take_less_then(3)
    sleep 0.5
    
    @pid = @server.pid

    log = File.read('daemon_test.log')
    log.should include('simple puts', 'STDERR.puts', 'STDOUT.puts')
    
    File.delete 'daemon_test.log'
  end
  
  it 'should change privilege' do
    @pid = fork do
      @server.daemonize
      @server.change_privilege('root', 'admin')
    end
    Process.wait(@pid)
    $?.should be_a_success
  end
  
  it 'should kill process in pid file' do
    @pid = fork do
      @server.daemonize
      loop { sleep 3 }
    end
  
    server_should_start_in_less_then 3
    
    @pid = @server.pid
  
    silence_stream STDOUT do
      TestServer.kill(@server.pid_file, 1)
    end
  
    File.exist?(@server.pid_file).should be_false
  end
  
  it 'should force kill process in pid file' do
    @pid = fork do
      @server.daemonize
      loop { sleep 3 }
    end
  
    server_should_start_in_less_then 3
    
    @pid = @server.pid
  
    silence_stream STDOUT do
      TestServer.kill(@server.pid_file, 0)
    end
  
    File.exist?(@server.pid_file).should be_false
  end
  
  it 'should send kill signal if timeout' do
    @pid = fork do
      @server.should_receive(:stop) # pretend we cannot handle the INT signal
      @server.daemonize
      sleep 5
    end
  
    server_should_start_in_less_then 10
    
    @pid = @server.pid
  
    silence_stream STDOUT do
      TestServer.kill(@server.pid_file, 1)
    end
    
    sleep 1
  
    File.exist?(@server.pid_file).should be_false
    Process.running?(@pid).should be_false
  end
  
  it "should restart" do
    @pid = fork do
      @server.on_restart {}
      @server.daemonize
      sleep 5
    end
    
    server_should_start_in_less_then 10
    
    @pid = @server.pid
  
    silence_stream STDOUT do
      TestServer.restart(@server.pid_file)
    end
    
    proc { sleep 0.1 while File.exist?(@server.pid_file) }.should take_less_then(10)
  end
  
  it "should not restart when not running" do
    silence_stream STDOUT do
      TestServer.restart(@server.pid_file)
    end
  end
  
  it "should exit and raise if pid file already exist" do
    @pid = fork do
      @server.daemonize
      sleep 5
    end
    server_should_start_in_less_then 10
    
    @pid = @server.pid

    proc { @server.daemonize }.should raise_error(PidFileExist)
    
    File.exist?(@server.pid_file).should be_true
  end
  
  it "should should delete pid file if stale" do
    # Create a file w/ a PID that does not exist
    File.open(@server.pid_file, 'w') { |f| f << 999999999 }
    
    @server.send(:remove_stale_pid_file)
    
    File.exist?(@server.pid_file).should be_false
  end
  
  after do
    Process.kill(9, @pid.to_i) if @pid && Process.running?(@pid.to_i)
    Process.kill(9, @server.pid) if @server.pid && Process.running?(@server.pid)
    File.delete(@server.pid_file) rescue nil
  end
  
  private
    def server_should_start_in_less_then(sec=10)
      proc { sleep 0.1 until File.exist?(@server.pid_file) }.should take_less_then(10)
    end
end