padrino-core 0.12.8.1 → 0.12.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +13 -5
  2. data/Rakefile +1 -5
  3. data/bin/padrino +1 -1
  4. data/lib/padrino-core/application/application_setup.rb +2 -0
  5. data/lib/padrino-core/application/params_protection.rb +1 -7
  6. data/lib/padrino-core/application/routing.rb +15 -5
  7. data/lib/padrino-core/caller.rb +2 -1
  8. data/lib/padrino-core/cli/adapter.rb +11 -2
  9. data/lib/padrino-core/cli/base.rb +12 -8
  10. data/lib/padrino-core/cli/launcher.rb +12 -4
  11. data/lib/padrino-core/cli/rake_tasks.rb +24 -14
  12. data/lib/padrino-core/configuration.rb +40 -0
  13. data/lib/padrino-core/loader.rb +1 -2
  14. data/lib/padrino-core/logger.rb +71 -11
  15. data/lib/padrino-core/mounter/application_extension.rb +55 -0
  16. data/lib/padrino-core/mounter.rb +21 -62
  17. data/lib/padrino-core/reloader/rack.rb +4 -1
  18. data/lib/padrino-core/reloader/storage.rb +31 -3
  19. data/lib/padrino-core/reloader.rb +4 -2
  20. data/lib/padrino-core/version.rb +1 -1
  21. data/lib/padrino-core.rb +2 -0
  22. data/padrino-core.gemspec +1 -7
  23. data/test/fixtures/apps/custom_dependencies/custom_dependencies.rb +11 -0
  24. data/test/fixtures/apps/custom_dependencies/my_dependencies/my_dependency.rb +0 -0
  25. data/test/fixtures/apps/external_apps/fake_lib.rb +1 -0
  26. data/test/fixtures/apps/external_apps/fake_root.rb +2 -0
  27. data/test/fixtures/apps/rack_apps.rb +4 -0
  28. data/test/fixtures/apps/simple.rb +0 -1
  29. data/test/fixtures/apps/system.rb +2 -0
  30. data/test/helper.rb +4 -26
  31. data/test/test_application.rb +8 -0
  32. data/test/test_configuration.rb +29 -0
  33. data/test/test_core.rb +12 -0
  34. data/test/test_csrf_protection.rb +7 -6
  35. data/test/test_logger.rb +93 -0
  36. data/test/test_mounter.rb +15 -0
  37. data/test/test_params_protection.rb +15 -15
  38. data/test/test_reloader_simple.rb +2 -2
  39. data/test/test_reloader_storage.rb +51 -0
  40. data/test/test_reloader_system.rb +20 -0
  41. data/test/test_routing.rb +31 -2
  42. metadata +49 -46
  43. data/test/fixtures/apps/helpers/support.rb +0 -1
@@ -1,4 +1,4 @@
1
- require 'delegate'
1
+ require 'padrino-core/mounter/application_extension'
2
2
 
3
3
  module Padrino
4
4
  ##
@@ -14,55 +14,6 @@ module Padrino
14
14
  class MounterException < RuntimeError
15
15
  end
16
16
 
17
- class ApplicationWrapper < SimpleDelegator
18
- attr_accessor :uri_root
19
- attr_writer :public_folder
20
-
21
- def initialize(app, options = {})
22
- @options = options
23
- super(app)
24
- end
25
-
26
- def dependencies
27
- @__dependencies ||= Dir["#{root}/**/*.rb"]
28
- end
29
-
30
- def prerequisite
31
- @__prerequisite ||= []
32
- end
33
-
34
- def app_file
35
- return @__app_file if @__app_file
36
- obj = __getobj__
37
- @__app_file = obj.respond_to?(:app_file) ? obj.app_file : @options[:app_file]
38
- end
39
-
40
- def root
41
- return @__root if @__root
42
- obj = __getobj__
43
- @__root = obj.respond_to?(:root) ? obj.root : File.expand_path("#{app_file}/../")
44
- end
45
-
46
- def public_folder
47
- return @public_folder if @public_folder
48
- obj = __getobj__
49
- @public_folder = obj.respond_to?(:public_folder) ? obj.public_folder : ""
50
- end
51
-
52
- def app_name
53
- @__app_name ||= @options[:app_name] || __getobj__.to_s.underscore.to_sym
54
- end
55
-
56
- def setup_application!
57
- @configured ||=
58
- begin
59
- $LOAD_PATH.concat(prerequisite)
60
- Padrino.require_dependencies(dependencies, :force => true)
61
- true
62
- end
63
- end
64
- end
65
-
66
17
  attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host, :cascade
