testbot_instructure 0.7.8
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.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/CHANGELOG +264 -0
- data/Gemfile +3 -0
- data/README.markdown +141 -0
- data/Rakefile +35 -0
- data/bin/testbot +59 -0
- data/lib/generators/testbot/templates/testbot.rake.erb +35 -0
- data/lib/generators/testbot/templates/testbot.yml.erb +45 -0
- data/lib/generators/testbot/testbot_generator.rb +19 -0
- data/lib/railtie.rb +16 -0
- data/lib/requester/requester.rb +171 -0
- data/lib/runner/job.rb +112 -0
- data/lib/runner/runner.rb +222 -0
- data/lib/runner/safe_result_text.rb +29 -0
- data/lib/server/build.rb +36 -0
- data/lib/server/group.rb +48 -0
- data/lib/server/job.rb +64 -0
- data/lib/server/memory_model.rb +91 -0
- data/lib/server/runner.rb +47 -0
- data/lib/server/server.rb +103 -0
- data/lib/server/status/javascripts/jquery-1.4.4.min.js +167 -0
- data/lib/server/status/status.html +48 -0
- data/lib/server/status/stylesheets/status.css +14 -0
- data/lib/shared/adapters/adapter.rb +27 -0
- data/lib/shared/adapters/cucumber_adapter.rb +91 -0
- data/lib/shared/adapters/helpers/ruby_env.rb +47 -0
- data/lib/shared/adapters/rspec2_adapter.rb +61 -0
- data/lib/shared/adapters/rspec_adapter.rb +79 -0
- data/lib/shared/adapters/test_unit_adapter.rb +44 -0
- data/lib/shared/color.rb +16 -0
- data/lib/shared/simple_daemonize.rb +25 -0
- data/lib/shared/ssh_tunnel.rb +36 -0
- data/lib/shared/testbot.rb +132 -0
- data/lib/shared/version.rb +12 -0
- data/lib/tasks/testbot.rake +30 -0
- data/lib/testbot.rb +2 -0
- data/test/fixtures/local/Rakefile +7 -0
- data/test/fixtures/local/config/testbot.yml +5 -0
- data/test/fixtures/local/log/test.log +0 -0
- data/test/fixtures/local/script/spec +2 -0
- data/test/fixtures/local/spec/models/car_spec.rb +0 -0
- data/test/fixtures/local/spec/models/house_spec.rb +0 -0
- data/test/fixtures/local/spec/spec.opts +0 -0
- data/test/fixtures/local/tmp/restart.txt +0 -0
- data/test/integration_test.rb +55 -0
- data/test/requester/requester_test.rb +407 -0
- data/test/requester/testbot.yml +7 -0
- data/test/requester/testbot_with_erb.yml +2 -0
- data/test/runner/job_test.rb +94 -0
- data/test/runner/safe_result_text_test.rb +20 -0
- data/test/server/group_test.rb +43 -0
- data/test/server/server_test.rb +511 -0
- data/test/shared/adapters/adapter_test.rb +22 -0
- data/test/shared/adapters/cucumber_adapter_test.rb +72 -0
- data/test/shared/adapters/helpers/ruby_env_test.rb +108 -0
- data/test/shared/adapters/rspec_adapter_test.rb +109 -0
- data/test/shared/testbot_test.rb +185 -0
- data/testbot.gemspec +34 -0
- metadata +313 -0
@@ -0,0 +1,511 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../lib/server/server'))
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rack/test'
|
4
|
+
require 'shoulda'
|
5
|
+
require 'flexmock/test_unit'
|
6
|
+
|
7
|
+
set :environment, :test
|
8
|
+
|
9
|
+
module Testbot::Server
|
10
|
+
|
11
|
+
class ServerTest < Test::Unit::TestCase
|
12
|
+
include Rack::Test::Methods
|
13
|
+
|
14
|
+
def setup
|
15
|
+
Job.delete_all
|
16
|
+
Runner.delete_all
|
17
|
+
Build.delete_all
|
18
|
+
end
|
19
|
+
|
20
|
+
def app
|
21
|
+
Sinatra::Application
|
22
|
+
end
|
23
|
+
|
24
|
+
context "POST /builds" do
|
25
|
+
|
26
|
+
should "create a build and return its id" do
|
27
|
+
flexmock(Runner).should_receive(:total_instances).and_return(2)
|
28
|
+
post '/builds', :files => 'spec/models/car_spec.rb spec/models/house_spec.rb', :root => 'server:/path/to/project', :type => 'spec', :available_runner_usage => "100%", :project => 'things', :sizes => "10 20", :jruby => false
|
29
|
+
|
30
|
+
first_build = Build.all.first
|
31
|
+
assert last_response.ok?
|
32
|
+
|
33
|
+
assert_equal first_build.id.to_s, last_response.body
|
34
|
+
assert_equal 'spec/models/car_spec.rb spec/models/house_spec.rb', first_build.files
|
35
|
+
assert_equal '10 20', first_build.sizes
|
36
|
+
assert_equal 'server:/path/to/project', first_build.root
|
37
|
+
assert_equal 'spec', first_build.type
|
38
|
+
assert_equal 'things', first_build.project
|
39
|
+
assert_equal 0, first_build.jruby
|
40
|
+
assert_equal '', first_build.results
|
41
|
+
assert_equal true, first_build.success
|
42
|
+
end
|
43
|
+
|
44
|
+
should "create jobs from the build based on the number of total instances" do
|
45
|
+
flexmock(Runner).should_receive(:total_instances).and_return(2)
|
46
|
+
flexmock(Group).should_receive(:build).with(["spec/models/car_spec.rb", "spec/models/car2_spec.rb", "spec/models/house_spec.rb", "spec/models/house2_spec.rb"], [ 1, 1, 1, 1 ], 2, 'spec').once.and_return([
|
47
|
+
["spec/models/car_spec.rb", "spec/models/car2_spec.rb"],
|
48
|
+
["spec/models/house_spec.rb", "spec/models/house2_spec.rb"]
|
49
|
+
])
|
50
|
+
|
51
|
+
post '/builds', :files => 'spec/models/car_spec.rb spec/models/car2_spec.rb spec/models/house_spec.rb spec/models/house2_spec.rb', :root => 'server:/path/to/project', :type => 'spec', :available_runner_usage => "100%", :project => 'things', :sizes => "1 1 1 1", :jruby => true
|
52
|
+
|
53
|
+
assert_equal 2, Job.count
|
54
|
+
first_job, last_job = Job.all
|
55
|
+
assert_equal 'spec/models/car_spec.rb spec/models/car2_spec.rb', first_job.files
|
56
|
+
assert_equal 'spec/models/house_spec.rb spec/models/house2_spec.rb', last_job.files
|
57
|
+
|
58
|
+
assert_equal 'server:/path/to/project', first_job.root
|
59
|
+
assert_equal 'spec', first_job.type
|
60
|
+
assert_equal 'things', first_job.project
|
61
|
+
assert_equal 1, first_job.jruby
|
62
|
+
assert_equal Build.all.first, first_job.build
|
63
|
+
end
|
64
|
+
|
65
|
+
should "return a 503 error if there are no known runners" do
|
66
|
+
flexmock(Runner).should_receive(:total_instances).and_return(0)
|
67
|
+
post '/builds', :files => 'spec/models/car_spec.rb spec/models/car2_spec.rb spec/models/house_spec.rb spec/models/house2_spec.rb', :root => 'server:/path/to/project', :type => 'spec', :available_runner_usage => "100%", :project => 'things', :sizes => "1 1 1 1", :jruby => true
|
68
|
+
assert_equal 0, Job.count
|
69
|
+
assert_equal 503, last_response.status
|
70
|
+
assert_equal "No runners available", last_response.body
|
71
|
+
end
|
72
|
+
|
73
|
+
should "only use resources according to available_runner_usage" do
|
74
|
+
flexmock(Runner).should_receive(:total_instances).and_return(4)
|
75
|
+
flexmock(Group).should_receive(:build).with(["spec/models/car_spec.rb", "spec/models/car2_spec.rb", "spec/models/house_spec.rb", "spec/models/house2_spec.rb"], [ 1, 1, 1, 1 ], 2, 'spec').and_return([])
|
76
|
+
post '/builds', :files => 'spec/models/car_spec.rb spec/models/car2_spec.rb spec/models/house_spec.rb spec/models/house2_spec.rb', :root => 'server:/path/to/project', :type => 'spec', :sizes => "1 1 1 1", :available_runner_usage => "50%"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
context "GET /builds/:id" do
|
82
|
+
|
83
|
+
should 'return the build status' do
|
84
|
+
build = Build.create(:done => false, :results => "testbot5\n..........\ncompleted", :success => false)
|
85
|
+
get "/builds/#{build.id}"
|
86
|
+
assert_equal true, last_response.ok?
|
87
|
+
assert_equal ({ "done" => false, "results" => "testbot5\n..........\ncompleted", "success" => false }),
|
88
|
+
JSON.parse(last_response.body)
|
89
|
+
end
|
90
|
+
|
91
|
+
should 'remove a build that is done' do
|
92
|
+
build = Build.create(:done => true)
|
93
|
+
get "/builds/#{build.id}"
|
94
|
+
assert_equal true, JSON.parse(last_response.body)['done']
|
95
|
+
assert_equal 0, Build.count
|
96
|
+
end
|
97
|
+
|
98
|
+
should 'remove all related jobs of a build that is done' do
|
99
|
+
build = Build.create(:done => true)
|
100
|
+
related_job = Job.create(:build => build)
|
101
|
+
other_job = Job.create(:build => nil)
|
102
|
+
get "/builds/#{build.id}"
|
103
|
+
assert !Job.find(related_job.id)
|
104
|
+
assert Job.find(other_job.id)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
context "GET /jobs/next" do
|
110
|
+
|
111
|
+
should "be able to return a job and mark it as taken" do
|
112
|
+
build = Build.create
|
113
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :root => 'server:/project', :type => 'spec', :build => build, :project => 'things', :jruby => 1
|
114
|
+
|
115
|
+
get '/jobs/next', :version => Testbot.version
|
116
|
+
assert last_response.ok?
|
117
|
+
|
118
|
+
assert_equal [ job1.id, build.id, "things", "server:/project", "spec", "jruby", "spec/models/car_spec.rb" ].join(','), last_response.body
|
119
|
+
assert job1.taken_at != nil
|
120
|
+
end
|
121
|
+
|
122
|
+
should "not return a job that has already been taken" do
|
123
|
+
build = Build.create
|
124
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now, :type => 'spec', :build => build
|
125
|
+
job2 = Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :build => build, :project => 'things', :jruby => 0
|
126
|
+
get '/jobs/next', :version => Testbot.version
|
127
|
+
assert last_response.ok?
|
128
|
+
assert_equal [ job2.id, build.id, "things", "server:/project", "spec", "ruby", "spec/models/house_spec.rb" ].join(','), last_response.body
|
129
|
+
assert job2.taken_at != nil
|
130
|
+
end
|
131
|
+
|
132
|
+
should "not return a job if there isnt any" do
|
133
|
+
get '/jobs/next', :version => Testbot.version
|
134
|
+
assert last_response.ok?
|
135
|
+
assert_equal '', last_response.body
|
136
|
+
end
|
137
|
+
|
138
|
+
should "save which runner takes a job" do
|
139
|
+
job = Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :build => Build.create
|
140
|
+
get '/jobs/next', :version => Testbot.version
|
141
|
+
assert_equal Runner.first, job.taken_by
|
142
|
+
end
|
143
|
+
|
144
|
+
should "save information about the runners" do
|
145
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini.local', :uid => "00:01:...", :idle_instances => 2, :max_instances => 4
|
146
|
+
runner = Runner.first
|
147
|
+
assert_equal Testbot.version, runner.version
|
148
|
+
assert_equal '127.0.0.1', runner.ip
|
149
|
+
assert_equal 'macmini.local', runner.hostname
|
150
|
+
assert_equal '00:01:...', runner.uid
|
151
|
+
assert_equal 2, runner.idle_instances
|
152
|
+
assert_equal 4, runner.max_instances
|
153
|
+
assert (Time.now - 5) < runner.last_seen_at
|
154
|
+
assert (Time.now + 5) > runner.last_seen_at
|
155
|
+
end
|
156
|
+
|
157
|
+
should "only create one record for the same mac" do
|
158
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:01:..."
|
159
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:01:..."
|
160
|
+
assert_equal 1, Runner.count
|
161
|
+
end
|
162
|
+
|
163
|
+
should "not return anything to outdated clients" do
|
164
|
+
Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project'
|
165
|
+
get '/jobs/next', :version => "1", :uid => "00:..."
|
166
|
+
assert last_response.ok?
|
167
|
+
assert_equal '', last_response.body
|
168
|
+
end
|
169
|
+
|
170
|
+
should "only give jobs from the same source to a runner" do
|
171
|
+
build = Build.create
|
172
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :type => 'spec', :build => build
|
173
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:...", :build_id => build.id
|
174
|
+
|
175
|
+
# Creating the second job here because of the random lookup.
|
176
|
+
job2 = Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :build => build
|
177
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:...", :build_id => build.id + 1
|
178
|
+
|
179
|
+
assert last_response.ok?
|
180
|
+
assert_equal '', last_response.body
|
181
|
+
end
|
182
|
+
|
183
|
+
should "not give more jruby jobs to an instance that can't take more" do
|
184
|
+
build = Build.create
|
185
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :type => 'spec', :jruby => 1, :build => build
|
186
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:..."
|
187
|
+
|
188
|
+
# Creating the second job here because of the random lookup.
|
189
|
+
job2 = Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :jruby => 1, :build => build
|
190
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:...", :no_jruby => "true"
|
191
|
+
|
192
|
+
assert last_response.ok?
|
193
|
+
assert_equal '', last_response.body
|
194
|
+
end
|
195
|
+
|
196
|
+
should "still return other jobs when the runner cant take more jruby jobs" do
|
197
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :type => 'spec', :jruby => 1, :build => Build.create
|
198
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:..."
|
199
|
+
|
200
|
+
# Creating the second job here because of the random lookup.
|
201
|
+
job2 = Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :jruby => 0, :build => Build.create
|
202
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:...", :no_jruby => "true"
|
203
|
+
|
204
|
+
assert last_response.ok?
|
205
|
+
assert_equal job2.id.to_s, last_response.body.split(',')[0]
|
206
|
+
end
|
207
|
+
|
208
|
+
should "return the jobs in random order in order to start working for a new build right away" do
|
209
|
+
build1, build2 = Build.create, Build.create
|
210
|
+
20.times { Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :build => build1 }
|
211
|
+
|
212
|
+
20.times { Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :build => build2 }
|
213
|
+
|
214
|
+
build_ids = (0...10).map {
|
215
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:..."
|
216
|
+
last_response.body.split(',')[1]
|
217
|
+
}
|
218
|
+
|
219
|
+
assert build_ids.find { |build_id| build_id == build1.id.to_s }
|
220
|
+
assert build_ids.find { |build_id| build_id == build2.id.to_s }
|
221
|
+
end
|
222
|
+
|
223
|
+
should "return the jobs randomly when passing build_id" do
|
224
|
+
build = Build.create
|
225
|
+
20.times { Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :build => build }
|
226
|
+
|
227
|
+
20.times { Job.create :files => 'spec/models/car_spec.rb', :root => 'server:/project', :type => 'spec', :build => build }
|
228
|
+
|
229
|
+
files = (0...10).map {
|
230
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:...", :build_id => build.id
|
231
|
+
last_response.body.split(',').last
|
232
|
+
}
|
233
|
+
|
234
|
+
assert files.find { |file| file.include?('car') }
|
235
|
+
assert files.find { |file| file.include?('house') }
|
236
|
+
end
|
237
|
+
|
238
|
+
should "return taken jobs to other runners if the runner hasn't been seen for 10 seconds or more" do
|
239
|
+
missing_runner = Runner.create(:last_seen_at => Time.now - 15)
|
240
|
+
build = Build.create
|
241
|
+
old_taken_job = Job.create :files => 'spec/models/house_spec.rb', :root => 'server:/project', :type => 'spec', :build => build, :taken_by => missing_runner, :taken_at => Time.now - 30, :project => 'things'
|
242
|
+
|
243
|
+
new_runner = Runner.create(:uid => "00:01")
|
244
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:01"
|
245
|
+
assert_equal new_runner, old_taken_job.taken_by
|
246
|
+
|
247
|
+
assert last_response.ok?
|
248
|
+
assert_equal [ old_taken_job.id, build.id.to_s, "things", "server:/project", "spec", "ruby", "spec/models/house_spec.rb" ].join(','), last_response.body
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
context "/runners/outdated" do
|
254
|
+
|
255
|
+
should "return a list of outdated runners" do
|
256
|
+
get '/jobs/next', :version => "1", :hostname => 'macmini1.local', :uid => "00:01"
|
257
|
+
get '/jobs/next', :version => "1", :hostname => 'macmini2.local', :uid => "00:02"
|
258
|
+
get '/jobs/next'
|
259
|
+
get '/jobs/next', :version => Testbot.version.to_s, :hostname => 'macmini3.local', :uid => "00:03"
|
260
|
+
assert_equal 4, Runner.count
|
261
|
+
get '/runners/outdated'
|
262
|
+
assert last_response.ok?
|
263
|
+
assert_equal "127.0.0.1 macmini1.local 00:01\n127.0.0.1 macmini2.local 00:02\n127.0.0.1", last_response.body
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
context "GET /runners/available_runners" do
|
269
|
+
|
270
|
+
should "return a list of available runners" do
|
271
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini1.local', :uid => "00:01", :idle_instances => 2, :username => 'user1'
|
272
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini2.local', :uid => "00:02", :idle_instances => 4, :username => 'user2'
|
273
|
+
get '/runners/available'
|
274
|
+
assert last_response.ok?
|
275
|
+
assert_equal "127.0.0.1 macmini1.local 00:01 user1 2\n127.0.0.1 macmini2.local 00:02 user2 4", last_response.body
|
276
|
+
end
|
277
|
+
|
278
|
+
should "not return a runner as available when it hasnt pinged the server yet" do
|
279
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini1.local', :uid => "00:01", :username => 'user1'
|
280
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini2.local', :uid => "00:02", :idle_instances => 4, :username => 'user2'
|
281
|
+
get '/runners/available'
|
282
|
+
assert last_response.ok?
|
283
|
+
assert_equal "127.0.0.1 macmini2.local 00:02 user2 4", last_response.body
|
284
|
+
end
|
285
|
+
|
286
|
+
should "not return runners as available when not seen the last 10 seconds" do
|
287
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini1.local', :uid => "00:01", :idle_instances => 2, :username => "user1"
|
288
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini2.local', :uid => "00:02", :idle_instances => 4
|
289
|
+
Runner.find_by_uid("00:02").update(:last_seen_at => Time.now - 10)
|
290
|
+
get '/runners/available'
|
291
|
+
assert_equal "127.0.0.1 macmini1.local 00:01 user1 2", last_response.body
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
context "GET /runners/available_instances" do
|
297
|
+
|
298
|
+
should "return the number of available runner instances" do
|
299
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini1.local', :uid => "00:01", :idle_instances => 2
|
300
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini2.local', :uid => "00:02", :idle_instances => 4
|
301
|
+
get '/runners/available_instances'
|
302
|
+
assert last_response.ok?
|
303
|
+
assert_equal "6", last_response.body
|
304
|
+
end
|
305
|
+
|
306
|
+
should "not return instances as available when not seen the last 10 seconds" do
|
307
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini1.local', :uid => "00:01", :idle_instances => 2
|
308
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini2.local', :uid => "00:02", :idle_instances => 4
|
309
|
+
Runner.find_by_uid("00:02").update(:last_seen_at => Time.now - 10)
|
310
|
+
get '/runners/available_instances'
|
311
|
+
assert last_response.ok?
|
312
|
+
assert_equal "2", last_response.body
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|
316
|
+
|
317
|
+
context "GET /runners/total_instances" do
|
318
|
+
|
319
|
+
should "return the number of available runner instances" do
|
320
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini1.local', :uid => "00:01", :max_instances => 2, :idle_instances => 1
|
321
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini2.local', :uid => "00:02", :max_instances => 4, :idle_instances => 2
|
322
|
+
get '/runners/total_instances'
|
323
|
+
assert last_response.ok?
|
324
|
+
assert_equal "6", last_response.body
|
325
|
+
end
|
326
|
+
|
327
|
+
should "not return instances as available when not seen the last 10 seconds" do
|
328
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini1.local', :uid => "00:01", :max_instances => 2, :idle_instances => 1
|
329
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini2.local', :uid => "00:02", :max_instances => 4, :idle_instances => 2
|
330
|
+
Runner.find_by_uid("00:02").update(:last_seen_at => Time.now - 10)
|
331
|
+
get '/runners/total_instances'
|
332
|
+
assert last_response.ok?
|
333
|
+
assert_equal "2", last_response.body
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|
337
|
+
|
338
|
+
context "GET /runners/ping" do
|
339
|
+
|
340
|
+
should "update last_seen_at for the runner" do
|
341
|
+
runner = Runner.create(:uid => 'aa:aa:aa:aa:aa:aa')
|
342
|
+
get "/runners/ping", :uid => 'aa:aa:aa:aa:aa:aa', :version => Testbot.version
|
343
|
+
assert last_response.ok?
|
344
|
+
assert (Time.now - 5) < runner.last_seen_at
|
345
|
+
assert (Time.now + 5) > runner.last_seen_at
|
346
|
+
end
|
347
|
+
|
348
|
+
should "update data on the runner" do
|
349
|
+
build = Build.create
|
350
|
+
runner = Runner.create(:uid => 'aa:aa:..')
|
351
|
+
get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke', :build_id => build.id
|
352
|
+
assert last_response.ok?
|
353
|
+
assert_equal 'aa:aa:..', runner.uid
|
354
|
+
assert_equal 4, runner.max_instances
|
355
|
+
assert_equal 2, runner.idle_instances
|
356
|
+
assert_equal 'hostname1', runner.hostname
|
357
|
+
assert_equal Testbot.version, runner.version
|
358
|
+
assert_equal 'jocke', runner.username
|
359
|
+
assert_equal build, runner.build
|
360
|
+
end
|
361
|
+
|
362
|
+
should "do nothing if the version does not match" do
|
363
|
+
runner = Runner.create(:uid => 'aa:aa:..', :version => Testbot.version)
|
364
|
+
get "/runners/ping", :uid => 'aa:aa:..', :version => "OLD"
|
365
|
+
assert last_response.ok?
|
366
|
+
assert_equal Testbot.version, runner.version
|
367
|
+
end
|
368
|
+
|
369
|
+
should "do nothing if the runners isnt known yet found" do
|
370
|
+
get "/runners/ping", :uid => 'aa:aa:aa:aa:aa:aa', :version => Testbot.version
|
371
|
+
assert last_response.ok?
|
372
|
+
end
|
373
|
+
|
374
|
+
should "return an order to stop the build if the build id does not exist anymore" do
|
375
|
+
runner = Runner.create(:uid => 'aa:aa:..')
|
376
|
+
get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke', :build_id => 1
|
377
|
+
assert_equal last_response.body, "stop_build,1"
|
378
|
+
end
|
379
|
+
|
380
|
+
should "not return an order to stop a build without an id" do
|
381
|
+
runner = Runner.create(:uid => 'aa:aa:..')
|
382
|
+
get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke', :build_id => ''
|
383
|
+
assert_equal last_response.body, ''
|
384
|
+
get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke', :build_id => nil
|
385
|
+
assert_equal last_response.body, ''
|
386
|
+
end
|
387
|
+
|
388
|
+
end
|
389
|
+
|
390
|
+
context "PUT /jobs/:id" do
|
391
|
+
|
392
|
+
should "receive the results of a job" do
|
393
|
+
job = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30
|
394
|
+
put "/jobs/#{job.id}", :result => 'test run result', :status => "successful"
|
395
|
+
assert last_response.ok?
|
396
|
+
assert_equal 'test run result', job.result
|
397
|
+
assert_equal 'successful', job.status
|
398
|
+
end
|
399
|
+
|
400
|
+
should "update the related build" do
|
401
|
+
build = Build.create
|
402
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
403
|
+
job2 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
404
|
+
put "/jobs/#{job1.id}", :result => 'test run result 1\n', :status => "successful"
|
405
|
+
put "/jobs/#{job2.id}", :result => 'test run result 2\n', :status => "successful"
|
406
|
+
assert_equal 'test run result 1\ntest run result 2\n', build.results
|
407
|
+
assert_equal true, build.success
|
408
|
+
end
|
409
|
+
|
410
|
+
should "make the related build done if there are no more jobs for the build" do
|
411
|
+
build = Build.create
|
412
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
413
|
+
job2 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
414
|
+
put "/jobs/#{job1.id}", :result => 'test run result 1\n', :status => "successful"
|
415
|
+
put "/jobs/#{job2.id}", :result => 'test run result 2\n', :status => "successful"
|
416
|
+
assert_equal true, build.done
|
417
|
+
end
|
418
|
+
|
419
|
+
should "make the build fail if one of the jobs fail" do
|
420
|
+
build = Build.create
|
421
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
422
|
+
job2 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
423
|
+
put "/jobs/#{job1.id}", :result => 'test run result 1\n', :status => "failed"
|
424
|
+
put "/jobs/#{job2.id}", :result => 'test run result 2\n', :status => "successful"
|
425
|
+
assert_equal false, build.success
|
426
|
+
end
|
427
|
+
|
428
|
+
should "be able to update from multiple result postings" do
|
429
|
+
build = Build.create
|
430
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
431
|
+
job2 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
432
|
+
# maybe later:
|
433
|
+
# put "/jobs/#{job.id}", :result => 'Preparing, db setup, etc.', :status => "preparing"
|
434
|
+
put "/jobs/#{job1.id}", :result => 'Running tests..', :status => "running"
|
435
|
+
put "/jobs/#{job2.id}", :result => 'Running other tests. done.', :status => "successful"
|
436
|
+
put "/jobs/#{job1.id}", :result => 'Running tests....', :status => "running"
|
437
|
+
assert_equal false, build.done
|
438
|
+
assert_equal false, job1.done
|
439
|
+
assert_equal "Running tests....", job1.result
|
440
|
+
assert_equal "Running tests..Running other tests. done...", build.results
|
441
|
+
end
|
442
|
+
|
443
|
+
should "not break when updating without new results" do
|
444
|
+
build = Build.create
|
445
|
+
job1 = Job.create :files => 'spec/models/car_spec.rb', :taken_at => Time.now - 30, :build => build
|
446
|
+
put "/jobs/#{job1.id}", :result => 'Running tests..', :status => "running"
|
447
|
+
put "/jobs/#{job1.id}", :result => '', :status => "successful"
|
448
|
+
assert_equal "Running tests..", build.results
|
449
|
+
end
|
450
|
+
|
451
|
+
end
|
452
|
+
|
453
|
+
context "GET /version" do
|
454
|
+
|
455
|
+
should "return its version" do
|
456
|
+
get '/version'
|
457
|
+
assert last_response.ok?
|
458
|
+
assert_equal Testbot.version.to_s, last_response.body
|
459
|
+
end
|
460
|
+
|
461
|
+
end
|
462
|
+
|
463
|
+
context "GET /runners" do
|
464
|
+
|
465
|
+
should "return runner information in json format" do
|
466
|
+
get '/jobs/next', :version => Testbot.version, :uid => "00:01"
|
467
|
+
get "/runners/ping", :uid => '00:01', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'testbot', :build_id => nil
|
468
|
+
get '/runners'
|
469
|
+
|
470
|
+
assert last_response.ok?
|
471
|
+
assert_equal ([ { "version" => Testbot.version.to_s, "build" => nil, "hostname" => 'hostname1', "uid" => "00:01",
|
472
|
+
"idle_instances" => 2, "max_instances" => 4, "username" => 'testbot',
|
473
|
+
"ip" => "127.0.0.1", "last_seen_at" => Runner.first.last_seen_at.to_s } ]),
|
474
|
+
JSON.parse(last_response.body)
|
475
|
+
end
|
476
|
+
|
477
|
+
should "not return instances when not seen the last 10 seconds" do
|
478
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini1.local', :uid => "00:01", :idle_instances => 2
|
479
|
+
get '/jobs/next', :version => Testbot.version, :hostname => 'macmini2.local', :uid => "00:02", :idle_instances => 4
|
480
|
+
Runner.find_by_uid("00:02").update(:last_seen_at => Time.now - 10)
|
481
|
+
get '/runners'
|
482
|
+
assert last_response.ok?
|
483
|
+
parsed_body = JSON.parse(last_response.body)
|
484
|
+
assert_equal 1, parsed_body.size
|
485
|
+
assert_equal '00:01', parsed_body.first["uid"]
|
486
|
+
end
|
487
|
+
|
488
|
+
end
|
489
|
+
|
490
|
+
context "GET /status" do
|
491
|
+
|
492
|
+
should "return the contents of the status page" do
|
493
|
+
get '/status'
|
494
|
+
assert_equal true, last_response.body.include?('Testbot status')
|
495
|
+
end
|
496
|
+
|
497
|
+
end
|
498
|
+
|
499
|
+
context "GET /status/:dir/:file" do
|
500
|
+
|
501
|
+
should "return the file" do
|
502
|
+
get "/status/javascripts/jquery-1.4.4.min.js"
|
503
|
+
assert_equal true, last_response.body.include?('jQuery JavaScript Library v1.4.4')
|
504
|
+
end
|
505
|
+
|
506
|
+
end
|
507
|
+
|
508
|
+
end
|
509
|
+
|
510
|
+
end
|
511
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../lib/shared/adapters/adapter.rb'))
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
class AdapterTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
should "be able to find adapters" do
|
8
|
+
assert_equal RspecAdapter, Adapter.find(:spec)
|
9
|
+
assert_equal TestUnitAdapter, Adapter.find(:test)
|
10
|
+
end
|
11
|
+
|
12
|
+
should "find be able to find an adapter by string" do
|
13
|
+
assert_equal RspecAdapter, Adapter.find("spec")
|
14
|
+
assert_equal TestUnitAdapter, Adapter.find("test")
|
15
|
+
end
|
16
|
+
|
17
|
+
should "be able to return a list of adapters" do
|
18
|
+
assert Adapter.all.include?(RspecAdapter)
|
19
|
+
assert Adapter.all.include?(TestUnitAdapter)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../../lib/shared/adapters/cucumber_adapter.rb'))
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
class CucumberAdapterTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context "sum_results" do
|
8
|
+
|
9
|
+
should "be able to parse and sum results" do
|
10
|
+
results =<<STR
|
11
|
+
testbot4:/tmp/testbot
|
12
|
+
............................................................................................................................................................
|
13
|
+
|
14
|
+
13 scenarios (\033[32m13 passed\033[0m)
|
15
|
+
153 steps (\033[32m153 passed\033[0m)
|
16
|
+
0m25.537s
|
17
|
+
|
18
|
+
testbot3:/tmp/testbot
|
19
|
+
................................................................................................................
|
20
|
+
|
21
|
+
12 scenarios (\033[32m12 passed\033[0m)
|
22
|
+
109 steps (\033[32m109 passed\033[0m)
|
23
|
+
1m28.472s
|
24
|
+
STR
|
25
|
+
|
26
|
+
assert_equal "25 scenarios (25 passed)\n262 steps (262 passed)", Color.strip(CucumberAdapter.sum_results(results))
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
should "should handle undefined steps" do
|
31
|
+
results =<<STR
|
32
|
+
5 scenarios (1 failed, 1 undefined, 3 passed)
|
33
|
+
42 steps (1 failed, 3 skipped, 1 undefined, 37 passed)
|
34
|
+
|
35
|
+
5 scenarios (1 failed, 1 undefined, 3 passed)
|
36
|
+
42 steps (1 failed, 3 skipped, 1 undefined, 37 passed)
|
37
|
+
|
38
|
+
6 scenarios (6 passed)
|
39
|
+
80 steps (80 passed)
|
40
|
+
STR
|
41
|
+
|
42
|
+
assert_equal "16 scenarios (2 failed, 2 undefined, 12 passed)\n164 steps (2 failed, 6 skipped, 2 undefined, 154 passed)", Color.strip(CucumberAdapter.sum_results(results))
|
43
|
+
end
|
44
|
+
|
45
|
+
should "handle other combinations" do
|
46
|
+
results =<<STR
|
47
|
+
5 scenarios (1 failed, 1 undefined, 3 passed)
|
48
|
+
42 steps (1 failed, 1 undefined, 37 passed)
|
49
|
+
|
50
|
+
5 scenarios (1 failed, 1 undefined, 3 passed)
|
51
|
+
42 steps (3 skipped, 1 undefined, 37 passed)
|
52
|
+
|
53
|
+
6 scenarios (6 passed)
|
54
|
+
80 steps (80 passed)
|
55
|
+
STR
|
56
|
+
|
57
|
+
assert_equal "16 scenarios (2 failed, 2 undefined, 12 passed)\n164 steps (1 failed, 3 skipped, 2 undefined, 154 passed)", Color.strip(CucumberAdapter.sum_results(results))
|
58
|
+
end
|
59
|
+
|
60
|
+
should "colorize" do
|
61
|
+
results =<<STR
|
62
|
+
5 scenarios (1 failed, 1 undefined, 3 passed)
|
63
|
+
42 steps (1 failed, 3 skipped, 1 undefined, 37 passed)
|
64
|
+
STR
|
65
|
+
|
66
|
+
assert_equal "5 scenarios (\e[31m1 failed\e[0m, \e[33m1 undefined\e[0m, \e[32m3 passed\e[0m)\n42 steps (\e[31m1 failed\e[0m, \e[36m3 skipped\e[0m, \e[33m1 undefined\e[0m, \e[32m37 passed\e[0m)", CucumberAdapter.sum_results(results)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
end
|