serverside 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +15 -11
- data/Rakefile +18 -18
- data/bin/serverside +20 -16
- data/lib/serverside/cluster.rb +4 -33
- data/lib/serverside/core_ext.rb +56 -7
- data/lib/serverside/daemon.rb +10 -17
- data/lib/serverside/http/caching.rb +79 -0
- data/lib/serverside/http/const.rb +69 -0
- data/lib/serverside/http/error.rb +24 -0
- data/lib/serverside/http/parsing.rb +175 -0
- data/lib/serverside/http/response.rb +91 -0
- data/lib/serverside/http/server.rb +194 -0
- data/lib/serverside/http/static.rb +72 -0
- data/lib/serverside/http.rb +14 -0
- data/lib/serverside/js.rb +173 -0
- data/lib/serverside/log.rb +79 -0
- data/lib/serverside/template.rb +5 -4
- data/lib/serverside/xml.rb +84 -0
- data/lib/serverside.rb +11 -2
- data/spec/core_ext_spec.rb +13 -58
- data/spec/daemon_spec.rb +61 -28
- data/spec/http_spec.rb +259 -0
- data/spec/template_spec.rb +9 -7
- metadata +42 -28
- data/CHANGELOG +0 -261
- data/lib/serverside/application.rb +0 -26
- data/lib/serverside/caching.rb +0 -91
- data/lib/serverside/connection.rb +0 -34
- data/lib/serverside/controllers.rb +0 -91
- data/lib/serverside/request.rb +0 -210
- data/lib/serverside/routing.rb +0 -133
- data/lib/serverside/server.rb +0 -27
- data/lib/serverside/static.rb +0 -82
- data/spec/caching_spec.rb +0 -318
- data/spec/cluster_spec.rb +0 -140
- data/spec/connection_spec.rb +0 -59
- data/spec/controllers_spec.rb +0 -142
- data/spec/request_spec.rb +0 -288
- data/spec/routing_spec.rb +0 -240
- data/spec/server_spec.rb +0 -40
- data/spec/static_spec.rb +0 -279
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'metaid'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module ServerSide
|
5
|
+
# Serializes data into a Javscript literal hash format. For example:
|
6
|
+
# ServerSide::JS.new {|j| j}
|
7
|
+
class JS
|
8
|
+
# blank slate
|
9
|
+
instance_methods.each do |m|
|
10
|
+
undef_method m unless (m =~ /^__|instance_eval|meta|respond_to|nil|is_a/)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Initializes a new document. A callback function name can be supplied to
|
14
|
+
# wrap the hash.
|
15
|
+
def initialize(callback = nil, &block)
|
16
|
+
@callback = callback
|
17
|
+
@stack = [self]
|
18
|
+
block.call(self) if block
|
19
|
+
end
|
20
|
+
|
21
|
+
# Catches calls to define keys and creates methods on the fly.
|
22
|
+
def method_missing(key, *args, &block)
|
23
|
+
value = nil
|
24
|
+
if block
|
25
|
+
@stack.push JS.new
|
26
|
+
block.call(self)
|
27
|
+
value = @stack.pop.__content
|
28
|
+
else
|
29
|
+
value = args.first
|
30
|
+
end
|
31
|
+
@stack.last.__add_hash_value(key, value)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def __add_hash_value(key, value)
|
36
|
+
@content ||= {}
|
37
|
+
@content[key] = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def __add_array_value(value)
|
41
|
+
@content ||= []
|
42
|
+
@content << value
|
43
|
+
end
|
44
|
+
|
45
|
+
def <<(value)
|
46
|
+
value = value.__content if value.respond_to?(:__content)
|
47
|
+
@stack.last.__add_array_value(value)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the current document content.
|
51
|
+
def __content
|
52
|
+
@content
|
53
|
+
end
|
54
|
+
|
55
|
+
NULL = 'null'.freeze
|
56
|
+
|
57
|
+
# Serializes the specified object into JS/JSON format.
|
58
|
+
def __serialize(obj, quote_keys)
|
59
|
+
case obj
|
60
|
+
when Time: JSON.generate(obj.to_f)
|
61
|
+
else
|
62
|
+
JSON.generate(obj)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the document content as a literal Javascript object. If a callback was specified,
|
67
|
+
# the object is wrapped in a Javascript function call.
|
68
|
+
def to_s
|
69
|
+
j = __serialize(@content, false)
|
70
|
+
@callback ? "#{@callback}(#{j});" : j
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the content in JSON format.
|
74
|
+
def to_json
|
75
|
+
__serialize(@content, true)
|
76
|
+
end
|
77
|
+
|
78
|
+
alias_method :inspect, :to_s
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
__END__
|
83
|
+
|
84
|
+
module ServerSide
|
85
|
+
# Serializes data into a Javscript literal hash format. For example:
|
86
|
+
# ServerSide::JS.new {|j| j}
|
87
|
+
class JS
|
88
|
+
# blank slate
|
89
|
+
instance_methods.each do |m|
|
90
|
+
undef_method m unless (m =~ /^__|instance_eval|meta|respond_to|nil|is_a/)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Initializes a new document. A callback function name can be supplied to
|
94
|
+
# wrap the hash.
|
95
|
+
def initialize(callback = nil, &block)
|
96
|
+
@callback = callback
|
97
|
+
@stack = [self]
|
98
|
+
block.call(self) if block
|
99
|
+
end
|
100
|
+
|
101
|
+
# Catches calls to define keys and creates methods on the fly.
|
102
|
+
def method_missing(key, *args, &block)
|
103
|
+
value = nil
|
104
|
+
if block
|
105
|
+
@stack.push JS.new
|
106
|
+
block.call(self)
|
107
|
+
value = @stack.pop.__content
|
108
|
+
else
|
109
|
+
value = args.first
|
110
|
+
end
|
111
|
+
@stack.last.__add_hash_value(key, value)
|
112
|
+
self
|
113
|
+
end
|
114
|
+
|
115
|
+
def __add_hash_value(key, value)
|
116
|
+
@content ||= {}
|
117
|
+
@content[key] = value
|
118
|
+
end
|
119
|
+
|
120
|
+
def __add_array_value(value)
|
121
|
+
@content ||= []
|
122
|
+
@content << value
|
123
|
+
end
|
124
|
+
|
125
|
+
def <<(value)
|
126
|
+
value = value.__content if value.respond_to?(:__js)
|
127
|
+
@stack.last.__add_array_value(value)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the current document content.
|
131
|
+
def __content
|
132
|
+
@content
|
133
|
+
end
|
134
|
+
|
135
|
+
NULL = 'null'.freeze
|
136
|
+
|
137
|
+
# Serializes the specified object into JS/JSON format.
|
138
|
+
def __serialize(obj, quote_keys)
|
139
|
+
if obj.nil?
|
140
|
+
NULL
|
141
|
+
elsif obj.is_a? Array
|
142
|
+
"[#{obj.map{|v| __serialize(v, quote_keys)}.join(', ')}]"
|
143
|
+
elsif obj.is_a? Hash
|
144
|
+
if quote_keys
|
145
|
+
fields = obj.to_a.map{|kv| "\"#{kv[0]}\": #{__serialize(kv[1], quote_keys)}"}
|
146
|
+
else
|
147
|
+
fields = obj.to_a.map{|kv| "#{kv[0]}: #{__serialize(kv[1], quote_keys)}"}
|
148
|
+
end
|
149
|
+
"{#{fields.join(', ')}}"
|
150
|
+
elsif obj.is_a? Symbol
|
151
|
+
obj.to_s
|
152
|
+
elsif obj.is_a? Time
|
153
|
+
obj.to_f
|
154
|
+
else
|
155
|
+
obj.inspect
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns the document content as a literal Javascript object. If a callback was specified,
|
160
|
+
# the object is wrapped in a Javascript function call.
|
161
|
+
def to_s
|
162
|
+
j = __serialize(@content, false)
|
163
|
+
@callback ? "#{@callback}(#{j});" : j
|
164
|
+
end
|
165
|
+
|
166
|
+
# Returns the content in JSON format.
|
167
|
+
def to_json
|
168
|
+
__serialize(@content, true)
|
169
|
+
end
|
170
|
+
|
171
|
+
alias_method :inspect, :to_s
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module ServerSide
|
4
|
+
@@logger = nil
|
5
|
+
|
6
|
+
def self.logger
|
7
|
+
@@logger
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.logger=(l)
|
11
|
+
@@logger = l
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.setup_stock_logger(logdev, shift_age = 0, shift_size = 1048576)
|
15
|
+
@@logger = Logger.new(logdev, shift_age, shift_size)
|
16
|
+
@@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
17
|
+
@@logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.logger_level=(level)
|
21
|
+
@@logger.level = level if @@logger
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.log(level, text)
|
25
|
+
@@logger.log(level, text) if @@logger
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.debug(text)
|
29
|
+
@@logger.debug(text) if @@logger
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.info(text)
|
33
|
+
@@logger.info(text) if @@logger
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.warn(text)
|
37
|
+
@@logger.warn(text) if @@logger
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.error(text)
|
41
|
+
@@logger.error(text) if @@logger
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.fatal(text)
|
45
|
+
@@logger.fatal(text) if @@logger
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.log_error(e)
|
49
|
+
if @@logger
|
50
|
+
@@logger.error("#{e.message}:\r\n" + e.backtrace.join("\r\n"))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
REFERER = "Referer".freeze
|
55
|
+
USER_AGENT = "User-Agent".freeze
|
56
|
+
HOST = "Host".freeze
|
57
|
+
HOST_REGEXP = /([^\:]*)(\:(.*))?$/
|
58
|
+
|
59
|
+
def self.log_request(c)
|
60
|
+
if @@logger
|
61
|
+
return unless request_line = c.request_line
|
62
|
+
req_line.chomp!
|
63
|
+
if c.method == :post && c.content_type == HTTP::Request::CONTENT_TYPE_URL_ENCODED
|
64
|
+
req_line << " (#{r.body})"
|
65
|
+
end
|
66
|
+
host = (r.request_headers[HOST] || "") =~ HOST_REGEXP ? $1 : ""
|
67
|
+
msg = "%s %s %s %s %s %s %s" % [
|
68
|
+
r.client_name,
|
69
|
+
host.inspect,
|
70
|
+
request_line.inspect,
|
71
|
+
r.status || '?',
|
72
|
+
r.content_length || '?',
|
73
|
+
(r.headers[REFERER] || "").inspect,
|
74
|
+
(r.headers[USER_AGENT] || "").inspect
|
75
|
+
]
|
76
|
+
@@logger.info(msg)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/serverside/template.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
require '
|
1
|
+
require 'rubygems'
|
2
|
+
require 'erubis'
|
2
3
|
|
3
4
|
module ServerSide
|
4
|
-
# The Template module implements an
|
5
|
-
# are cached and automatically reloaded if the file changes.
|
5
|
+
# The Template module implements an Erubis template rendering system.
|
6
|
+
# Templates are cached and automatically reloaded if the file changes.
|
6
7
|
class Template
|
7
8
|
# The @@templates variable caches templates in use. The values are
|
8
9
|
# arrays containing 2 objects: a file stamp (if the template comes from a
|
@@ -12,7 +13,7 @@ module ServerSide
|
|
12
13
|
# Caches a template for later use. The stamp parameter is used only when
|
13
14
|
# the content of a template file is stored.
|
14
15
|
def self.set(name, body, stamp = nil)
|
15
|
-
@@templates[name] = [stamp,
|
16
|
+
@@templates[name] = [stamp, Erubis::Eruby.new(body)]
|
16
17
|
end
|
17
18
|
|
18
19
|
# Validates the referenced template by checking its stamp. If the name
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'metaid'
|
2
|
+
|
3
|
+
module ServerSide
|
4
|
+
class XML
|
5
|
+
# blank slate
|
6
|
+
instance_methods.each {|m|
|
7
|
+
undef_method m unless (m =~ /^__|instance_eval|meta|respond_to/)}
|
8
|
+
|
9
|
+
TAG_LEFT_OPEN = '<'.freeze
|
10
|
+
TAG_LEFT_CLOSE = '</'.freeze
|
11
|
+
TAG_RIGHT = '>'.freeze
|
12
|
+
|
13
|
+
def __open_tag(tag, atts)
|
14
|
+
@doc << TAG_LEFT_OPEN
|
15
|
+
@doc << tag.to_s
|
16
|
+
@doc << __fmt_atts(atts) if atts
|
17
|
+
@doc << TAG_RIGHT
|
18
|
+
end
|
19
|
+
|
20
|
+
def __close_tag(tag)
|
21
|
+
@doc << TAG_LEFT_CLOSE
|
22
|
+
@doc << tag.to_s
|
23
|
+
@doc << TAG_RIGHT
|
24
|
+
end
|
25
|
+
|
26
|
+
def __value(value)
|
27
|
+
@doc << value.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
INSTRUCT_LEFT = '<?xml'.freeze
|
31
|
+
INSTRUCT_RIGHT = '?>'.freeze
|
32
|
+
|
33
|
+
def __instruct(arg)
|
34
|
+
@doc << INSTRUCT_LEFT
|
35
|
+
@doc << __fmt_atts(arg)
|
36
|
+
@doc << INSTRUCT_RIGHT
|
37
|
+
end
|
38
|
+
|
39
|
+
SPACE = ' '.freeze
|
40
|
+
|
41
|
+
def __fmt_atts(atts)
|
42
|
+
atts.inject('') {|m, i| m << " #{i[0]}=#{i[1].to_s.inspect}"}
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def initialize(tag = nil, atts = nil, &block)
|
47
|
+
@doc = ''
|
48
|
+
__open_tag(tag, atts) if tag
|
49
|
+
block.call(self) if block
|
50
|
+
__close_tag(tag) if tag
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(tag, *args, &block)
|
54
|
+
if block
|
55
|
+
__open_tag(tag, args.first)
|
56
|
+
block.call(self)
|
57
|
+
__close_tag(tag)
|
58
|
+
else
|
59
|
+
value, atts = args.pop, args.pop
|
60
|
+
subtags, atts = atts, nil if atts.is_a?(Array)
|
61
|
+
if subtags
|
62
|
+
__open_tag(tag, atts)
|
63
|
+
subtags.each {|k| __send__(k, value[k])}
|
64
|
+
__close_tag(tag)
|
65
|
+
else
|
66
|
+
__open_tag(tag, atts)
|
67
|
+
__value(value)
|
68
|
+
__close_tag(tag)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def instruct!(atts = nil)
|
75
|
+
__instruct(atts || {:version => "1.0", :encoding => "UTF-8"})
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_s
|
79
|
+
@doc
|
80
|
+
end
|
81
|
+
|
82
|
+
alias_method :inspect, :to_s
|
83
|
+
end
|
84
|
+
end
|
data/lib/serverside.rb
CHANGED
@@ -9,5 +9,14 @@
|
|
9
9
|
module ServerSide
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
lib_dir = File.join(File.dirname(__FILE__), 'serverside')
|
13
|
+
|
14
|
+
require File.join(lib_dir, 'core_ext')
|
15
|
+
require File.join(lib_dir, 'http')
|
16
|
+
require File.join(lib_dir, 'daemon')
|
17
|
+
require File.join(lib_dir, 'cluster')
|
18
|
+
require File.join(lib_dir, 'log')
|
19
|
+
require File.join(lib_dir, 'template')
|
20
|
+
require File.join(lib_dir, 'js')
|
21
|
+
require File.join(lib_dir, 'xml')
|
22
|
+
|
data/spec/core_ext_spec.rb
CHANGED
@@ -21,72 +21,27 @@ context "String" do
|
|
21
21
|
('touch'/'/me/'/'hold'/'/me').should == 'touch/me/hold/me'
|
22
22
|
end
|
23
23
|
|
24
|
-
specify "
|
24
|
+
specify "#underscore should turn camel-cased phrases to underscored ones" do
|
25
25
|
'CamelCase'.underscore.should == 'camel_case'
|
26
26
|
'Content-Type'.underscore.should == 'content_type'
|
27
27
|
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Symbol extensions
|
31
|
-
|
32
|
-
class Symbol
|
33
|
-
attr_reader :_to_s
|
34
|
-
end
|
35
|
-
|
36
|
-
context "Symbol.to_s" do
|
37
|
-
specify "should convert the symbol to a string" do
|
38
|
-
:abc_def.to_s.should == 'abc_def'
|
39
|
-
:def_ghi.to_s.should_be_instance_of String
|
40
|
-
:ghi_jkl.to_s.should == :ghi_jkl.id2name
|
41
|
-
end
|
42
|
-
|
43
|
-
specify "should cache the id2name value" do
|
44
|
-
:kwantz_mit_krantz._to_s.should_be_nil
|
45
|
-
:kwantz_mit_krantz.to_s
|
46
|
-
:kwantz_mit_krantz._to_s.should == :kwantz_mit_krantz.id2name
|
47
|
-
end
|
48
|
-
|
49
|
-
specify "should always return the same cached value" do
|
50
|
-
:item.to_s.should_be :item.to_s
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context "Proc.proc_tag" do
|
55
|
-
setup do
|
56
|
-
@l1 = lambda {1 + 1}
|
57
|
-
@l2 = lambda {1 + 1}
|
58
|
-
end
|
59
|
-
|
60
|
-
specify "should return a unique tag for the proc object" do
|
61
|
-
@l1.proc_tag.should_not_equal @l2.proc_tag
|
62
|
-
end
|
63
|
-
|
64
|
-
specify "should return the same tag always" do
|
65
|
-
@l1.proc_tag.should == @l1.proc_tag
|
66
|
-
end
|
67
28
|
|
68
|
-
specify "should
|
69
|
-
|
29
|
+
specify "#camelize should turn an underscore name to camelcase" do
|
30
|
+
'wowie_zowie'.camelize.should == 'WowieZowie'
|
70
31
|
end
|
71
32
|
end
|
72
33
|
|
73
|
-
context "
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
specify "should return the same tag always" do
|
84
|
-
@o1.const_tag.should == @o1.const_tag
|
85
|
-
@o2.const_tag.should == @o2.const_tag
|
34
|
+
context "Process.exists?" do
|
35
|
+
specify "should return false for a non-existing process" do
|
36
|
+
# bogus pid
|
37
|
+
pid = nil
|
38
|
+
while pid = rand(10000)
|
39
|
+
break if `ps #{pid}` !~ /#{pid}/
|
40
|
+
end
|
41
|
+
Process.exists?(pid).should be_false
|
86
42
|
end
|
87
43
|
|
88
|
-
specify "should return
|
89
|
-
|
90
|
-
@o2.const_tag.should == 'C' + @o2.object_id.to_s(36).upcase.sub('-', '_')
|
44
|
+
specify "should return true for an existing process" do
|
45
|
+
Process.exists?(Process.pid).should be_true
|
91
46
|
end
|
92
47
|
end
|
data/spec/daemon_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
__END__
|
2
|
+
|
1
3
|
require File.join(File.dirname(__FILE__), '../lib/serverside')
|
2
4
|
|
3
5
|
class TestDaemon < Daemon::Base
|
@@ -62,38 +64,69 @@ context "Daemon::PidFile" do
|
|
62
64
|
end
|
63
65
|
|
64
66
|
context "Daemon.control" do
|
65
|
-
|
67
|
+
teardown {Daemon.control(TestDaemon, :stop) rescue nil}
|
66
68
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
specify "should start and stop the daemon" do
|
70
|
+
Daemon::PidFile.remove(TestDaemon)
|
71
|
+
Daemon.control(TestDaemon, :start)
|
72
|
+
sleep 0.2
|
73
|
+
File.file?(TestDaemon.pid_fn).should == true
|
74
|
+
sleep 0.5
|
75
|
+
proc {Daemon::PidFile.recall(TestDaemon)}.should_not_raise
|
76
|
+
Daemon.control(TestDaemon, :stop)
|
77
|
+
sleep 0.2
|
78
|
+
File.file?(TestDaemon.result_fn).should == false
|
79
|
+
end
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
81
|
+
specify "should restart the daemon" do
|
82
|
+
Daemon::PidFile.remove(TestDaemon)
|
83
|
+
Daemon.control(TestDaemon, :start)
|
84
|
+
begin
|
85
|
+
sleep 1
|
86
|
+
pid1 = Daemon::PidFile.recall(TestDaemon)
|
87
|
+
Daemon.control(TestDaemon, :restart)
|
88
|
+
sleep 1
|
89
|
+
pid2 = Daemon::PidFile.recall(TestDaemon)
|
90
|
+
pid1.should_not == pid2
|
91
|
+
ensure
|
92
|
+
Daemon.control(TestDaemon, :stop)
|
93
|
+
Daemon::PidFile.remove(TestDaemon)
|
94
|
+
end
|
95
|
+
end
|
94
96
|
|
95
97
|
specify "should raise RuntimeError for invalid command" do
|
96
|
-
proc {Daemon.control(TestDaemon, :invalid)}.should_raise
|
98
|
+
proc {Daemon.control(TestDaemon, :invalid)}.should_raise
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "Daemon.alive?" do
|
103
|
+
teardown {Daemon.control(TestDaemon, :stop) rescue nil}
|
104
|
+
|
105
|
+
specify "should return false if not running" do
|
106
|
+
Daemon.alive?(TestDaemon).should_be false
|
107
|
+
end
|
108
|
+
|
109
|
+
specify "should return true if running" do
|
110
|
+
Daemon.control(TestDaemon, :start)
|
111
|
+
sleep 1
|
112
|
+
Daemon.alive?(TestDaemon).should_be true
|
113
|
+
sleep 1
|
114
|
+
Daemon.control(TestDaemon, :stop)
|
115
|
+
sleep 1
|
116
|
+
Daemon.alive?(TestDaemon).should_be false
|
117
|
+
end
|
118
|
+
|
119
|
+
specify "should return false if the daemon process is killed" do
|
120
|
+
Daemon.control(TestDaemon, :start)
|
121
|
+
sleep 1
|
122
|
+
pid = Daemon::PidFile.recall(TestDaemon)
|
123
|
+
Daemon.alive?(TestDaemon).should_be true
|
124
|
+
Process.kill("TERM", pid)
|
125
|
+
while `ps #{pid}` =~ /#{pid}/
|
126
|
+
sleep 0.2
|
127
|
+
end
|
128
|
+
Daemon.alive?(TestDaemon).should_be false
|
129
|
+
Daemon.control(TestDaemon, :stop)
|
97
130
|
end
|
98
131
|
end
|
99
132
|
|