67
18
 
68
19
  ##
@@ -83,7 +34,10 @@ module Padrino
83
34
  @app_file = options[:app_file] || locate_app_file
84
35
  @app_obj = options[:app_obj] || app_constant || locate_app_object
85
36
  ensure_app_file! || ensure_app_object!
86
- @app_obj = ApplicationWrapper.new(@app_obj, options) unless padrino_application?
37
+ unless padrino_application?
38
+ @app_obj.extend ApplicationExtension
39
+ @app_obj.mounter_options = options
40
+ end
87
41
  @app_root = options[:app_root] || (@app_obj.respond_to?(:root) && @app_obj.root || File.dirname(@app_file))
88
42
  @uri_root = "/"
89
43
  @cascade = options[:cascade] ? true == options[:cascade] ? DEFAULT_CASCADE.dup : Array(options[:cascade]) : []
@@ -142,20 +96,23 @@ module Padrino
142
96
  def map_onto(router)
143
97
  app_data = self
144
98
  app_obj = @app_obj
99
+
100
+ uri_root = app_data.uri_root
101
+ public_folder_exists = File.exist?(app_obj.public_folder)
102
+
145
103
  if padrino_application?
146
- app_obj.set :uri_root, app_data.uri_root
147
- app_obj.set :app_name, app_data.app_obj.app_name.to_s
148
- app_obj.set :app_file, app_data.app_file unless ::File.exist?(app_obj.app_file)
149
- app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
150
- app_obj.set :public_folder, Padrino.root('public', app_data.uri_root) unless File.exist?(app_obj.public_folder)
151
- app_obj.set :static, File.exist?(app_obj.public_folder) if app_obj.nil?
104
+ app_obj.set :uri_root, uri_root
105
+ app_obj.set :app_name, app_obj.app_name.to_s
106
+ app_obj.set :root, app_data.app_root
107
+ app_obj.set :public_folder, Padrino.root('public', uri_root) unless public_folder_exists
108
+ app_obj.set :static, public_folder_exists
152
109
  app_obj.set :cascade, app_data.cascade
153
110
  else
154
- app_obj.uri_root = app_data.uri_root
155
- app_obj.public_folder = Padrino.root('public', app_data.uri_root) unless ::File.exist?(app_obj.public_folder)
111
+ app_obj.uri_root = uri_root
112
+ app_obj.public_folder = Padrino.root('public', uri_root) unless public_folder_exists
156
113
  end
157
114
  app_obj.setup_application! # Initializes the app here with above settings.
158
- router.map(:to => app_obj, :path => app_data.uri_root, :host => app_data.app_host)
115
+ router.map(:to => app_obj, :path => uri_root, :host => app_data.app_host)
159
116
  end
160
117
 
161
118
  ###
@@ -174,7 +131,7 @@ module Padrino
174
131
  def named_routes
