tinderbox 1.0.0

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.
@@ -0,0 +1,285 @@
1
+ $TESTING = false unless defined? $TESTING
2
+ require 'tinderbox'
3
+ require 'tinderbox/gem_runner'
4
+ require 'tinderbox/build'
5
+ require 'rubygems/source_info_cache'
6
+
7
+ require 'optparse'
8
+ require 'rbconfig'
9
+ require 'socket'
10
+
11
+ require 'rubygems'
12
+ require 'firebrigade/cache'
13
+
14
+ ##
15
+ # GemTinderbox is a tinderbox for RubyGems.
16
+
17
+ class Tinderbox::GemTinderbox
18
+
19
+ ##
20
+ # Root directory that the GemTinderbox will use.
21
+
22
+ attr_accessor :root
23
+
24
+ ##
25
+ # Timeout for GemRunner.
26
+
27
+ attr_accessor :timeout
28
+
29
+ ##
30
+ # Processes +args+ into options.
31
+
32
+ def self.process_args(args)
33
+ opts_file = File.expand_path '~/.gem_tinderbox'
34
+ options = {}
35
+
36
+ if File.exist? opts_file then
37
+ File.readlines(opts_file).map { |l| l.chomp.split '=', 2 }.each do |k,v|
38
+ v = true if v == 'true'
39
+ v = false if v == 'false'
40
+ v = Integer(v) if k == 'Timeout'
41
+ options[k.intern] = v
42
+ end
43
+ end
44
+
45
+ options[:Daemon] ||= false
46
+ options[:Timeout] ||= 120
47
+
48
+ opts = OptionParser.new do |opts|
49
+ opts.banner = "Usage: #{File.basename $0} [options]"
50
+ opts.separator ''
51
+ opts.separator 'Options may also be set in the options file ~/.gem_tinderbox.'
52
+ opts.separator ''
53
+ opts.separator 'Example ~/.gem_tinderbox'
54
+ opts.separator "\tServer=firebrigade.example.com"
55
+ opts.separator "\tUsername=my username"
56
+ opts.separator "\tPassword=my password"
57
+ opts.separator "\tRoot=/path/to/tinderbox/root"
58
+
59
+ opts.separator ''
60
+
61
+ opts.on("-s", "--server HOST",
62
+ "Firebrigade server host",
63
+ "Default: #{options[:Server].inspect}",
64
+ "Options file name: Server") do |server|
65
+ options[:Server] = server
66
+ end
67
+
68
+ opts.on("-u", "--username USERNAME",
69
+ "Firebrigade username",
70
+ "Default: #{options[:Username].inspect}",
71
+ "Options file name: Username") do |username|
72
+ options[:Username] = username
73
+ end
74
+
75
+ opts.on("-p", "--password PASSWORD",
76
+ "Firebrigade password",
77
+ "Default: Read from ~/.gem_tinderbox",
78
+ "Options file name: Password") do |password|
79
+ options[:Password] = password
80
+ end
81
+
82
+ opts.separator ''
83
+
84
+ opts.on("-t", "--timeout TIMEOUT",
85
+ "Maximum time to wait for a gem's tests to",
86
+ "finish",
87
+ "Default: #{options[:Timeout]}",
88
+ Numeric) do |timeout|
89
+ options[:Timeout] = timeout
90
+ end
91
+
92
+ opts.on("-r", "--root ROOT",
93
+ "Root directory for gem tinderbox",
94
+ "Default: #{options[:Root]}",
95
+ "Gems will be lit on fire here.") do |root|
96
+ options[:Root] = root
97
+ end
98
+
99
+ opts.on("-d", "--daemonize",
100
+ "Run as a daemon process",
101
+ "Default: #{options[:Daemon]}") do |daemon|
102
+ options[:Daemon] = true
103
+ end
104
+ end
105
+
106
+ opts.version = Tinderbox::VERSION
107
+ opts.release = nil
108
+
109
+ opts.parse! args
110
+
111
+ if options[:Server].nil? or
112
+ options[:Username].nil? or
113
+ options[:Password].nil? then
114
+ $stderr.puts opts
115
+ $stderr.puts
116
+ $stderr.puts "Firebrigade Server not set" if options[:Server].nil?
117
+ $stderr.puts "Firebrigade Username not set" if options[:Username].nil?
118
+ $stderr.puts "Firebrigade Password not set" if options[:Password].nil?
119
+ exit 1
120
+ end
121
+
122
+ return options
123
+ rescue OptionParser::ParseError
124
+ $stderr.puts opts
125
+ exit 1
126
+ end
127
+
128
+ ##
129
+ # Starts a GemTinderbox.
130
+
131
+ def self.run(args = ARGV)
132
+ options = process_args args
133
+
134
+ tinderbox = new options[:Server], options[:Username], options[:Password]
135
+ tinderbox.root = options[:Root]
136
+ tinderbox.timeout = options[:Timeout]
137
+
138
+ if options[:Daemon] then
139
+ require 'webrick/server'
140
+ WEBrick::Daemon.start
141
+ end
142
+
143
+ tinderbox.run
144
+
145
+ rescue Interrupt, SystemExit
146
+ exit
147
+ rescue Exception => e
148
+ puts "#{e.message}(#{e.class}):"
149
+ puts "\t#{e.backtrace.join "\n\t"}"
150
+ exit 1
151
+ end
152
+
153
+ ##
154
+ # Creates a new GemTinderbox that will submit results to +host+ as
155
+ # +username+ using +password+.
156
+
157
+ def initialize(host, username, password)
158
+ @host = host
159
+ @username = username
160
+ @password = password
161
+ @root = nil
162
+ @timeout = 120
163
+
164
+ @source_info_cache = nil
165
+ @seen_gem_names = []
166
+ @wait_time = 300
167
+
168
+ @fc = Firebrigade::Cache.new @host, @username, @password
169
+ @target_id = nil
170
+ end
171
+
172
+ ##
173
+ # Finds new gems in the source_info_cache
174
+
175
+ def new_gems
176
+ update_gems
177
+
178
+ latest_gems = {}
179
+ source_info_cache.cache_data.each do |source, sic_e|
180
+ sic_e.source_index.latest_specs.each do |name, spec|
181
+ latest_gems[name] = spec
182
+ end
183
+ end
184
+
185
+ new_gem_names = latest_gems.keys - @seen_gem_names
186
+
187
+ @seen_gem_names = latest_gems.keys
188
+
189
+ latest_gems.values_at(*new_gem_names)
190
+ end
191
+
192
+ ##
193
+ # Tests all the gems, then waits a while and tests anything that is new in
194
+ # the index. If an unhandled error is encountered, GemTinderbox waits a
195
+ # minute then starts from the beginning. (Since information is cached,
196
+ # GemTinderbox won't pound on Firebrigade.)
197
+
198
+ def run
199
+ @seen_gem_names = []
200
+ @target_id ||= @fc.get_target_id
201
+
202
+ loop do
203
+ new_gems.each do |spec| run_spec spec end
204
+ sleep @wait_time
205
+ end
206
+ rescue RCRest::CommunicationError, Gem::RemoteFetcher::FetchError,
207
+ Gem::RemoteSourceException => e
208
+ wait = Time.now + 60
209
+
210
+ $stderr.puts e.message
211
+ $stderr.puts "Will retry at #{wait}"
212
+
213
+ unless $TESTING then
214
+ sleep 60
215
+ retry
216
+ end
217
+ end
218
+
219
+ ##
220
+ # Runs Gem::Specification +spec+ using a GemRunner then submits the results
221
+ # to Firebrigade.
222
+
223
+ def run_spec(spec)
224
+ $stderr.puts "*** Checking #{spec.full_name}"
225
+
226
+ version_id = @fc.get_version_id spec
227
+ return if tested? version_id
228
+
229
+ $stderr.puts "*** Igniting (http://#{@host}/gem/show/#{spec.name}/#{spec.version})"
230
+ begin
231
+ build = test_gem spec
232
+ rescue Tinderbox::BuildError, Tinderbox::InstallError => e
233
+ @seen_gem_names.delete spec.full_name
234
+ $stderr.puts "*** Failed to install (#{e.class})"
235
+ return
236
+ rescue Tinderbox::InstallError => e
237
+ $stderr.puts "*** Failed to install (#{e.class}), will try again later"
238
+ return
239
+ end
240
+
241
+ if build.successful then
242
+ $stderr.puts "*** I couldn't light #{spec.full_name} on fire"
243
+ else
244
+ $stderr.puts "*** I lit #{spec.full_name} on fire!"
245
+ end
246
+
247
+ build.submit version_id, @target_id, @host, @username, @password
248
+
249
+ build
250
+ end
251
+
252
+ ##
253
+ # Rubygems' source info cache
254
+
255
+ def source_info_cache
256
+ return @source_info_cache if @source_info_cache
257
+ @source_info_cache = Gem::SourceInfoCache.cache
258
+ end
259
+
260
+ ##
261
+ # Tests the Gem::Specification +spec+ and returns a Build containing its
262
+ # results.
263
+
264
+ def test_gem(spec)
265
+ runner = Tinderbox::GemRunner.new spec.name, spec.version.to_s, root
266
+ runner.timeout = @timeout
267
+ runner.run
268
+ end
269
+
270
+ ##
271
+ # Checks the server to see if +version_id+ has been tested.
272
+
273
+ def tested?(version_id)
274
+ !!@fc.get_build_id(version_id, @target_id)
275
+ end
276
+
277
+ ##
278
+ # Refreshes Rubygems' source info cache
279
+
280
+ def update_gems
281
+ source_info_cache.refresh
282
+ end
283
+
284
+ end
285
+
@@ -0,0 +1,103 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'rc_rest/uri_stub'
4
+ require 'rc_rest/net_http_stub'
5
+ require 'test/zentest_assertions'
6
+
7
+ require 'tinderbox/build'
8
+
9
+ class TestTinderboxBuild < Test::Unit::TestCase
10
+
11
+ def setup
12
+ URI::HTTP.responses = []
13
+ URI::HTTP.uris = []
14
+
15
+ Net::HTTP.params = []
16
+ Net::HTTP.paths = []
17
+ Net::HTTP.responses = []
18
+
19
+ @build = Tinderbox::Build.new
20
+ end
21
+
22
+ def test_duration
23
+ @build.duration = 5
24
+ assert_equal 5, @build.duration
25
+ end
26
+
27
+ def test_log
28
+ @build.log = 'some crap'
29
+ assert_equal 'some crap', @build.log
30
+ end
31
+
32
+ def test_successful
33
+ @build.successful = true
34
+ assert_equal true, @build.successful
35
+ end
36
+
37
+ def test_submit
38
+ Net::HTTP.responses << <<-EOF
39
+ <ok>
40
+ <build>
41
+ <id>100</id>
42
+ <created_on>#{Time.now}</created_on>
43
+ <duration>1.5</duration>
44
+ <guilty_party></guilty_party>
45
+ <successful>true</successful>
46
+ <target_id>100</target_id>
47
+ <version_id>101</version_id>
48
+ </build>
49
+ </ok>
50
+ EOF
51
+
52
+ @build.log = "*** blah\nfailed"
53
+ @build.successful = false
54
+ @build.duration = 1.5
55
+
56
+ srand 0
57
+
58
+ @build.submit 101, 100, 'firebrigade.example.com', 'username', 'password'
59
+
60
+ assert_empty Net::HTTP.responses
61
+
62
+ assert_equal 1, Net::HTTP.paths.length
63
+ assert_equal '/api/REST/add_build', Net::HTTP.paths.shift
64
+
65
+ assert_equal 1, Net::HTTP.params.length
66
+
67
+ expected = <<-EOF.strip
68
+ --ac_2f_75_c0_43_fb_c3_67\r
69
+ Content-Disposition: form-data; name=\"duration\"\r
70
+ \r
71
+ 1.5\r
72
+ --ac_2f_75_c0_43_fb_c3_67\r
73
+ Content-Disposition: form-data; name=\"hash\"\r
74
+ \r
75
+ e99435ecca5025c0e3a6f7e98fc91b7e\r
76
+ --ac_2f_75_c0_43_fb_c3_67\r
77
+ Content-Disposition: form-data; name=\"log\"\r
78
+ \r
79
+ *** blah
80
+ failed\r
81
+ --ac_2f_75_c0_43_fb_c3_67\r
82
+ Content-Disposition: form-data; name=\"successful\"\r
83
+ \r
84
+ false\r
85
+ --ac_2f_75_c0_43_fb_c3_67\r
86
+ Content-Disposition: form-data; name=\"target_id\"\r
87
+ \r
88
+ 100\r
89
+ --ac_2f_75_c0_43_fb_c3_67\r
90
+ Content-Disposition: form-data; name=\"user\"\r
91
+ \r
92
+ username\r
93
+ --ac_2f_75_c0_43_fb_c3_67\r
94
+ Content-Disposition: form-data; name=\"version_id\"\r
95
+ \r
96
+ 101\r
97
+ --ac_2f_75_c0_43_fb_c3_67--
98
+ EOF
99
+ assert_equal expected, Net::HTTP.params.shift
100
+ end
101
+
102
+ end
103
+
@@ -0,0 +1,688 @@
1
+ require 'test/unit'
2
+
3
+ require 'rubygems'
4
+ require 'test/zentest_assertions'
5
+
6
+ require 'rbconfig'
7
+ require 'tmpdir'
8
+
9
+ require 'tinderbox/gem_runner'
10
+
11
+ class Tinderbox::GemRunner
12
+ attr_writer :gemspec
13
+ attr_accessor :installed_gems, :remote_installer, :log
14
+ attr_reader :duration, :successful
15
+ end
16
+
17
+ class Gem::RemoteInstaller
18
+ alias orig_install install
19
+ def install(gem_name, version = '1.2.3')
20
+ full_gem_name = "#{gem_name}-#{version}"
21
+ gem_path = File.join Gem.dir, 'gems', full_gem_name
22
+ FileUtils.mkpath gem_path
23
+ s = Gem::Specification.new
24
+ s.name = gem_name
25
+ s.version = version
26
+ s.loaded_from = File.join Gem.dir, 'gems', full_gem_name
27
+ return [s]
28
+ end
29
+ end
30
+
31
+ class Gem::SourceInfoCache
32
+ attr_writer :cache_data
33
+ class << self; attr_writer :cache; end
34
+ end
35
+
36
+ class TestTinderboxGemRunner < Test::Unit::TestCase
37
+
38
+ def setup
39
+ @gem_name = 'some_test_gem'
40
+ @gem_version = '1.2.3'
41
+ @gem_full_name = "#{@gem_name}-#{@gem_version}"
42
+
43
+ @rake = Gem::Specification.new
44
+ @rake.name = 'rake'
45
+ @rake.version = '999.999.999'
46
+
47
+ @rspec = Gem::Specification.new
48
+ @rspec.name = 'rspec'
49
+ @rspec.version = '999.999.999'
50
+
51
+ @gemspec = Gem::Specification.new
52
+ @gemspec.name = @gem_name
53
+ @gemspec.version = @gem_version
54
+ @gemspec.loaded_from = File.join Gem.dir, 'gems', @gem_full_name
55
+ @gemspec.require_paths = ['lib', 'other']
56
+
57
+ @root = File.join Dir.tmpdir, 'tinderbox_test'
58
+ @sandbox_dir = File.join @root, 'sandbox'
59
+ @tgr = Tinderbox::GemRunner.new @gem_name, @gem_version, @root
60
+
61
+ @util_test_setup = false
62
+ end
63
+
64
+ def teardown
65
+ FileUtils.remove_dir @root rescue nil
66
+ ENV['GEM_HOME'] = nil
67
+ Gem.clear_paths
68
+ end
69
+
70
+ def test_gem_lib_paths
71
+ @tgr.gemspec = @gemspec
72
+ assert_equal "lib#{Config::CONFIG['PATH_SEPARATOR']}other",
73
+ @tgr.gem_lib_paths
74
+ end
75
+
76
+ def test_initialize
77
+ assert_equal @sandbox_dir, @tgr.sandbox_dir
78
+ assert_equal File.join(Config::CONFIG['libdir'], 'ruby', 'gems',
79
+ Config::CONFIG['ruby_version']),
80
+ @tgr.host_gem_dir
81
+ assert_equal @gem_name, @tgr.gem_name
82
+ assert_equal @gem_version, @tgr.gem_version
83
+ assert_equal nil, @tgr.gemspec
84
+
85
+ e = assert_raise ArgumentError do
86
+ tgr = Tinderbox::GemRunner.new @gem_name, @gem_version, 'relative'
87
+ end
88
+
89
+ assert_equal 'root must not be relative', e.message
90
+ end
91
+
92
+ def test_install
93
+ @tgr.sandbox_setup
94
+ @tgr.install_sources
95
+ @tgr.install
96
+
97
+ deny_empty Dir[File.join(@sandbox_dir, 'gems', @gem_full_name)]
98
+ assert_equal true, File.directory?(File.join(@root, 'cache'))
99
+ assert_equal @gem_full_name, @tgr.gemspec.full_name
100
+ end
101
+
102
+ def test_install_bad_gem
103
+ ri = @tgr.remote_installer
104
+ def ri.install(*a) raise Gem::InstallError end
105
+
106
+ @tgr.sandbox_setup
107
+ @tgr.install_sources
108
+ assert_raise Tinderbox::InstallError do
109
+ @tgr.install
110
+ end
111
+
112
+ assert_empty Dir[File.join(@sandbox_dir, 'gems', @gem_full_name)]
113
+ end
114
+
115
+ def test_install_ext_build_error
116
+ ri = @tgr.remote_installer
117
+ def ri.install(*a) raise Gem::Installer::ExtensionBuildError end
118
+
119
+ @tgr.sandbox_setup
120
+ @tgr.install_sources
121
+ assert_raise Tinderbox::BuildError do
122
+ @tgr.install
123
+ end
124
+
125
+ assert_empty Dir[File.join(@sandbox_dir, 'gems', @gem_full_name)]
126
+ end
127
+
128
+ def test_install_wrong_platform
129
+ ri = @tgr.remote_installer
130
+ def ri.install(*a) raise Gem::RemoteInstallationCancelled end
131
+
132
+ @tgr.sandbox_setup
133
+ @tgr.install_sources
134
+
135
+ assert_raise Tinderbox::ManualInstallError do
136
+ @tgr.install
137
+ end
138
+ end
139
+
140
+ def test_install_rake
141
+ o = Object.new
142
+ def o.search(pattern)
143
+ rake = Gem::Specification.new
144
+ rake.name = 'rake'
145
+ rake.version = '999.999.999'
146
+ rake
147
+ end
148
+ sic = Gem::SourceInfoCache.new
149
+ sic_e = Gem::SourceInfoCacheEntry.new o, 0
150
+ sic.cache_data = { 'foo' => sic_e }
151
+ Gem::SourceInfoCache.cache = sic
152
+
153
+ @tgr.sandbox_setup
154
+ @tgr.installed_gems = []
155
+ @tgr.install_sources
156
+ log = @tgr.install_rake
157
+
158
+ deny_empty Dir[File.join(@sandbox_dir, 'gems', 'rake-*')]
159
+
160
+ expected = <<-EOF
161
+ !!! HAS Rakefile, DOES NOT DEPEND ON RAKE! NEEDS s.add_dependency 'rake'
162
+ ### rake installed, even though you claim not to need it
163
+ EOF
164
+
165
+ assert_equal expected, log
166
+ ensure
167
+ Gem::SourceInfoCache.instance_variable_set :@cache, nil
168
+ end
169
+
170
+ def test_install_rspec
171
+ o = Object.new
172
+ def o.search(pattern)
173
+ rake = Gem::Specification.new
174
+ rake.name = 'rspec'
175
+ rake.version = '999.999.999'
176
+ rake
177
+ end
178
+ sic = Gem::SourceInfoCache.new
179
+ sic_e = Gem::SourceInfoCacheEntry.new o, 0
180
+ sic.cache_data = { 'foo' => sic_e }
181
+ Gem::SourceInfoCache.cache = sic
182
+
183
+ @tgr.sandbox_setup
184
+ @tgr.installed_gems = []
185
+ @tgr.install_sources
186
+ log = @tgr.install_rspec 'message'
187
+
188
+ deny_empty Dir[File.join(@sandbox_dir, 'gems', 'rspec-*')]
189
+
190
+ expected = <<-EOF
191
+ !!! HAS message, DOES NOT DEPEND ON RSPEC! NEEDS s.add_dependency 'rspec'
192
+ ### RSpec installed, even though you claim not to need it
193
+ EOF
194
+
195
+ assert_equal expected, log
196
+ ensure
197
+ Gem::SourceInfoCache.instance_variable_set :@cache, nil
198
+ end
199
+
200
+ def test_install_sources
201
+ @tgr.sandbox_setup
202
+ @tgr.install_sources
203
+
204
+ assert_equal true, File.exist?(File.join(@sandbox_dir, 'source_cache'))
205
+ deny_empty Dir["#{File.join @sandbox_dir, 'gems', 'sources'}-*"]
206
+ end
207
+
208
+ def test_passed_eh
209
+ status = Object.new
210
+ def status.exitstatus() 0; end
211
+
212
+ log = ""
213
+ tested = @tgr.passed? status
214
+
215
+ assert_equal "", @tgr.log
216
+
217
+ deny tested
218
+ deny @tgr.successful
219
+ end
220
+
221
+ def test_passed_eh_spec
222
+ status = Object.new
223
+ def status.exitstatus() 0; end
224
+
225
+ @tgr.log = "1 specification, 0 failures\n"
226
+ tested = @tgr.passed? status
227
+
228
+ assert_equal "1 specification, 0 failures\n", @tgr.log
229
+
230
+ assert tested
231
+ assert @tgr.successful
232
+ end
233
+
234
+ def test_passed_eh_spec_broken
235
+ status = Object.new
236
+ def status.exitstatus() 0; end
237
+
238
+ @tgr.log = "1 specification, 1 failure\n"
239
+ tested = @tgr.passed? status
240
+
241
+ expected = <<-EOF
242
+ 1 specification, 1 failure
243
+ !!! Project has broken spec target, exited with 0 after spec failure
244
+ EOF
245
+
246
+ assert_equal expected, @tgr.log
247
+
248
+ assert tested
249
+ deny @tgr.successful
250
+ end
251
+
252
+ def test_passed_eh_spec_exit_failed
253
+ status = Object.new
254
+ def status.exitstatus() 1; end
255
+
256
+ @tgr.log = "1 specification, 0 failures\n"
257
+ tested = @tgr.passed? status
258
+ assert_equal "1 specification, 0 failures\n", @tgr.log
259
+
260
+ assert tested
261
+ deny @tgr.successful
262
+ end
263
+
264
+ def test_passed_eh_spec_no_assertions
265
+ status = Object.new
266
+ def status.exitstatus() 0; end
267
+
268
+ @tgr.log = "0 specifications, 0 failures\n"
269
+ tested = @tgr.passed? status
270
+
271
+ expected = <<-EOF
272
+ 0 specifications, 0 failures
273
+ !!! No output indicating success found
274
+ EOF
275
+
276
+ assert_equal expected, @tgr.log
277
+
278
+ assert tested
279
+ deny @tgr.successful
280
+ end
281
+
282
+ def test_passed_eh_test
283
+ status = Object.new
284
+ def status.exitstatus() 0; end
285
+
286
+ @tgr.log = "1 tests, 1 assertions, 0 failures, 0 errors\n"
287
+ tested = @tgr.passed? status
288
+
289
+ assert_equal "1 tests, 1 assertions, 0 failures, 0 errors\n", @tgr.log
290
+
291
+ assert tested
292
+ assert @tgr.successful
293
+ end
294
+
295
+ def test_passed_eh_test_broken
296
+ status = Object.new
297
+ def status.exitstatus() 0; end
298
+
299
+ @tgr.log = "1 tests, 1 assertions, 1 failures, 0 errors\n"
300
+ tested = @tgr.passed? status
301
+
302
+ expected = <<-EOF
303
+ 1 tests, 1 assertions, 1 failures, 0 errors
304
+ !!! Project has broken test target, exited with 0 after test failure
305
+ EOF
306
+
307
+ assert_equal expected, @tgr.log
308
+
309
+ assert tested
310
+ deny @tgr.successful
311
+ end
312
+
313
+ def test_passed_eh_test_exit_failed
314
+ status = Object.new
315
+ def status.exitstatus() 1; end
316
+
317
+ @tgr.log = "1 tests, 1 assertions, 0 failures, 0 errors\n"
318
+ tested = @tgr.passed? status
319
+ assert_equal "1 tests, 1 assertions, 0 failures, 0 errors\n", @tgr.log
320
+
321
+ assert tested
322
+ deny @tgr.successful
323
+ end
324
+
325
+ def test_passed_eh_test_no_assertions
326
+ status = Object.new
327
+ def status.exitstatus() 0; end
328
+
329
+ @tgr.log = "1 tests, 0 assertions, 0 failures, 0 errors\n"
330
+ tested = @tgr.passed? status
331
+
332
+ expected = <<-EOF
333
+ 1 tests, 0 assertions, 0 failures, 0 errors
334
+ !!! No output indicating success found
335
+ EOF
336
+
337
+ assert_equal expected, @tgr.log
338
+
339
+ assert tested
340
+ deny @tgr.successful
341
+ end
342
+
343
+ def test_rake_installed_eh
344
+ e = assert_raises RuntimeError do
345
+ @tgr.rake_installed?
346
+ end
347
+
348
+ assert_equal 'you haven\'t installed anything yet', e.message
349
+
350
+ @tgr.installed_gems = []
351
+
352
+ assert_equal false, @tgr.rake_installed?
353
+
354
+ @tgr.installed_gems = [@rake]
355
+
356
+ assert_equal true, @tgr.rake_installed?
357
+ end
358
+
359
+ def test_rspec_installed_eh
360
+ e = assert_raises RuntimeError do
361
+ @tgr.rspec_installed?
362
+ end
363
+
364
+ assert_equal 'you haven\'t installed anything yet', e.message
365
+
366
+ @tgr.installed_gems = []
367
+
368
+ assert_equal false, @tgr.rspec_installed?
369
+
370
+ @tgr.installed_gems = [@rspec]
371
+
372
+ assert_equal true, @tgr.rspec_installed?
373
+ end
374
+
375
+ def test_ruby # HACK lame
376
+ ruby_exe = Config::CONFIG['ruby_install_name'] + Config::CONFIG['EXEEXT']
377
+ ruby = File.join Config::CONFIG['bindir'], ruby_exe
378
+
379
+ assert_equal ruby, @tgr.ruby
380
+ end
381
+
382
+ def test_run
383
+ build = @tgr.run
384
+
385
+ assert_equal true, File.exist?(File.join(@sandbox_dir, 'source_cache'))
386
+
387
+ assert_equal 0, build.duration
388
+ assert_equal false, build.successful
389
+
390
+ expected = <<-EOF.strip
391
+ ### installing some_test_gem-1.2.3 + dependencies
392
+ ### some_test_gem-1.2.3
393
+ ### testing some_test_gem-1.2.3
394
+ !!! could not figure out how to test some_test_gem-1.2.3
395
+ EOF
396
+
397
+ assert_equal expected, build.log
398
+ end
399
+
400
+ def test_run_pass
401
+ def @tgr.test
402
+ @log = "passed!"
403
+ @successful = true
404
+ @duration = 1.0
405
+ nil
406
+ end
407
+
408
+ build = @tgr.run
409
+
410
+ assert_equal true, File.exist?(File.join(@sandbox_dir, 'source_cache'))
411
+
412
+ assert_equal 1.0, build.duration
413
+ assert_equal true, build.successful
414
+
415
+ expected = <<-EOF.strip
416
+ ### installing some_test_gem-1.2.3 + dependencies
417
+ ### some_test_gem-1.2.3
418
+ ### testing some_test_gem-1.2.3
419
+ passed!
420
+ EOF
421
+
422
+ assert_equal expected, build.log
423
+ end
424
+
425
+ def test_run_command
426
+ tested = @tgr.run_command "ruby -e '$stderr.puts \"bye\"; $stdout.puts \"hi\"'"
427
+
428
+ expected = <<-EOF
429
+ ### ruby -e '$stderr.puts \"bye\"; $stdout.puts \"hi\"'
430
+ bye
431
+ hi
432
+ EOF
433
+
434
+ assert_equal expected, @tgr.log
435
+ assert_operator 0, :<, @tgr.duration
436
+ deny tested
437
+ end
438
+
439
+ def test_run_command_tested
440
+ tested = @tgr.run_command "ruby -e \"puts '1 specification, 1 failure'\""
441
+
442
+ assert tested, @tgr.log
443
+ end
444
+
445
+ def test_sandbox_cleanup
446
+ FileUtils.mkpath @sandbox_dir
447
+
448
+ assert_equal true, File.exist?(@sandbox_dir)
449
+
450
+ @tgr.sandbox_cleanup
451
+
452
+ assert_equal false, File.exist?(@sandbox_dir)
453
+ end
454
+
455
+ def test_sandbox_cleanup_no_dir
456
+ assert_equal false, File.exist?(@sandbox_dir)
457
+
458
+ @tgr.sandbox_cleanup
459
+
460
+ assert_equal false, File.exist?(@sandbox_dir)
461
+ end
462
+
463
+ def test_sandbox_setup
464
+ @tgr.sandbox_setup
465
+
466
+ assert_equal true, File.exist?(@sandbox_dir)
467
+ assert_equal true, File.exist?(File.join(@sandbox_dir, 'gems'))
468
+ assert_equal @sandbox_dir, ENV['GEM_HOME']
469
+ assert_equal @sandbox_dir, Gem.dir
470
+
471
+ e = assert_raise RuntimeError do
472
+ @tgr.sandbox_setup
473
+ end
474
+
475
+ assert_equal "#{@sandbox_dir} already exists", e.message
476
+ end
477
+
478
+ def test_test_best_effort
479
+ util_test_setup
480
+
481
+ File.open File.join(@gemspec.full_gem_path, 'Rakefile'), 'w' do |fp|
482
+ fp.write <<-EOF
483
+ require 'rake/testtask'
484
+
485
+ task :test do exit 1 end
486
+ EOF
487
+ end
488
+
489
+ File.open File.join(@gemspec.full_gem_path, 'Makefile'), 'w' do |fp|
490
+ fp.write <<-EOF
491
+ test:
492
+ \texit 1
493
+
494
+ .PHONY: test
495
+ EOF
496
+ end
497
+
498
+ util_test_assertions :test, true, -1
499
+ end
500
+
501
+ def test_test_no_tests
502
+ util_test_setup
503
+
504
+ @tgr.gemspec = @gemspec
505
+ @tgr.test
506
+
507
+ assert_equal 0, @tgr.duration
508
+ assert_equal false, @tgr.successful
509
+
510
+ expected = <<-EOF.strip
511
+ !!! could not figure out how to test some_test_gem-1.2.3
512
+ EOF
513
+
514
+ assert_equal expected, @tgr.log
515
+ end
516
+
517
+ def test_test_Makefile_fail
518
+ util_test_add_Makefile
519
+ util_test_assertions :test, false, -2
520
+ end
521
+
522
+ def test_test_Makefile_pass
523
+ util_test_add_Makefile
524
+ util_test_assertions :test, true, -1
525
+ end
526
+
527
+ def test_test_Rakefile_spec_fail
528
+ util_test_add_Rakefile :spec
529
+ util_test_assertions :spec, false, -1
530
+ end
531
+
532
+ def test_test_Rakefile_spec_pass
533
+ util_test_add_Rakefile :spec
534
+ util_test_assertions :spec, true, -1
535
+ end
536
+
537
+ def test_test_Rakefile_test_fail
538
+ util_test_add_Rakefile
539
+ util_test_assertions :test, false, -1
540
+ end
541
+
542
+ def test_test_Rakefile_test_pass
543
+ util_test_add_Rakefile
544
+ util_test_assertions :test, true, -1
545
+ end
546
+
547
+ def test_test_testrb_fail
548
+ util_test_assertions :test, false, -1
549
+ end
550
+
551
+ def test_test_testrb_pass
552
+ util_test_assertions :test, true, -1
553
+
554
+ assert_equal "### #{@tgr.ruby} -Ilib:other -S #{@tgr.testrb} test",
555
+ @tgr.log.split("\n").first
556
+ end
557
+
558
+ def test_test_spec_fail
559
+ util_test_assertions :spec, false, -1
560
+ end
561
+
562
+ def test_test_spec_pass
563
+ util_test_assertions :spec, true, -1
564
+ end
565
+
566
+ def test_testrb # HACK lame
567
+ testrb_exe = 'testrb' + (RUBY_PLATFORM =~ /mswin/ ? '.bat' : '')
568
+ testrb = File.join Config::CONFIG['bindir'], testrb_exe
569
+
570
+ assert_equal testrb, @tgr.testrb
571
+ end
572
+
573
+ def util_test_add_Makefile
574
+ util_test_setup
575
+ File.open File.join(@gemspec.full_gem_path, 'Makefile'), 'w' do |fp|
576
+ fp.write <<-EOF
577
+ test:
578
+ \ttestrb test
579
+
580
+ .PHONY: test
581
+ EOF
582
+ end
583
+ end
584
+
585
+ def util_test_add_Rakefile(type = :test)
586
+ util_test_setup
587
+ File.open File.join(@gemspec.full_gem_path, 'Rakefile'), 'w' do |fp|
588
+ fp.write <<-EOF
589
+ require 'rake/testtask'
590
+ require 'spec/rake/spectask
591
+
592
+ EOF
593
+
594
+ case type
595
+ when :test then
596
+ fp.write <<-EOF
597
+ Rake::TestTask.new :test do |t|
598
+ t.test_files = FileList['test/test_*.rb']
599
+ end
600
+ EOF
601
+ when :spec then
602
+ fp.write <<-EOF
603
+ Spec::Rake::SpecTask.new
604
+ EOF
605
+ else
606
+ raise ArgumentError, "unknown type #{type.inspect}"
607
+ end
608
+ end
609
+ end
610
+
611
+ def util_test_add_test(passes)
612
+ test_dir = File.join @gemspec.full_gem_path, 'test'
613
+ @test_file = File.join test_dir, 'test_something.rb'
614
+ FileUtils.mkpath test_dir
615
+
616
+ File.open @test_file, 'w' do |fp|
617
+ fp.write <<-EOF
618
+ require 'test/unit'
619
+
620
+ class TestSomething < Test::Unit::TestCase
621
+ def test_something
622
+ assert #{passes}
623
+ end
624
+ end
625
+ EOF
626
+ end
627
+ end
628
+
629
+ def util_test_add_spec(passes)
630
+ test_dir = File.join @gemspec.full_gem_path, 'spec'
631
+ @spec_file = File.join test_dir, 'true_spec.rb'
632
+ FileUtils.mkpath test_dir
633
+
634
+ File.open @spec_file, 'w' do |fp|
635
+ fp.write <<-EOF
636
+ context "dummy spec" do
637
+ specify "should be true" do
638
+ #{passes}.should == true
639
+ end
640
+ end
641
+ EOF
642
+ end
643
+ end
644
+
645
+ def util_test_assertions(type, passes, count_index)
646
+ util_test_setup
647
+ case type
648
+ when :test then util_test_add_test passes
649
+ when :spec then util_test_add_spec passes
650
+ else raise ArgumentError, "unknown test type #{type.inspect}"
651
+ end
652
+
653
+ @tgr.gemspec = @gemspec
654
+
655
+ ENV['GEM_HOME'] = nil
656
+ successful = @tgr.test
657
+
658
+ assert_operator 0, :<, @tgr.duration, 'Time taken too short'
659
+ assert_equal passes, @tgr.successful, 'The tests failed'
660
+
661
+ log = @tgr.log.split "\n"
662
+
663
+ failures = passes ? 0 : 1
664
+
665
+ expected = case type
666
+ when :test then
667
+ "1 tests, 1 assertions, #{failures} failures, 0 errors"
668
+ when :spec then
669
+ "1 specification, #{failures} failure#{passes ? 's' : ''}"
670
+ end
671
+
672
+ #log.each_with_index do |l, i| puts "#{i}\t#{l[0..10]}" end
673
+ assert_equal expected, log[count_index]
674
+ end
675
+
676
+ def util_test_setup
677
+ return if @util_test_setup
678
+ @util_test_setup = true
679
+ @tgr.installed_gems = [@rake]
680
+
681
+ ENV['GEM_HOME'] = @sandbox_dir
682
+ Gem.clear_paths
683
+ @gemspec.loaded_from = File.join Gem.dir, 'gems', @gem_full_name
684
+ FileUtils.mkpath @gemspec.full_gem_path
685
+ end
686
+
687
+ end
688
+