build_status_server 0.8 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,6 @@
1
- # TODO
2
- # move all configuration stuff to Config
3
- # and just call config[:blaj] instead of if blah
4
1
  module BuildStatusServer
5
2
  class Server
6
- attr_reader :config, :store
3
+ attr_reader :config, :store, :udp_server
7
4
 
8
5
  def initialize(options = {})
9
6
  @config = Config.new
@@ -11,30 +8,11 @@ module BuildStatusServer
11
8
  end
12
9
 
13
10
  def listen
14
- sock = UDPSocket.new
15
- udp_server = config.udp_server
16
-
17
- begin
18
- sock.bind(udp_server["address"], udp_server["port"])
19
- rescue Errno::EADDRINUSE
20
- STDERR.puts <<-EOT
21
- There appears that another instance is running, or another process
22
- is listening at the same port (#{udp_server["address"]}:#{udp_server["port"]}
23
-
24
- EOT
25
- exit
26
- end
27
-
28
- puts "Listening on UDP #{udp_server["address"]}:#{udp_server["port"]}" if config.verbose
11
+ setup_udp_server
29
12
 
30
13
  begin
31
14
  while true
32
- data, addr = sock.recvfrom(2048)
33
-
34
- if process_job(data)
35
- status = process_all_statuses
36
- notify(status)
37
- end
15
+ process_loop
38
16
  end
39
17
  rescue Interrupt
40
18
  puts "Good bye."
@@ -45,6 +23,39 @@ is listening at the same port (#{udp_server["address"]}:#{udp_server["port"]}
45
23
 
46
24
  private
47
25
 
26
+ def process_loop
27
+ data, addr = udp_server.recvfrom(2048)
28
+
29
+ if process_job(data)
30
+ status = process_all_statuses
31
+ notify(status)
32
+ end
33
+ end
34
+
35
+ def setup_udp_server
36
+ address, port = config.udp_server["address"], config.udp_server["port"]
37
+ @udp_server = UDPSocket.new
38
+
39
+ begin
40
+ udp_server.bind(address, port)
41
+ rescue Errno::EADDRINUSE
42
+ STDERR.puts <<-EOT
43
+ There appears that another instance is running, or another process
44
+ is listening on the same port (#{address}:#{port})
45
+
46
+ EOT
47
+ exit
48
+ rescue Errno::EADDRNOTAVAIL
49
+ STDERR.puts <<-EOT
50
+ The address configured is not available (#{address})
51
+
52
+ EOT
53
+ exit
54
+ end
55
+
56
+ STDOUT.puts "Listening on UDP #{address}:#{port}" if config.verbose
57
+ end
58
+
48
59
  def load_store
49
60
  @store = begin
50
61
  YAML.load_file(config.store_file)
@@ -75,7 +86,8 @@ is listening at the same port (#{udp_server["address"]}:#{udp_server["port"]}
75
86
  status = job["build"]["status"]
76
87
 
77
88
  if phase == "FINISHED"
78
- STDOUT.puts "Got #{status} for #{build_name} on #{Time.now} [#{job.inspect}]" if config.verbose
89
+ # Got SUCCESS for topic_action_master on Tue May 01 12:02:31 -0400 2012 []
90
+ STDOUT.puts "Got #{status} for #{build_name} on #{Time.now} [#{job_internals(job)}]" if config.verbose
79
91
  case status
80
92
  when "SUCCESS", "FAILURE"
81
93
  load_store
@@ -84,12 +96,18 @@ is listening at the same port (#{udp_server["address"]}:#{udp_server["port"]}
84
96
  return true
85
97
  end
86
98
  else
87
- STDOUT.puts "Started for #{build_name} on #{Time.now} [#{job.inspect}]" if config.verbose
99
+ # Started for topic_action_master on Tue May 01 12:00:30 -0400 2012 [{"name"=>"topic_action_master", "url"=>"job/topic_action_master/", "build"=>{"number"=>98, "url"=>"job/topic_action_master/98/", "phase"= >"STARTED", "full_url"=>"http://ci.berman.challengepost.com/job/topic_action_master/98/"}}]
100
+ # Started for topic_action_master on Tue May 01 12:02:31 -0400 2012 [{"name"=>"topic_action_master", "url"=>"job/topic_action_master/", "build"=>{"number"=>98, "url"=>"job/topic_action_master/98/", "status" =>"SUCCESS", "phase"=>"COMPLETED", "full_url"=>"http://ci.berman.challengepost.com/job/topic_action_master/98/"}}]
101
+ STDOUT.puts "Started for #{build_name} on #{Time.now} [#{job_internals(job)}]" if config.verbose
88
102
  end
89
103
 
90
104
  return false
91
105
  end
92
106
 
107
+ def job_internals(job)
108
+ "build=>#{job["build"]["number"]}, status=>#{job["build"]["status"]}"
109
+ end
110
+
93
111
  def should_process_build(build_name)
94
112
  # If mask exists, then ...
95
113
  ! (
@@ -103,7 +121,7 @@ is listening at the same port (#{udp_server["address"]}:#{udp_server["port"]}
103
121
  def process_all_statuses
104
122
  pass = true
105
123
 
106
- @store.values.each do |val|
124
+ store.values.each do |val|
107
125
  pass &&= (val == "pass" || val == "SUCCESS")
108
126
  end
109
127
 
@@ -112,10 +130,12 @@ is listening at the same port (#{udp_server["address"]}:#{udp_server["port"]}
112
130
 
113
131
  def notify(status)
114
132
  tcp_client = config.tcp_client
133
+ tcp_client["attempts"] ||= 2
115
134
 
116
135
  attempts = 0
117
136
  light = status ? tcp_client["pass"] : tcp_client["fail"]
118
137
 
138
+ client = nil
119
139
  begin
120
140
  timeout(5) do
121
141
  attempts += 1
@@ -123,39 +143,18 @@ is listening at the same port (#{udp_server["address"]}:#{udp_server["port"]}
123
143
  client.print "GET #{light} HTTP/1.0\n\n"
124
144
  answer = client.gets(nil)
125
145
  STDOUT.puts answer if config.verbose
126
- client.close
127
146
  end
128
147
  rescue Timeout::Error => ex
129
148
  STDERR.puts "Error: #{ex} while trying to send #{light}"
130
- retry unless attempts > 2
149
+ retry unless attempts > tcp_client["attempts"]
131
150
  rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => ex
132
151
  STDERR.puts "Error: #{ex} while trying to send #{light}"
133
152
  STDERR.puts "Will wait for 2 seconds and try again..."
134
153
  sleep 2
135
- retry unless attempts > 2
154
+ retry unless attempts > tcp_client["attempts"]
155
+ ensure
156
+ client.close if client
136
157
  end
137
158
  end
138
159
  end
139
160
  end
140
-
141
- __END__
142
-
143
- Example payload:
144
- {
145
- "name":"test",
146
- "url":"job/test/",
147
- "build":{
148
- "full_url":"http://cronus.local:3001/job/test/20/",
149
- "number":20,
150
- "phase":"FINISHED",
151
- "status":"SUCCESS",
152
- "url":"job/test/20/"
153
- }
154
- }
155
-
156
- We're getting this error once in a while:
157
- /usr/local/lib/ruby/1.8/timeout.rb:64:in `notify': execution expired (Timeout::Error)
158
- from /home/jcmuller/build_notifier/lib/server.rb:102:in `notify'
159
- from /home/jcmuller/build_notifier/lib/server.rb:33:in `listen'
160
- from bin/server:5
161
-
@@ -0,0 +1,32 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>version.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="../build_status_server.html">build_status_server.rb</a>
16
+ <a class="source" href="config.html">config.rb</a>
17
+ <a class="source" href="server.html">server.rb</a>
18
+ <a class="source" href="version.html">version.rb</a>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <table cellspacing=0 cellpadding=0>
23
+ <thead>
24
+ <tr>
25
+ <th class=docs><h1>version.rb</h1></th>
26
+ <th class=code></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ </table>
31
+ </div>
32
+ </body>
@@ -1,3 +1,3 @@
1
1
  module BuildStatusServer
2
- VERSION = "0.8"
2
+ VERSION = "0.9"
3
3
  end
@@ -1,6 +1,6 @@
1
- require 'spec_helper'
2
- require 'build_status_server'
3
- require 'tempfile'
1
+ require "spec_helper"
2
+ require "build_status_server"
3
+ require "tempfile"
4
4
 
5
5
  describe BuildStatusServer::Config do
6
6
  let(:config) { BuildStatusServer::Config.new }
@@ -15,7 +15,7 @@ describe BuildStatusServer::Config do
15
15
  it "should set the config values from yaml file" do
16
16
  config.should_receive(:load_config_file).and_return(YAML.load(config.send(:get_example_config)))
17
17
  config.load
18
- config.udp_server.should == {'address' => '127.0.0.1', 'port' => 1234}
18
+ config.udp_server.should == {"address" => "127.0.0.1", "port" => 1234}
19
19
  config.verbose.should == false
20
20
  end
21
21
  end
@@ -24,7 +24,7 @@ describe BuildStatusServer::Config do
24
24
  it "should load the yaml file passed in as a file argument" do
25
25
  file_name = nil
26
26
 
27
- Tempfile.open('config') do |f|
27
+ Tempfile.open(["config", ".yml"]) do |f|
28
28
  f.puts "---"
29
29
  f.puts "key: value"
30
30
  f.puts "key2: value2"
@@ -39,7 +39,7 @@ describe BuildStatusServer::Config do
39
39
 
40
40
  it "should try to load paths from the locations to try" do
41
41
  file_name = nil
42
- Tempfile.open("config") do |f|
42
+ Tempfile.open(["config", ".yml"]) do |f|
43
43
  f.puts "---"
44
44
  f.puts "key: value"
45
45
  f.puts "key2: value2"
@@ -60,7 +60,7 @@ describe BuildStatusServer::Config do
60
60
 
61
61
  it "should throw an exception if the config file isn't a hash" do
62
62
  file_name = nil
63
- Tempfile.open(file_name) do |f|
63
+ Tempfile.open(["base", ".yml"]) do |f|
64
64
  f.puts "YADDA YADDA"
65
65
  file_name = f.path
66
66
  end
@@ -5,12 +5,101 @@ describe BuildStatusServer::Server do
5
5
  let(:server) { BuildStatusServer::Server.new }
6
6
 
7
7
  before do
8
- STDERR.should_receive :puts
8
+ STDERR.should_receive(:puts)
9
9
  end
10
10
 
11
11
  describe "#listen"
12
12
 
13
13
  context "private methods" do
14
+
15
+ describe "#setup_udp_server" do
16
+ it "reads the udp_server options from configuration file" do
17
+ server.config.stub!(:udp_server).and_return({"address" => "address", "port" => "port"})
18
+ socket = mock(:udp_socket)
19
+ socket.should_receive(:bind).with("address", "port")
20
+ UDPSocket.should_receive(:new).and_return(socket)
21
+
22
+ server.send(:setup_udp_server)
23
+ end
24
+
25
+ it "instantiates a UDPSocket object and binds it to address and port" do
26
+ server.config.stub!(:udp_server).and_return({"address" => "127.0.0.1", "port" => "9999"})
27
+
28
+ server.send(:setup_udp_server)
29
+
30
+ client = UDPSocket.new
31
+ client.connect("127.0.0.1", 9999)
32
+ client.send "hello, world!", 0
33
+ msg = server.udp_server.recvfrom(13)
34
+
35
+ msg[0].should == "hello, world!"
36
+ ["AF_INET", "127.0.0.1"].each do |e|
37
+ msg[1].should include e
38
+ end
39
+ end
40
+
41
+ it "should show message and exit when connecting to address not available" do
42
+ server.config.stub!(:udp_server).and_return({"address" => "192.192.192.192", "port" => "9999"})
43
+
44
+ STDERR.should_receive(:puts).with("The address configured is not available (192.192.192.192)\n\n")
45
+ server.should_receive(:exit)
46
+
47
+ server.send(:setup_udp_server)
48
+ end
49
+
50
+ it "it recovers from an address in use exception" do
51
+ server.config.stub!(:udp_server).and_return({"address" => "127.0.0.1", "port" => "9999"})
52
+
53
+ socket = mock(:udp_socket)
54
+ socket.should_receive(:bind).and_raise(Errno::EADDRINUSE)
55
+ UDPSocket.should_receive(:new).and_return(socket)
56
+
57
+ STDERR.should_receive(:puts).with("There appears that another instance is running, or another process\nis listening on the same port (127.0.0.1:9999)\n\n")
58
+ server.should_receive(:exit)
59
+ server.send(:setup_udp_server)
60
+ end
61
+
62
+ it "if verbose is enabled, show message" do
63
+ server.config.stub!(:udp_server).and_return({"address" => "address", "port" => "port"})
64
+ socket = mock(:udp_socket)
65
+ socket.should_receive(:bind).with("address", "port")
66
+ UDPSocket.should_receive(:new).and_return(socket)
67
+
68
+ server.config.stub!(:verbose).and_return(true)
69
+ STDOUT.should_receive(:puts).with("Listening on UDP address:port")
70
+
71
+ server.send(:setup_udp_server)
72
+ end
73
+ end
74
+
75
+ describe "#process_loop" do
76
+ it "should process all statuses and notify when process job returns true" do
77
+ socket = mock(:udp_socket)
78
+ socket.stub!(:recvfrom).and_return("data", "addr")
79
+
80
+ server.should_receive(:udp_server).and_return(socket)
81
+ server.should_receive(:process_job).with("data").and_return(true)
82
+
83
+ server.should_receive(:process_all_statuses).and_return("status")
84
+ server.should_receive(:notify).with("status")
85
+
86
+ server.send(:process_loop)
87
+ end
88
+
89
+ it "should not process all statuses or notify when process job returns false" do
90
+ socket = mock(:udp_socket)
91
+ socket.stub!(:recvfrom).and_return("data", "addr")
92
+
93
+ server.should_receive(:udp_server).and_return(socket)
94
+ server.should_receive(:process_job).with("data").and_return(false)
95
+
96
+ server.should_not_receive(:process_all_statuses)
97
+ server.should_not_receive(:notify)
98
+
99
+ server.send(:process_loop)
100
+ end
101
+ end
102
+
14
103
  describe "#load_store" do
15
104
  before do
16
105
  server.config.stub!(:store_file).and_return("/tmp/build")
@@ -38,19 +127,12 @@ describe BuildStatusServer::Server do
38
127
  end
39
128
  end
40
129
 
41
- describe "#notify"
42
- describe "#process_all_statuses"
43
- describe "#process_job"
44
-
45
130
  describe "#should_process_build" do
46
131
  context "when mask exists" do
47
- before do
48
- server.stub!(:mask).and_return(%r{.*(?:master).*})
49
- end
50
132
 
51
133
  context "when policy is include" do
52
134
  before do
53
- server.stub!(:mask_policy).and_return("include")
135
+ server.config.stub!(:mask).and_return({"policy" => "include", "regex" => %r{.*(?:master).*}})
54
136
  end
55
137
 
56
138
  it "ignores builds if mask doesn't match build name" do
@@ -64,7 +146,7 @@ describe BuildStatusServer::Server do
64
146
 
65
147
  context "when policy is exclude" do
66
148
  before do
67
- server.config.stub!(:mask).and_return({"policy" => "exclude", "regex" => /.*(?:master).*/})
149
+ server.config.stub!(:mask).and_return({"policy" => "exclude", "regex" => %r{.*(?:master).*}})
68
150
  end
69
151
 
70
152
  it "ignores builds if mask matches build name" do
@@ -105,7 +187,7 @@ describe BuildStatusServer::Server do
105
187
  end
106
188
  end
107
189
 
108
- context "when mask doesn't" do
190
+ context "when mask regex doesn't" do
109
191
  before do
110
192
  server.config.stub!(:mask).and_return({"policy" => "include", "regex" => nil})
111
193
  end
@@ -115,6 +197,201 @@ describe BuildStatusServer::Server do
115
197
  end
116
198
  end
117
199
  end
200
+
201
+ describe "#process_job" do
202
+ it "returns false if should_process_build returns false" do
203
+ server.should_receive(:should_process_build).and_return(false)
204
+ server.send(:process_job).should be_false
205
+ end
206
+
207
+ it "returns false and says so on stderr if payload doesn't have a hash for build" do
208
+ server.should_receive(:should_process_build).and_return(true)
209
+ JSON.should_receive(:parse).and_return({"build" => "Not a hash!"})
210
+ STDERR.should_receive(:puts).with("Pinged with an invalid payload")
211
+ server.send(:process_job).should be_false
212
+ end
213
+
214
+ it "returns false and says that the we got the job started when phase is FINISHED but status isn't success nor failure" do
215
+ server.config.should_receive(:verbose).and_return(true)
216
+ server.should_receive(:should_process_build).and_return(true)
217
+ JSON.should_receive(:parse).with("{}").and_return({
218
+ "name" => "name",
219
+ "build" => { "phase" => "FINISHED", "status" => "some status", "number" => "number" }
220
+ })
221
+ Time.should_receive(:now).and_return("this is the time")
222
+ STDOUT.should_receive(:puts).with('Got some status for name on this is the time [build=>number, status=>some status]')
223
+ server.send(:process_job).should be_false
224
+ end
225
+
226
+ it "returns false and says that the job started when the phase isn't finished" do
227
+ server.config.should_receive(:verbose).and_return(true)
228
+ server.should_receive(:should_process_build).and_return(true)
229
+ JSON.should_receive(:parse).with("{}").and_return({
230
+ "name" => "name",
231
+ "build" => { "phase" => "STARTED", "status" => "some status", "number" => "number" }
232
+ })
233
+ Time.should_receive(:now).and_return("this is the time")
234
+ STDOUT.should_receive(:puts).with("Started for name on this is the time [build=>number, status=>some status]")
235
+ server.send(:process_job).should be_false
236
+ end
237
+
238
+ context "phase is FINISHED and status is either SUCCESS or FAILURE" do
239
+ before do
240
+ server.config.should_receive(:verbose).and_return(true)
241
+ server.should_receive(:should_process_build).and_return(true)
242
+ Time.should_receive(:now).and_return("this is the time")
243
+ YAML.should_receive(:load_file).and_return({})
244
+ File.should_receive(:open)
245
+ end
246
+
247
+ it "should return true and write yaml file when phase is FINISHED and status is SUCCESS" do
248
+ JSON.should_receive(:parse).with("{}").and_return({
249
+ "name" => "name",
250
+ "build" => { "phase" => "FINISHED", "status" => "SUCCESS", "number" => "number" }
251
+ })
252
+ STDOUT.should_receive(:puts).with("Got SUCCESS for name on this is the time [build=>number, status=>SUCCESS]")
253
+
254
+ server.send(:process_job).should be_true
255
+ end
256
+
257
+ it "should return true and write yaml file when phase is FINISHED and status is FAILURE" do
258
+ JSON.should_receive(:parse).with("{}").and_return({
259
+ "name" => "name",
260
+ "build" => { "phase" => "FINISHED", "status" => "FAILURE", "number" => "number" }
261
+ })
262
+ STDOUT.should_receive(:puts).with("Got FAILURE for name on this is the time [build=>number, status=>FAILURE]")
263
+
264
+ server.send(:process_job).should be_true
265
+ end
266
+ end
267
+ end
268
+
269
+ describe "#notify" do
270
+ let(:client) { mock(:client) }
271
+
272
+ context "no exceptions" do
273
+ before do
274
+ options = {
275
+ "pass" => "pass",
276
+ "fail" => "fail",
277
+ "host" => "host",
278
+ "port" => "port"
279
+ }
280
+ config = mock(:config)
281
+ config.should_receive(:tcp_client).and_return(options)
282
+ config.should_receive(:verbose).and_return(true)
283
+
284
+ server.should_receive(:config).twice.and_return(config)
285
+
286
+ STDOUT.should_receive(:puts).with("answer")
287
+
288
+ client.should_receive(:gets).and_return("answer")
289
+ client.should_receive(:close)
290
+
291
+ TCPSocket.should_receive(:new).with("host", "port").and_return(client)
292
+ end
293
+
294
+ it "should send passing packet to tcp socket when status is true" do
295
+ client.should_receive(:print).with("GET pass HTTP/1.0\n\n")
296
+ server.send(:notify, true)
297
+ end
298
+
299
+ it "should send failing packet to tcp socket when status is false" do
300
+ client.should_receive(:print).with("GET fail HTTP/1.0\n\n")
301
+ server.send(:notify, false)
302
+ end
303
+ end
304
+
305
+ context "exceptions" do
306
+ before do
307
+ options = {
308
+ "fail" => "fail",
309
+ "host" => "host",
310
+ "port" => "port",
311
+ "attempts" => 2
312
+ }
313
+ config = mock(:config)
314
+ config.should_receive(:tcp_client).and_return(options)
315
+ config.should_receive(:verbose).and_return(false)
316
+
317
+ server.should_receive(:config).twice.and_return(config)
318
+ client.should_receive(:close)
319
+
320
+ client.should_receive(:gets).and_return("answer")
321
+ end
322
+
323
+ it "should time out and retry 2 times" do
324
+ TCPSocket.should_receive(:new).exactly(3).with("host", "port").and_return(client)
325
+ STDERR.should_receive(:puts).exactly(2).with("Error: Timeout::Error while trying to send fail")
326
+ client.should_receive(:print).exactly(2).with("GET fail HTTP/1.0\n\n").and_raise(Timeout::Error)
327
+ client.should_receive(:print).with("GET fail HTTP/1.0\n\n")
328
+
329
+ server.send(:notify, false)
330
+ end
331
+
332
+ it "should not connect and retry 2 times" do
333
+ STDERR.should_receive(:puts).with("Error: Connection refused while trying to send fail")
334
+ STDERR.should_receive(:puts).with("Error: No route to host while trying to send fail")
335
+ STDERR.should_receive(:puts).exactly(2).with("Will wait for 2 seconds and try again...")
336
+
337
+ TCPSocket.should_receive(:new).with("host", "port").and_raise(Errno::ECONNREFUSED)
338
+ TCPSocket.should_receive(:new).with("host", "port").and_raise(Errno::EHOSTUNREACH)
339
+ TCPSocket.should_receive(:new).with("host", "port").and_return(client)
340
+
341
+ server.should_receive(:sleep).twice.with(2)
342
+
343
+ client.should_receive(:print).with("GET fail HTTP/1.0\n\n")
344
+
345
+ server.send(:notify, false)
346
+ end
347
+ end
348
+
349
+ it "should gracefully recover if config doesn't have attempts configured" do
350
+ options = {
351
+ "fail" => "fail",
352
+ "host" => "host",
353
+ "port" => "port"
354
+ }
355
+
356
+ config = mock(:config)
357
+ config.should_receive(:tcp_client).and_return(options)
358
+ config.should_receive(:verbose).and_return(false)
359
+
360
+ server.should_receive(:config).twice.and_return(config)
361
+ client.should_receive(:close)
362
+
363
+ client.should_receive(:gets).and_return("answer")
364
+ TCPSocket.should_receive(:new).exactly(3).with("host", "port").and_return(client)
365
+ STDERR.should_receive(:puts).exactly(2).with("Error: Timeout::Error while trying to send fail")
366
+ client.should_receive(:print).exactly(2).with("GET fail HTTP/1.0\n\n").and_raise(Timeout::Error)
367
+ client.should_receive(:print).with("GET fail HTTP/1.0\n\n")
368
+
369
+ server.send(:notify, false)
370
+ end
371
+ end
372
+
373
+ describe "#process_all_statuses" do
374
+ it "should return true if all values are SUCCESS" do
375
+ server.should_receive(:store).and_return(mock(:blah, :values => %w(SUCCESS SUCCESS SUCCESS)))
376
+ server.send(:process_all_statuses).should be_true
377
+ end
378
+
379
+ it "should return true if all values are pass" do
380
+ server.should_receive(:store).and_return(mock(:blah, :values => %w(pass pass pass)))
381
+ server.send(:process_all_statuses).should be_true
382
+ end
383
+
384
+ it "should return true if some values are pass and some are SUCCESS" do
385
+ server.should_receive(:store).and_return(mock(:blah, :values => %w(SUCCESS pass SUCCESS)))
386
+ server.send(:process_all_statuses).should be_true
387
+ end
388
+
389
+ it "should return false if at least one value isn't pass or SUCCESS" do
390
+ server.should_receive(:store).and_return(mock(:blah, :values => %w(SUCCESS blah SUCCESS)))
391
+ server.send(:process_all_statuses).should be_false
392
+ end
393
+ end
394
+
118
395
  end
119
396
  end
120
397