175
132
  app_obj.routes.map { |route|
176
133
  route_name = route.name.to_s
177
- route_name =
134
+ route_name =
178
135
  if route.controller
179
136
  route_name.split(" ", 2).map{|name| ":#{name}" }.join(", ")
180
137
  else
@@ -231,8 +188,10 @@ module Padrino
231
188
  # Returns the determined location of the mounted application main file.
232
189
  #
233
190
  def locate_app_file
191
+ app_const = app_constant
192
+
234
193
  candidates = []
235
- candidates << app_constant.app_file if app_constant.respond_to?(:app_file) && File.exist?(app_constant.app_file.to_s)
194
+ candidates << app_const.app_file if app_const.respond_to?(:app_file)
236
195
  candidates << Padrino.first_caller if File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
237
196
  candidates << Padrino.mounted_root(name.downcase, "app.rb")
238
197
  simple_name = name.split("::").last.downcase
@@ -11,12 +11,15 @@ module Padrino
11
11
  @app = app
12
12
  @cooldown = cooldown
13
13
  @last = (Time.now - cooldown)
14
+ @mutex = Mutex.new
14
15
  end
15
16
 
16
17
  # Invoked in order to perform the reload as part of the request stack.
17
18
  def call(env)
18
19
  if @cooldown && Time.now > @last + @cooldown
19
- Thread.list.size > 1 ? Thread.exclusive { Padrino.reload! } : Padrino.reload!
20
+ @mutex.synchronize do
21
+ Padrino.reload!
22
+ end
20
23
  @last = Time.now
21
24
  end
22
25
  @app.call(env)
@@ -22,7 +22,7 @@ module Padrino
22
22
  file = remove(name)
23
23
  @old_entries ||= {}
24
24
  @old_entries[name] = {
25
- :constants => ObjectSpace.classes,
25
+ :constants => object_classes,
26
26
  :features => old_features = Set.new($LOADED_FEATURES.dup)
27
27
  }
28
28
  features = file && file[:features] || []
@@ -32,7 +32,7 @@ module Padrino
32
32
 
33
33
  def commit(name)
34
34
  entry = {
35
- :constants => ObjectSpace.new_classes(@old_entries[name][:constants]),
35
+ :constants => new_classes(@old_entries[name][:constants]),
36
36
  :features => Set.new($LOADED_FEATURES) - @old_entries[name][:features] - [name]
37
37
  }
38
38
  files[name] = entry
@@ -40,7 +40,7 @@ module Padrino
40
40
  end
41
41
 
42
42
  def rollback(name)
43
- new_constants = ObjectSpace.new_classes(@old_entries[name][:constants])
43
+ new_constants = new_classes(@old_entries[name][:constants])
44
44
  new_constants.each{ |klass| Reloader.remove_constant(klass) }
45
45
  @old_entries.delete(name)
46
46
  end
@@ -50,6 +50,34 @@ module Padrino
50
50
  def files
51
51
  @files ||= {}
52
52
  end
53
+
54
+ ##
55
+ # Returns all the classes in the object space.
56
+ #
57
+ def object_classes
58
+ klasses = Set.new
59
+
60
+ ObjectSpace.each_object(Class).each do |klass|
61
+ if block_given?
62
+ if filtered_class = yield(klass)
63
+ klasses << filtered_class
64
+ end
65
+ else
66
+ klasses << klass
67
+ end
68
+ end
69
+
70
+ klasses
71
+ end
72
+
73
+ ##
74
+ # Returns a list of object space classes that are not included in "snapshot".
75
+ #
76
+ def new_classes(snapshot)
77
+ object_classes do |klass|
78
+ snapshot.include?(klass) ? nil : klass
79
+ end
80
+ end
53
81
  end
54
82
  end
55
83
  end
@@ -73,7 +73,7 @@ module Padrino
73
73
  # We lock dependencies sets to prevent reloading of protected constants
74
74
  #
75
75
  def lock!
76
- klasses = ObjectSpace.classes do |klass|
76
+ klasses = Storage.send(:object_classes) do |klass|
77
77
  original_klass_name = klass._orig_klass_name
78
78
  original_klass_name.split('::').first if original_klass_name
79
79
  end
@@ -222,7 +222,9 @@ module Padrino
222
222
  #
223
223
  def files_for_rotation
224
224
  files = Set.new
225
- files += Dir.glob("#{Padrino.root}/{lib,models,shared}/**/*.rb")
225
+ Padrino.dependency_paths.each do |path|
226
+ files += Dir.glob(path)
227
+ end
226
228
  reloadable_apps.each do |app|
227
229
  files << app.app_file
228
230
  files += Dir.glob(app.app_obj.prerequisites)
@@ -6,7 +6,7 @@
6
6
  #
7
7
  module Padrino
8
8
  # The version constant for the current version of Padrino.
9
- VERSION = '0.12.8.1' unless defined?(Padrino::VERSION)
9
+ VERSION = '0.12.9' unless defined?(Padrino::VERSION)
10
10
 
11
11
  #
12
12
  # The current Padrino version.
data/lib/padrino-core.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'sinatra/base'
2
2
  require 'padrino-core/version'
3
3
  require 'padrino-support'
4
+ require 'padrino-core/configuration'
4
5
  require 'padrino-core/application'
5
6
 
6
7
  require 'padrino-core/caller'
@@ -25,6 +26,7 @@ module Padrino
25
26
  class ApplicationLoadError < RuntimeError # @private
26
27
  end
27
28
 
29
+ extend Configuration
28
30
  extend Loader
29
31
 
30
32
  class << self
data/padrino-core.gemspec CHANGED
@@ -24,13 +24,7 @@ Gem::Specification.new do |s|
24
24
  s.rdoc_options = ["--charset=UTF-8"]
25
25
 
26
26
  s.add_dependency("padrino-support", Padrino.version)
27
- if ENV["SINATRA_EDGE"]
28
- s.add_dependency("sinatra")
29
- else
30
- # remove this rack dependency after Sinatra > 1.4.5
31
- s.add_dependency("rack", "< 1.6.0")
32
- s.add_dependency("sinatra", "~> 1.4.2")
33
- end
27
+ s.add_dependency("sinatra", ">= 1.4.6")
34
28
  s.add_dependency("http_router", "~> 0.11.0")
35
29
  s.add_dependency("thor", "~> 0.18")
36
30
  s.add_dependency("activesupport", ">= 3.1")
@@ -0,0 +1,11 @@
1
+ PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
2
+
3
+ class CustomDependencies < Padrino::Application
4
+ set :reload, true
5
+ end
6
+
7
+ CustomDependencies.controllers do
8
+ get "/" do
9
+ "foo"
10
+ end
11
+ end
@@ -0,0 +1 @@
1
+ FakeLib = 1
@@ -0,0 +1,2 @@
1
+ class FakeRoot < Sinatra::Base
2
+ end
@@ -3,6 +3,10 @@ class RackApp
3
3
  def self.call(_)
4
4
  [200, {}, ["hello rack app"]]
5
5
  end
6
+
7
+ def self.prerequisites
8
+ super
9
+ end
6
10
  end
7
11
 
8
12
  RackApp2 = lambda{|_| [200, {}, ["hello rack app2"]] }
@@ -1,7 +1,6 @@
1
1
  PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
2
2
  # Remove this comment if you want do some like this: ruby RACK_ENV=test app.rb
3
3
  #
4
- # require 'rubygems'
5
4
  # require 'padrino-core'
6
5
  #
7
6
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
2
4
 
3
5
  class SystemDemo < Padrino::Application
data/test/helper.rb CHANGED
@@ -1,21 +1,18 @@
1
1
  ENV['RACK_ENV'] = 'test'
2
2
  PADRINO_ROOT = File.dirname(__FILE__) unless defined?(PADRINO_ROOT)
3
3
 
4
- require File.expand_path('../../../load_paths', __FILE__)
5
4
  require 'minitest/autorun'
6
5
  require 'minitest/pride'
7
6
  require 'i18n'
8
- require 'padrino-support'
9
- require 'padrino-core'
10
7
  require 'json'
11
8
  require 'builder'
12
9
  require 'rack/test'
13
- require 'rack'
14
10
  require 'yaml'
11
+ require 'padrino-core'
12
+ require 'tilt/haml'
15
13
 
16
- # Rubies < 1.9 don't handle hashes in the properly order so to prevent
17
- # this issue for now we remove extra values from mimetypes.
18
- Rack::Mime::MIME_TYPES.delete(".xsl") # In this way application/xml respond only to .xml
14
+ require 'ext/minitest-spec'
15
+ require 'ext/rack-test-methods'
19
16
 
20
17
  class MiniTest::Spec
21
18
  include Rack::Test::Methods
@@ -30,23 +27,4 @@ class MiniTest::Spec
30
27
  def app
31
28
  Rack::Lint.new(@app)
32
29
  end
33
-
34
- # Asserts that a file matches the pattern
35
- def assert_match_in_file(pattern, file)
36
- assert File.exist?(file), "File '#{file}' does not exist!"
37
- assert_match pattern, File.read(file)
38
- end
39
-
40
- # Delegate other missing methods to response.
41
- def method_missing(name, *args, &block)
42
- if response && response.respond_to?(name)
43
- response.send(name, *args, &block)
44
- else
45
- super(name, *args, &block)
46
- end
47
- rescue Rack::Test::Error # no response yet
48
- super(name, *args, &block)
49
- end
50
-
51
- alias :response :last_response
52
30
  end
@@ -148,6 +148,14 @@ describe "Application" do
148
148
  assert_equal 1, @app.errors.size
149
149
  assert_equal 'custom error', body
150
150
  end
151
+
152
+ it 'should raise NameError even if Kernel.require is extended' do
153
+ assert_raises NameError do
154
+ ConstTest = Class.new(Padrino::Application)
155
+ require 'active_support/dependencies'
156
+ ConstTest::UninitializedConstant
157
+ end
158
+ end
151
159
  end
152
160
 
153
161
  describe 'global prerequisites' do
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe "PadrinoConfiguration" do
4
+ it 'should be able to store values' do
5
+ Padrino.config.val1 = 12345
6
+ assert_equal 12345, Padrino.config.val1
7
+ end
8
+
9
+ it 'should be able to configure with block' do
10
+ Padrino.configure do |config|
11
+ config.val2 = 54321
12
+ end
13
+ assert_equal 54321, Padrino.config.val2
14
+ end
15
+
16
+ it 'should be able to configure with block' do
17
+ Padrino.configure :test do |config|
18
+ config.test1 = 54321
19
+ end
20
+ Padrino.configure :development do |config|
21
+ config.test1 = 12345
22
+ end
23
+ Padrino.configure :test, :development do |config|
24
+ config.both1 = 54321
25
+ end
26
+ assert_equal 54321, Padrino.config.test1
27
+ assert_equal 54321, Padrino.config.both1
28
+ end
29
+ end
data/test/test_core.rb CHANGED
@@ -77,5 +77,17 @@ describe "Core" do
77
77
  assert_equal @app.settings.zoo, :baz
78
78
  assert_equal @app.settings.moo, :bam
79
79
  end
80
+
81
+ it 'should return a friendly 500' do
82
+ mock_app do
83
+ enable :show_exceptions
84
+ get(:index){ raise StandardError }
85
+ end
86
+
87
+ get "/"
88
+ assert_equal 500, status
89
+ assert body.include?("StandardError")
90
+ assert body.include?("<code>show_exceptions</code> setting")
91
+ end
80
92
  end
81
93
  end
@@ -6,6 +6,7 @@ describe "Application" do
6
6
  describe 'CSRF protection' do
7
7
  describe "with CSRF protection on" do
8
8
  before do
9
+ @token = Rack::Protection::AuthenticityToken.random_token rescue "a_token"
9
10
  mock_app do
10
11
  enable :sessions
11
12
  enable :protect_from_csrf
@@ -19,25 +20,24 @@ describe "Application" do
19
20
  end
20
21
 
21
22
  it 'should allow requests with correct tokens' do
22
- post "/", {"authenticity_token" => "a"}, 'rack.session' => {:csrf => "a"}
23
+ post "/", {"authenticity_token" => @token}, 'rack.session' => {:csrf => @token}
23
24
  assert_equal 200, status
24
25
  end
25
26
 
26
27
  it 'should not allow requests with incorrect tokens' do
27
- post "/", {"authenticity_token" => "a"}, 'rack.session' => {:csrf => "b"}
28
+ post "/", {"authenticity_token" => "b"}, 'rack.session' => {:csrf => @token}
28
29
  assert_equal 403, status
29
30
  end
30
31
 
31
32
  it 'should allow requests with correct X-CSRF-TOKEN' do
32
- post "/", {}, 'rack.session' => {:csrf => "a"}, 'HTTP_X_CSRF_TOKEN' => "a"
33
+ post "/", {}, 'rack.session' => {:csrf => @token}, 'HTTP_X_CSRF_TOKEN' => @token
33
34
  assert_equal 200, status
34
35
  end
35
36
 
36
37
  it 'should not allow requests with incorrect X-CSRF-TOKEN' do
37
- post "/", {}, 'rack.session' => {:csrf => "a"}, 'HTTP_X_CSRF_TOKEN' => "b"
38
+ post "/", {}, 'rack.session' => {:csrf => @token}, 'HTTP_X_CSRF_TOKEN' => "b"
38
39
  assert_equal 403, status
39
40
  end
40
-
41
41
  end
42
42
 
43
43
  describe "without CSRF protection on" do
@@ -142,6 +142,7 @@ describe "Application" do
142
142
 
143
143
  describe "with custom protection options" do
144
144
  before do
145
+ @token = Rack::Protection::AuthenticityToken.random_token rescue "a_token"
145
146
  mock_app do
146
147
  enable :sessions
147
148
  set :protect_from_csrf, :authenticity_param => 'foobar', :message => 'sucker!'
@@ -150,7 +151,7 @@ describe "Application" do
150
151
  end
151
152
 
152
153
  it 'should allow configuring protection options' do
153
- post "/a", {"foobar" => "a"}, 'rack.session' => {:csrf => "a"}
154
+ post "/a", {"foobar" => @token}, 'rack.session' => {:csrf => @token}
154
155
  assert_equal 200, status
155
156
  end
156
157
 
data/test/test_logger.rb CHANGED
@@ -1,5 +1,7 @@
1
+ #coding:utf-8
1
2
  require File.expand_path(File.dirname(__FILE__) + '/helper')
2
3
  require 'logger'
4
+ require 'tempfile'
3
5
 
4
6
  describe "PadrinoLogger" do
5
7
  before do
@@ -36,6 +38,28 @@ describe "PadrinoLogger" do
36
38
  Padrino::Logger.setup!
37
39
  assert_equal my_stream, Padrino.logger.log
38
40
  end
41
+
42
+ it 'should use a custom file path' do
43
+ tempfile = Tempfile.new('app.txt')
44
+ path = tempfile.path
45
+ tempfile.unlink
46
+ Padrino::Logger::Config[:test][:stream] = :to_file
47
+ Padrino::Logger::Config[:test][:log_path] = path
48
+ Padrino::Logger.setup!
49
+ assert_file_exists path
50
+ File.unlink(path)
51
+ end
52
+
53
+ it 'should use a custom log directory' do
54
+ tmpdir = Dir.mktmpdir
55
+ Padrino::Logger::Config[:test][:stream] = :to_file
56
+ Padrino::Logger::Config[:test][:log_path] = tmpdir
57
+ Padrino::Logger.setup!
58
+ log_path = File.join(tmpdir, 'test.log')
59
+ assert_file_exists log_path
60
+ File.unlink(log_path)
61
+ Dir.rmdir(tmpdir)
62
+ end
39
63
  end
40
64
 
41
65
  it 'should log something' do
@@ -58,6 +82,30 @@ describe "PadrinoLogger" do
58
82
  assert_match /log via alias/, @log.string
59
83
  end
60
84
 
85
+ it 'should not blow up on mixed or broken encodings' do
86
+ setup_logger(:log_level => :error, :auto_flush => false)
87
+ binary_data = "\xD0".force_encoding('BINARY')
88
+ utf8_data = 'фыв'
89
+ @logger.error binary_data
90
+ @logger.error utf8_data
91
+ @logger.flush
92
+ assert @log.string.include?(utf8_data)
93
+ assert @log.string.force_encoding('BINARY').include?(binary_data)
94
+ end
95
+
96
+ it 'should sanitize mixed or broken encodings if said so' do
97
+ encoding = 'windows-1251'
98
+ setup_logger(:log_level => :error, :auto_flush => false, :sanitize_encoding => encoding)
99
+ @log.string.encode! encoding
100
+ binary_data = "\xD0".force_encoding('BINARY')
101
+ utf8_data = 'фыв'
102
+ @logger.error binary_data
103
+ @logger.error utf8_data
104
+ @logger.flush
105
+ assert @log.string.force_encoding(encoding).include?("?\n".encode(encoding))
106
+ assert @log.string.force_encoding(encoding).include?(utf8_data.encode(encoding))
107
+ end
108
+
61
109
  it 'should log an application' do
62
110
  mock_app do
63
111
  enable :logging
@@ -248,3 +296,48 @@ describe "options :colorize_logging" do
248
296
  end
249
297
  end
250
298
  end
299
+
300
+ describe "options :source_location" do
301
+ before do
302
+ Padrino::Logger::Config[:test][:source_location] = true
303
+ Padrino::Logger.setup!
304
+ end
305
+
306
+ def stub_root(base_path = File.expand_path("."), &block)
307
+ callable = proc{ |*args| File.join(base_path, *args) }
308
+ Padrino.stub(:root, callable, &block)
309
+ end
310
+
311
+ it 'should output source_location if :source_location is set to true' do
312
+ stub_root { Padrino.logger.debug("hello world") }
313
+ assert_match /\[test\/test_logger\.rb:#{__LINE__-1}\] hello world/, Padrino.logger.log.string
314
+ end
315
+
316
+ it 'should output source_location if file path is relative' do
317
+ stub_message = "test/test_logger.rb:269:in `test'"
318
+ Padrino::Logger.logger.stub(:caller, [stub_message]){ stub_root { Padrino.logger.debug("hello relative path") }}
319
+ assert_match /\[test\/test_logger\.rb:269\] hello relative path/, Padrino.logger.log.string
320
+ end
321
+
322
+ it 'should not output source_location if :source_location is set to false' do
323
+ Padrino::Logger::Config[:test][:source_location] = false
324
+ Padrino::Logger.setup!
325
+ stub_root { Padrino.logger.debug("hello world") }
326
+ assert_match /hello world/, Padrino.logger.log.string
327
+ refute_match /\[.+?\] hello world/, Padrino.logger.log.string
328
+ end
329
+
330
+ it 'should not output source_location unless file path is not started with Padrino.root' do
331
+ stub_root("/unknown/path/") { Padrino.logger.debug("hello boy") }
332
+ assert_match /hello boy/, Padrino.logger.log.string
333
+ refute_match /\[.+?\] hello boy/, Padrino.logger.log.string
334
+ end
335
+
336
+ it 'should not output source_location if source file path is started with Padrino.root + vendor' do
337
+ base_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/')
338
+ stub_message = File.expand_path(File.dirname(__FILE__) + '/fixtures/vendor/logger.rb') + ":291:in `test'"
339
+ Padrino::Logger.logger.stub(:caller, [stub_message]) { stub_root(base_path) { Padrino.logger.debug("hello vendor") } }
340
+ assert_match /hello vendor/, Padrino.logger.log.string
341
+ refute_match /\[.+?\] hello vendor/, Padrino.logger.log.string
342
+ end
343
+ end
data/test/test_mounter.rb CHANGED
@@ -269,6 +269,7 @@ describe "Mounter" do
269
269
  assert_equal "hello sinatra app", res.body
270
270
  res = Rack::MockRequest.new(app).get("/sinatra_app/static.html")
271
271
  assert_equal "hello static file\n", res.body
272
+ assert_equal [], RackApp.prerequisites
272
273
  end
273
274
 
274
275
  it 'should support the Rack Application inside padrino project' do
@@ -285,5 +286,19 @@ describe "Mounter" do
285
286
  assert_equal "api app", res.body
286
287
  assert defined?(DemoProject::APILib)
287
288
  end
289
+
290
+ it "should not load dependency files if app's root isn't started with Padrino.root" do
291
+ Object.send(:remove_const, :FakeLib) if defined?(FakeLib)
292
+ path = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/demo_project/app')
293
+ fake_path = File.expand_path(File.dirname(__FILE__) + "/fixtures/apps/external_apps/fake_root")
294
+ require path
295
+ require fake_path
296
+ Padrino.mount("fake_root", :app_class => "FakeRoot").to('/fake_root')
297
+ Padrino.mount('main_app', :app_class => 'DemoProject::App').to('/')
298
+ Padrino.stub(:root, File.expand_path(File.dirname(__FILE__) + "/fixtures/apps/demo_project")) do
299
+ Padrino.application
300
+ end
301
+ assert !defined?(FakeLib)
302
+ end
288
303
  end
289
304
  end