warbler 0.9.14 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,425 @@
1
+ #--
2
+ # Copyright (c) 2010 Engine Yard, Inc.
3
+ # This source code is available under the MIT license.
4
+ # See the file LICENSE.txt for details.
5
+ #++
6
+
7
+ require File.dirname(__FILE__) + '/../spec_helper'
8
+
9
+ describe Warbler::War do
10
+ before(:each) do
11
+ @rake = Rake::Application.new
12
+ Rake.application = @rake
13
+ verbose(false)
14
+ @pwd = Dir.getwd
15
+ Dir.chdir("spec/sample")
16
+ mkdir_p "log"
17
+ touch "log/test.log"
18
+ @config = Warbler::Config.new do |config|
19
+ config.war_name = "warbler"
20
+ config.gems = ["rake"]
21
+ config.webxml.jruby.max.runtimes = 5
22
+ end
23
+ @war = Warbler::War.new
24
+ end
25
+
26
+ after(:each) do
27
+ rm_rf "log"
28
+ rm_rf ".bundle"
29
+ rm_f FileList["*.war", "config.ru", "*web.xml*", "config/web.xml*",
30
+ "config/warble.rb", "file.txt", 'manifest', 'Gemfile*']
31
+ Dir.chdir(@pwd)
32
+ end
33
+
34
+ def file_list(regex)
35
+ @war.files.keys.select {|f| f =~ regex }
36
+ end
37
+
38
+ it "should collect files in public" do
39
+ @war.apply(@config)
40
+ file_list(%r{^index\.html}).should_not be_empty
41
+ end
42
+
43
+ it "should collect gem files" do
44
+ @config.gems << "rake"
45
+ @war.apply(@config)
46
+ file_list(%r{WEB-INF/gems/gems/rake.*/lib/rake.rb}).should_not be_empty
47
+ file_list(%r{WEB-INF/gems/specifications/rake.*\.gemspec}).should_not be_empty
48
+ end
49
+
50
+ it "should not include log files by default" do
51
+ @war.apply(@config)
52
+ file_list(%r{WEB-INF/log}).should_not be_empty
53
+ file_list(%r{WEB-INF/log/.*\.log}).should be_empty
54
+ end
55
+
56
+ def expand_webxml
57
+ @war.apply(@config)
58
+ @war.files.should include("WEB-INF/web.xml")
59
+ require 'rexml/document'
60
+ REXML::Document.new(@war.files["WEB-INF/web.xml"]).root.elements
61
+ end
62
+
63
+ it "should create a web.xml file" do
64
+ elements = expand_webxml
65
+ elements.to_a(
66
+ "context-param/param-name[text()='jruby.max.runtimes']"
67
+ ).should_not be_empty
68
+ elements.to_a(
69
+ "context-param/param-name[text()='jruby.max.runtimes']/../param-value"
70
+ ).first.text.should == "5"
71
+ end
72
+
73
+ it "should include custom context parameters in web.xml" do
74
+ @config.webxml.some.custom.config = "myconfig"
75
+ elements = expand_webxml
76
+ elements.to_a(
77
+ "context-param/param-name[text()='some.custom.config']"
78
+ ).should_not be_empty
79
+ elements.to_a(
80
+ "context-param/param-name[text()='some.custom.config']/../param-value"
81
+ ).first.text.should == "myconfig"
82
+ end
83
+
84
+ it "should allow one jndi resource to be included" do
85
+ @config.webxml.jndi = 'jndi/rails'
86
+ elements = expand_webxml
87
+ elements.to_a(
88
+ "resource-ref/res-ref-name[text()='jndi/rails']"
89
+ ).should_not be_empty
90
+ end
91
+
92
+ it "should allow multiple jndi resources to be included" do
93
+ @config.webxml.jndi = ['jndi/rails1', 'jndi/rails2']
94
+ elements = expand_webxml
95
+ elements.to_a(
96
+ "resource-ref/res-ref-name[text()='jndi/rails1']"
97
+ ).should_not be_empty
98
+ elements.to_a(
99
+ "resource-ref/res-ref-name[text()='jndi/rails2']"
100
+ ).should_not be_empty
101
+ end
102
+
103
+ it "should not include any ignored context parameters" do
104
+ @config.webxml.foo = "bar"
105
+ @config.webxml.ignored << "foo"
106
+ elements = expand_webxml
107
+ elements.to_a(
108
+ "context-param/param-name[text()='foo']"
109
+ ).should be_empty
110
+ elements.to_a(
111
+ "context-param/param-name[text()='ignored']"
112
+ ).should be_empty
113
+ elements.to_a(
114
+ "context-param/param-name[text()='jndi']"
115
+ ).should be_empty
116
+ end
117
+
118
+ it "should use a config/web.xml if it exists" do
119
+ mkdir_p "config"
120
+ touch "config/web.xml"
121
+ @war.apply(Warbler::Config.new)
122
+ @war.files["WEB-INF/web.xml"].should == "config/web.xml"
123
+ end
124
+
125
+ it "should use a config/web.xml.erb if it exists" do
126
+ mkdir_p "config"
127
+ File.open("config/web.xml.erb", "w") {|f| f << "Hi <%= webxml.public.root %>" }
128
+ @war.apply(Warbler::Config.new)
129
+ @war.files["WEB-INF/web.xml"].should_not be_nil
130
+ @war.files["WEB-INF/web.xml"].read.should == "Hi /"
131
+ end
132
+
133
+ it "should collect java libraries" do
134
+ @war.apply(@config)
135
+ file_list(%r{WEB-INF/lib/jruby-.*\.jar$}).should_not be_empty
136
+ end
137
+
138
+ it "should collect application files" do
139
+ @war.apply(@config)
140
+ file_list(%r{WEB-INF/app$}).should_not be_empty
141
+ file_list(%r{WEB-INF/config$}).should_not be_empty
142
+ file_list(%r{WEB-INF/lib$}).should_not be_empty
143
+ end
144
+
145
+ it "should accept an autodeploy directory where the war should be created" do
146
+ require 'tmpdir'
147
+ @config.autodeploy_dir = Dir::tmpdir
148
+ touch "file.txt"
149
+ @war.files["file.txt"] = "file.txt"
150
+ silence { @war.create(@config) }
151
+ File.exist?(File.join("#{Dir::tmpdir}","warbler.war")).should == true
152
+ end
153
+
154
+ it "should accept a custom manifest file" do
155
+ touch 'manifest'
156
+ @config.manifest_file = 'manifest'
157
+ @war.apply(@config)
158
+ @war.files['META-INF/MANIFEST.MF'].should == "manifest"
159
+ end
160
+
161
+ it "should be able to exclude files from the .war" do
162
+ @config.excludes += FileList['lib/tasks/utils.rake']
163
+ @war.apply(@config)
164
+ file_list(%r{lib/tasks/utils.rake}).should be_empty
165
+ end
166
+
167
+ it "should read configuration from #{Warbler::Config::FILE}" do
168
+ mkdir_p "config"
169
+ File.open(Warbler::Config::FILE, "w") do |dest|
170
+ contents =
171
+ File.open("#{Warbler::WARBLER_HOME}/warble.rb") do |src|
172
+ src.read
173
+ end
174
+ dest << contents.sub(/# config\.war_name/, 'config.war_name'
175
+ ).sub(/# config.gems << "tzinfo"/, 'config.gems = []')
176
+ end
177
+ t = Warbler::Task.new "warble"
178
+ t.config.war_name.should == "mywar"
179
+ end
180
+
181
+ it "should fail if a gem is requested that is not installed" do
182
+ @config.gems = ["nonexistent-gem"]
183
+ lambda {
184
+ Warbler::Task.new "warble", @config
185
+ @war.apply(@config)
186
+ }.should raise_error
187
+ end
188
+
189
+ it "should allow specification of dependency by Gem::Dependency" do
190
+ spec = mock "gem spec"
191
+ spec.stub!(:full_name).and_return "hpricot-0.6.157"
192
+ spec.stub!(:full_gem_path).and_return "hpricot-0.6.157"
193
+ spec.stub!(:loaded_from).and_return "hpricot.gemspec"
194
+ spec.stub!(:files).and_return ["Rakefile"]
195
+ spec.stub!(:dependencies).and_return []
196
+ Gem.source_index.should_receive(:search).and_return do |gem|
197
+ gem.name.should == "hpricot"
198
+ [spec]
199
+ end
200
+ @config.gems = [Gem::Dependency.new("hpricot", "> 0.6")]
201
+ @war.apply(@config)
202
+ end
203
+
204
+ it "should copy loose java classes to WEB-INF/classes" do
205
+ @config.java_classes = FileList["Rakefile"]
206
+ @war.apply(@config)
207
+ file_list(%r{WEB-INF/classes/Rakefile$}).should_not be_empty
208
+ end
209
+
210
+ def mock_rails_module
211
+ rails = Module.new
212
+ Object.const_set("Rails", rails)
213
+ version = Module.new
214
+ rails.const_set("VERSION", version)
215
+ version.const_set("STRING", "2.1.0")
216
+ rails
217
+ end
218
+
219
+ def mock_merb_module
220
+ merb = Module.new
221
+ silence { Object.const_set("Merb", merb) }
222
+ boot_loader = Module.new
223
+ merb.const_set("BootLoader", boot_loader)
224
+ merb.const_set("VERSION", "1.0")
225
+ dependencies = Class.new do
226
+ @@dependencies = []
227
+ def self.dependencies
228
+ @@dependencies
229
+ end
230
+ def self.dependencies=(deps)
231
+ @@dependencies = deps
232
+ end
233
+ end
234
+ boot_loader.const_set("Dependencies", dependencies)
235
+ dependencies
236
+ end
237
+
238
+ it "should auto-detect a Rails application" do
239
+ task :environment do
240
+ mock_rails_module
241
+ end
242
+ @config = Warbler::Config.new
243
+ @config.webxml.booter.should == :rails
244
+ @config.gems["rails"].should == "2.1.0"
245
+ end
246
+
247
+ it "should provide Rails gems by default, unless vendor/rails is present" do
248
+ rails = nil
249
+ task :environment do
250
+ rails = mock_rails_module
251
+ end
252
+
253
+ config = Warbler::Config.new
254
+ config.gems.should have_key("rails")
255
+
256
+ mkdir_p "vendor/rails"
257
+ config = Warbler::Config.new
258
+ config.gems.should be_empty
259
+
260
+ rm_rf "vendor/rails"
261
+ rails.stub!(:vendor_rails?).and_return true
262
+ config = Warbler::Config.new
263
+ config.gems.should be_empty
264
+ end
265
+
266
+ it "should not try to autodetect frameworks when Warbler.framework_detection is false" do
267
+ begin
268
+ Warbler.framework_detection = false
269
+ task :environment
270
+ config = Warbler::Config.new
271
+ config.webxml.booter.should_not == :rails
272
+ t = Rake::Task['environment']
273
+ class << t; public :instance_variable_get; end
274
+ t.instance_variable_get("@already_invoked").should == false
275
+ ensure
276
+ Warbler.framework_detection = true
277
+ end
278
+ end
279
+
280
+ it "should auto-detect a Merb application" do
281
+ task :merb_env do
282
+ mock_merb_module
283
+ end
284
+ @config = Warbler::Config.new
285
+ @config.webxml.booter.should == :merb
286
+ @config.gems.keys.should_not include("rails")
287
+ end
288
+
289
+ it "should auto-detect a Rack application with a config.ru file" do
290
+ rackup = "run Proc.new {|env| [200, {}, ['Hello World']]}"
291
+ File.open("config.ru", "w") {|f| f << rackup }
292
+ @config = Warbler::Config.new
293
+ @config.webxml.booter.should == :rack
294
+ @config.webxml.rackup.should == rackup
295
+ end
296
+
297
+ it "should automatically add Rails.configuration.gems to the list of gems" do
298
+ task :environment do
299
+ rails = mock_rails_module
300
+ config = mock "config"
301
+ rails.stub!(:configuration).and_return(config)
302
+ gem = mock "gem"
303
+ gem.stub!(:name).and_return "hpricot"
304
+ gem.stub!(:requirement).and_return Gem::Requirement.new("=0.6")
305
+ config.stub!(:gems).and_return [gem]
306
+ end
307
+
308
+ @config = Warbler::Config.new
309
+ @config.webxml.booter.should == :rails
310
+ @config.gems.keys.should include(Gem::Dependency.new("hpricot", Gem::Requirement.new("=0.6")))
311
+ end
312
+
313
+ it "should automatically add Merb::BootLoader::Dependencies.dependencies to the list of gems" do
314
+ task :merb_env do
315
+ deps = mock_merb_module
316
+ deps.dependencies = [Gem::Dependency.new("merb-core", ">= 1.0.6.1")]
317
+ end
318
+ @config = Warbler::Config.new
319
+ @config.webxml.booter.should == :merb
320
+ @config.gems.keys.should include(Gem::Dependency.new("merb-core", ">= 1.0.6.1"))
321
+ end
322
+
323
+ it "should skip Merb development dependencies" do
324
+ task :merb_env do
325
+ deps = mock_merb_module
326
+ deps.dependencies = [Gem::Dependency.new("rake", "= #{RAKEVERSION}", :development)]
327
+ end
328
+ @war.apply(Warbler::Config.new)
329
+ file_list(/rake-#{RAKEVERSION}/).should be_empty
330
+ end
331
+
332
+ it "should warn about using Merb < 1.0" do
333
+ task :merb_env do
334
+ silence { Object.const_set("Merb", Module.new) }
335
+ end
336
+ @config = silence { Warbler::Config.new }
337
+ @config.webxml.booter.should == :merb
338
+ end
339
+
340
+ it "should set the jruby max runtimes to 1 when MT Rails is detected" do
341
+ task :environment do
342
+ rails = mock_rails_module
343
+ config = mock "config"
344
+ rails.stub!(:configuration).and_return(config)
345
+ config.stub!(:threadsafe!)
346
+ config.should_receive(:allow_concurrency).and_return true
347
+ config.should_receive(:preload_frameworks).and_return true
348
+ end
349
+ @config = Warbler::Config.new
350
+ @config.webxml.booter.should == :rails
351
+ @config.webxml.jruby.max.runtimes.should == 1
352
+ end
353
+
354
+ it "should skip directories that don't exist in config.dirs and print a warning" do
355
+ @config.dirs = %w(lib notexist)
356
+ silence { @war.apply(@config) }
357
+ file_list(%r{WEB-INF/lib}).should_not be_empty
358
+ file_list(%r{WEB-INF/notexist}).should be_empty
359
+ end
360
+
361
+ it "should write gems to location specified by gem_path" do
362
+ @config = Warbler::Config.new {|c| c.gem_path = "/WEB-INF/jewels"; c.gems << 'rake' }
363
+ elements = expand_webxml
364
+ file_list(%r{WEB-INF/jewels}).should_not be_empty
365
+ elements.to_a(
366
+ "context-param/param-name[text()='gem.path']"
367
+ ).should_not be_empty
368
+ elements.to_a(
369
+ "context-param/param-name[text()='gem.path']/../param-value"
370
+ ).first.text.should == "/WEB-INF/jewels"
371
+
372
+ end
373
+
374
+ it "should detect a Bundler Gemfile and process only its gems" do
375
+ File.open("Gemfile", "w") {|f| f << "gem 'rspec'"}
376
+ @war.apply(Warbler::Config.new {|c| c.gems << "rake"})
377
+ file_list(%r{WEB-INF/Gemfile}).should_not be_empty
378
+ file_list(%r{WEB-INF/gems/specifications/rspec}).should_not be_empty
379
+ file_list(%r{WEB-INF/gems/specifications/rake}).should be_empty
380
+ end
381
+
382
+ it "should write a Bundler environment file into the war" do
383
+ File.open("Gemfile", "w") {|f| f << "gem 'rspec'"}
384
+ @war.apply(Warbler::Config.new)
385
+ file_list(%r{WEB-INF/\.bundle/environment\.rb}).should_not be_empty
386
+ end
387
+
388
+ it "should allow overriding of the gem path when using Bundler" do
389
+ File.open("Gemfile", "w") {|f| f << "gem 'rspec'"}
390
+ @war.apply(Warbler::Config.new {|c| c.gem_path = '/WEB-INF/jewels' })
391
+ file_list(%r{WEB-INF/jewels/specifications/rspec}).should_not be_empty
392
+ IO.readlines(".bundle/war-environment.rb").grep(/rspec/).last.should =~ %r{jewels/specifications}m
393
+ end
394
+
395
+ it "should not let the framework load Bundler from the locked environment" do
396
+ task :environment do
397
+ File.exist?('.bundle/environment.rb').should_not be_true
398
+ mock_rails_module
399
+ end
400
+
401
+ File.open("Gemfile", "w") {|f| f << "gem 'rspec'"}
402
+ `ruby -S bundle lock`
403
+ File.exist?('.bundle/environment.rb').should be_true
404
+ @war.apply(Warbler::Config.new)
405
+ hash = eval("[" + IO.readlines(".bundle/environment.rb").grep(/rspec/).last + "]").first
406
+ hash[:load_paths].each {|p| File.exist?(p).should be_true }
407
+ end
408
+
409
+ it "should allow adding additional WEB-INF files via config.webinf_files" do
410
+ File.open("myserver-web.xml", "w") do |f|
411
+ f << "<web-app></web-app>"
412
+ end
413
+ @war.apply(Warbler::Config.new {|c| c.webinf_files = FileList['myserver-web.xml'] })
414
+ file_list(%r{WEB-INF/myserver-web.xml}).should_not be_empty
415
+ end
416
+
417
+ it "should allow expanding of additional WEB-INF files via config.webinf_files" do
418
+ File.open("myserver-web.xml.erb", "w") do |f|
419
+ f << "<web-app><%= webxml.rails.env %></web-app>"
420
+ end
421
+ @war.apply(Warbler::Config.new {|c| c.webinf_files = FileList['myserver-web.xml.erb'] })
422
+ file_list(%r{WEB-INF/myserver-web.xml}).should_not be_empty
423
+ @war.files['WEB-INF/myserver-web.xml'].read.should =~ /web-app.*production/
424
+ end
425
+ end
@@ -3,9 +3,6 @@
3
3
 
4
4
  # Warbler web application assembly configuration file
5
5
  Warbler::Config.new do |config|
6
- # Temporary directory where the application is staged
7
- # config.staging_dir = "tmp/war"
8
-
9
6
  # Application directories to be included in the webapp.
10
7
  config.dirs = %w(app config lib log vendor tmp)
11
8
 
@@ -30,9 +27,28 @@ Warbler::Config.new do |config|
30
27
  # for details of how to specify a pathmap.
31
28
  # config.pathmaps.java_classes << "%{target/classes/,}p"
32
29
 
33
- # Gems to be included. You need to tell Warbler which gems your application needs
34
- # so that they can be packaged in the war file.
35
- # The Rails gems are included by default unless the vendor/rails directory is present.
30
+ # Path to the pre-bundled gem directory inside the war file. Default
31
+ # is 'WEB-INF/gems'. Specify path if gems are already bundled
32
+ # before running Warbler. This also sets 'gem.path' inside web.xml.
33
+ # config.gem_path = "WEB-INF/vendor/bundler_gems"
34
+
35
+ # Bundler support is built-in. If Warbler finds a Gemfile in the
36
+ # project directory, it will be used to collect the gems to bundle
37
+ # in your application. If you wish to explicitly disable this
38
+ # functionality, uncomment here.
39
+ # config.bundler = false
40
+
41
+ # Files for WEB-INF directory (next to web.xml). This contains
42
+ # web.xml by default. If there is an .erb-File it will be processed
43
+ # with webxml-config. You may want to exclude this file via
44
+ # config.excludes.
45
+ # config.webinf_files += FileList["jboss-web.xml"]
46
+
47
+ # Other gems to be included. You need to tell Warbler which gems
48
+ # your application needs so that they can be packaged in the war
49
+ # file.
50
+ # The Rails gems are included by default unless the vendor/rails
51
+ # directory is present.
36
52
  # config.gems += ["activerecord-jdbcmysql-adapter", "jruby-openssl"]
37
53
  # config.gems << "tzinfo"
38
54
 
@@ -48,8 +64,9 @@ Warbler::Config.new do |config|
48
64
  # config.gems << /^merb-/
49
65
  # config.gems << Gem::Dependency.new("merb-core", "= 0.9.3")
50
66
 
51
- # Include gem dependencies not mentioned specifically
52
- config.gem_dependencies = true
67
+ # Include gem dependencies not mentioned specifically. Default is true, uncomment
68
+ # to turn off.
69
+ # config.gem_dependencies = false
53
70
 
54
71
  # Files to be included in the root of the webapp. Note that files in public
55
72
  # will have the leading 'public/' part of the path stripped during staging.
@@ -58,6 +75,9 @@ Warbler::Config.new do |config|
58
75
  # Pathmaps for controlling how public HTML files are copied into the .war
59
76
  # config.pathmaps.public_html = ["%{public/,}p"]
60
77
 
78
+ # Pathmaps for controlling how application files are copied into the .war
79
+ # config.pathmaps.application = ["WEB-INF/%p"]
80
+
61
81
  # Name of the war file (without the .war) -- defaults to the basename
62
82
  # of RAILS_ROOT
63
83
  # config.war_name = "mywar"
@@ -69,7 +89,7 @@ Warbler::Config.new do |config|
69
89
  # Value of RAILS_ENV for the webapp -- default as shown below
70
90
  # config.webxml.rails.env = ENV['RAILS_ENV'] || 'production'
71
91
 
72
- # Application booter to use, one of :rack, :rails, or :merb. (Default :rails)
92
+ # Application booter to use, one of :rack, :rails, or :merb (autodetected by default)
73
93
  # config.webxml.booter = :rails
74
94
 
75
95
  # When using the :rack booter, "Rackup" script to use.