tennpipes-base 3.6.6

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.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.rdoc +294 -0
  4. data/Rakefile +1 -0
  5. data/bin/tennpipes +8 -0
  6. data/lib/tennpipes-base.rb +196 -0
  7. data/lib/tennpipes-base/application.rb +175 -0
  8. data/lib/tennpipes-base/application/application_setup.rb +202 -0
  9. data/lib/tennpipes-base/application/authenticity_token.rb +25 -0
  10. data/lib/tennpipes-base/application/flash.rb +229 -0
  11. data/lib/tennpipes-base/application/params_protection.rb +129 -0
  12. data/lib/tennpipes-base/application/routing.rb +1002 -0
  13. data/lib/tennpipes-base/application/show_exceptions.rb +50 -0
  14. data/lib/tennpipes-base/caller.rb +53 -0
  15. data/lib/tennpipes-base/cli/adapter.rb +33 -0
  16. data/lib/tennpipes-base/cli/base.rb +105 -0
  17. data/lib/tennpipes-base/cli/console.rb +20 -0
  18. data/lib/tennpipes-base/cli/launcher.rb +103 -0
  19. data/lib/tennpipes-base/cli/rake.rb +50 -0
  20. data/lib/tennpipes-base/cli/rake_tasks.rb +72 -0
  21. data/lib/tennpipes-base/command.rb +38 -0
  22. data/lib/tennpipes-base/ext/sinatra.rb +29 -0
  23. data/lib/tennpipes-base/filter.rb +52 -0
  24. data/lib/tennpipes-base/images/404.png +0 -0
  25. data/lib/tennpipes-base/images/500.png +0 -0
  26. data/lib/tennpipes-base/loader.rb +202 -0
  27. data/lib/tennpipes-base/logger.rb +492 -0
  28. data/lib/tennpipes-base/module.rb +58 -0
  29. data/lib/tennpipes-base/mounter.rb +308 -0
  30. data/lib/tennpipes-base/path_router.rb +119 -0
  31. data/lib/tennpipes-base/path_router/compiler.rb +110 -0
  32. data/lib/tennpipes-base/path_router/error_handler.rb +8 -0
  33. data/lib/tennpipes-base/path_router/matcher.rb +123 -0
  34. data/lib/tennpipes-base/path_router/route.rb +169 -0
  35. data/lib/tennpipes-base/reloader.rb +309 -0
  36. data/lib/tennpipes-base/reloader/rack.rb +26 -0
  37. data/lib/tennpipes-base/reloader/storage.rb +55 -0
  38. data/lib/tennpipes-base/router.rb +98 -0
  39. data/lib/tennpipes-base/server.rb +119 -0
  40. data/lib/tennpipes-base/tasks.rb +21 -0
  41. data/lib/tennpipes-base/version.rb +20 -0
  42. data/lib/tennpipes-base/version.rb~ +20 -0
  43. data/test/fixtures/app_gem/Gemfile +4 -0
  44. data/test/fixtures/app_gem/app/app.rb +3 -0
  45. data/test/fixtures/app_gem/app_gem.gemspec +17 -0
  46. data/test/fixtures/app_gem/lib/app_gem.rb +7 -0
  47. data/test/fixtures/app_gem/lib/app_gem/version.rb +3 -0
  48. data/test/fixtures/apps/complex.rb +32 -0
  49. data/test/fixtures/apps/demo_app.rb +7 -0
  50. data/test/fixtures/apps/demo_demo.rb +7 -0
  51. data/test/fixtures/apps/demo_project/api/app.rb +7 -0
  52. data/test/fixtures/apps/demo_project/api/lib/api_lib.rb +3 -0
  53. data/test/fixtures/apps/demo_project/app.rb +7 -0
  54. data/test/fixtures/apps/external_apps/fake_lib.rb +1 -0
  55. data/test/fixtures/apps/external_apps/fake_root.rb +2 -0
  56. data/test/fixtures/apps/helpers/class_methods_helpers.rb +4 -0
  57. data/test/fixtures/apps/helpers/instance_methods_helpers.rb +4 -0
  58. data/test/fixtures/apps/helpers/support.rb +1 -0
  59. data/test/fixtures/apps/helpers/system_helpers.rb +8 -0
  60. data/test/fixtures/apps/kiq.rb +3 -0
  61. data/test/fixtures/apps/lib/myklass.rb +2 -0
  62. data/test/fixtures/apps/lib/myklass/mysubklass.rb +4 -0
  63. data/test/fixtures/apps/models/child.rb +2 -0
  64. data/test/fixtures/apps/models/parent.rb +5 -0
  65. data/test/fixtures/apps/mountable_apps/rack_apps.rb +15 -0
  66. data/test/fixtures/apps/mountable_apps/static.html +1 -0
  67. data/test/fixtures/apps/precompiled_app.rb +19 -0
  68. data/test/fixtures/apps/simple.rb +32 -0
  69. data/test/fixtures/apps/static.rb +10 -0
  70. data/test/fixtures/apps/system.rb +13 -0
  71. data/test/fixtures/apps/system_class_methods_demo.rb +7 -0
  72. data/test/fixtures/apps/system_instance_methods_demo.rb +7 -0
  73. data/test/fixtures/dependencies/a.rb +9 -0
  74. data/test/fixtures/dependencies/b.rb +4 -0
  75. data/test/fixtures/dependencies/c.rb +1 -0
  76. data/test/fixtures/dependencies/circular/e.rb +13 -0
  77. data/test/fixtures/dependencies/circular/f.rb +2 -0
  78. data/test/fixtures/dependencies/circular/g.rb +2 -0
  79. data/test/fixtures/dependencies/d.rb +4 -0
  80. data/test/fixtures/reloadable_apps/external/app/app.rb +6 -0
  81. data/test/fixtures/reloadable_apps/external/app/controllers/base.rb +6 -0
  82. data/test/fixtures/reloadable_apps/main/app.rb +10 -0
  83. data/test/helper.rb +30 -0
  84. data/test/test_application.rb +185 -0
  85. data/test/test_core.rb +93 -0
  86. data/test/test_csrf_protection.rb +208 -0
  87. data/test/test_dependencies.rb +57 -0
  88. data/test/test_filters.rb +389 -0
  89. data/test/test_flash.rb +168 -0
  90. data/test/test_locale.rb +21 -0
  91. data/test/test_logger.rb +295 -0
  92. data/test/test_mounter.rb +302 -0
  93. data/test/test_params_protection.rb +195 -0
  94. data/test/test_reloader_complex.rb +74 -0
  95. data/test/test_reloader_external.rb +21 -0
  96. data/test/test_reloader_simple.rb +101 -0
  97. data/test/test_reloader_system.rb +113 -0
  98. data/test/test_restful_routing.rb +33 -0
  99. data/test/test_router.rb +281 -0
  100. data/test/test_routing.rb +2328 -0
  101. metadata +301 -0
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/complex')
3
+
4
+ describe "ComplexReloader" do
5
+
6
+ describe 'for complex reload functionality' do
7
+ before do
8
+ Tennpipes.clear!
9
+ Tennpipes.mount("complex_1_demo").to("/complex_1_demo")
10
+ Tennpipes.mount("complex_2_demo").to("/complex_2_demo")
11
+ end
12
+
13
+ it 'should correctly instantiate Complex(1-2)Demo fixture' do
14
+ assert_equal ["/complex_1_demo", "/complex_2_demo"], Tennpipes.mounted_apps.map(&:uri_root)
15
+ assert_equal ["complex_1_demo", "complex_2_demo"], Tennpipes.mounted_apps.map(&:name)
16
+ assert Complex1Demo.reload?
17
+ assert Complex2Demo.reload?
18
+ assert_match %r{fixtures/apps/complex.rb}, Complex1Demo.app_file
19
+ assert_match %r{fixtures/apps/complex.rb}, Complex2Demo.app_file
20
+ end
21
+
22
+ it 'should correctly reload Complex(1-2)Demo fixture' do
23
+ assert_match %r{fixtures/apps/complex.rb}, Complex1Demo.app_file
24
+ @app = Tennpipes.application
25
+
26
+ get "/"
27
+ assert_equal 404, status
28
+
29
+ get "/complex_1_demo"
30
+ assert_equal "Given random #{LibDemo.give_me_a_random}", body
31
+
32
+ get "/complex_2_demo"
33
+ assert_equal 200, status
34
+
35
+ get "/complex_1_demo/old"
36
+ assert_equal 200, status
37
+
38
+ get "/complex_2_demo/old"
39
+ assert_equal 200, status
40
+
41
+ get "/complex_2_demo/var/destroy"
42
+ assert_equal '{}', body
43
+
44
+ new_phrase = "The magick number is: #{rand(2**255)}!"
45
+ buffer = File.read(Complex1Demo.app_file)
46
+ new_buffer = buffer.sub(/The magick number is: \d+!/, new_phrase)
47
+ new_buffer.sub!(/get\(:destroy\)/, 'get(:destroy, :with => :id)')
48
+ begin
49
+ File.open(Complex1Demo.app_file, "w") { |f| f.write(new_buffer) }
50
+ Time.stub(:now, Time.now + 2) { get "/complex_2_demo" }
51
+ assert_equal new_phrase, body
52
+
53
+ # Re-Check that we didn't forget any route
54
+ get "/complex_1_demo"
55
+ assert_equal "Given random #{LibDemo.give_me_a_random}", body
56
+
57
+ get "/complex_2_demo"
58
+ assert_equal 200, status
59
+
60
+ get "/complex_1_demo/old"
61
+ assert_equal 200, status
62
+
63
+ get "/complex_2_demo/old"
64
+ assert_equal 200, status
65
+
66
+ get "/complex_2_demo/var/destroy/variable"
67
+ assert_equal '{"id"=>"variable"}', body
68
+ ensure
69
+ # Now we need to prevent to commit a new changed file so we revert it
70
+ File.open(Complex1Demo.app_file, "w") { |f| f.write(buffer) }
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/reloadable_apps/main/app')
3
+
4
+ describe "ExternalReloader" do
5
+ describe "for external app" do
6
+ before do
7
+ Tennpipes.clear!
8
+ Tennpipes.mount("ReloadableApp::External").to("/reloadable/external")
9
+ Tennpipes.mount("ReloadableApp::Main").to("/reloadable")
10
+ Tennpipes.load!
11
+ end
12
+
13
+ it "should avoid reloading the file if its path is not started with Tennpipes.root" do
14
+ @app = Tennpipes.application
15
+ Tennpipes.stub(:root, File.expand_path(File.dirname(__FILE__) + '/fixtures/reloadable_apps/main')) do
16
+ get "/reloadable/external/base"
17
+ end
18
+ assert_equal "Hello External App", body
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,101 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/simple')
3
+
4
+ describe "SimpleReloader" do
5
+
6
+ describe 'for simple reset functionality' do
7
+
8
+ it 'should reset routes' do
9
+ mock_app do
10
+ (1..10).each do |i|
11
+ get("/#{i}") { "Foo #{i}" }
12
+ end
13
+ end
14
+ (1..10).each do |i|
15
+ get "/#{i}"
16
+ assert_equal "Foo #{i}", body
17
+ end
18
+ @app.reset_routes!
19
+ (1..10).each do |i|
20
+ get "/#{i}"
21
+ assert_equal 404, status
22
+ end
23
+ end
24
+
25
+ it 'should keep sinatra routes on development' do
26
+ mock_app do
27
+ set :environment, :development
28
+ get("/"){ "ok" }
29
+ end
30
+ assert_equal :development, @app.environment
31
+ get "/"
32
+ assert_equal 200, status
33
+ get "/__sinatra__/404.png"
34
+ assert_equal 200, status
35
+ assert_match /image\/png/, response["Content-Type"]
36
+ @app.reset_routes!
37
+ get "/"
38
+ assert_equal 404, status
39
+ get "/__sinatra__/404.png"
40
+ assert_equal 200, status
41
+ assert_match /image\/png/, response["Content-Type"]
42
+ end
43
+ end
44
+
45
+ describe 'for simple reload functionality' do
46
+ before do
47
+ Tennpipes.clear!
48
+ Tennpipes.mount("simple_demo").to("/")
49
+ Tennpipes.reload!
50
+ end
51
+
52
+ it 'should correctly instantiate SimpleDemo fixture' do
53
+ assert_equal ["simple_demo"], Tennpipes.mounted_apps.map(&:name)
54
+ assert SimpleDemo.reload?
55
+ assert_match %r{fixtures/apps/simple.rb}, SimpleDemo.app_file
56
+ end
57
+
58
+ it 'should correctly reload SimpleDemo fixture' do
59
+ @app = SimpleDemo
60
+ get "/"
61
+ assert ok?
62
+ new_phrase = "The magick number is: #{rand(2**255)}!"
63
+ buffer = File.read(SimpleDemo.app_file)
64
+ new_buffer = buffer.sub(/The magick number is: \d+!/, new_phrase)
65
+ begin
66
+ File.open(SimpleDemo.app_file, "w") { |f| f.write(new_buffer) }
67
+ Time.stub(:now, Time.now + 2) { get "/" }
68
+ assert_equal new_phrase, body
69
+ ensure
70
+ File.open(SimpleDemo.app_file, "w") { |f| f.write(buffer) }
71
+ Tennpipes.reload!
72
+ end
73
+ end
74
+
75
+ it 'should correctly reset SimpleDemo fixture' do
76
+ @app = SimpleDemo
77
+ get "/"
78
+ @app.reload!
79
+ get "/rand"
80
+ assert ok?
81
+ last_body = body
82
+ assert_equal 1, @app.filters[:before].size
83
+ assert_equal 1, @app.errors.size
84
+ assert_equal 2, @app.filters[:after].size # app + content-type + tennpipes-flash
85
+ assert_equal 0, @app.middleware.size
86
+ assert_equal 4, @app.routes.size # GET+HEAD of "/" + GET+HEAD of "/rand" = 4
87
+ assert_equal 4, @app.extensions.size # [Tennpipes::ApplicationSetup, Tennpipes::ParamsProtection, Tennpipes::Routing, Tennpipes::Flash]
88
+ assert_equal 0, @app.templates.size
89
+ @app.reload!
90
+ get "/rand"
91
+ refute_equal last_body, body
92
+ assert_equal 1, @app.filters[:before].size
93
+ assert_equal 1, @app.errors.size
94
+ assert_equal 2, @app.filters[:after].size
95
+ assert_equal 0, @app.middleware.size
96
+ assert_equal 4, @app.routes.size # GET+HEAD of "/" = 2
97
+ assert_equal 4, @app.extensions.size # [Tennpipes::ApplicationSetup, Tennpipes::ParamsProtection, Tennpipes::Routing, Tennpipes::Flash]
98
+ assert_equal 0, @app.templates.size
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,113 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/kiq')
3
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/system')
4
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/static')
5
+
6
+ describe "SystemReloader" do
7
+ describe 'for wierd and difficult reload events' do
8
+ before do
9
+ @app = SystemDemo
10
+ get '/'
11
+ end
12
+
13
+ it 'should reload system features if they were required only in helper' do
14
+ @app.reload!
15
+ get '/'
16
+ assert_equal 'Resolv', body
17
+ end
18
+
19
+ it 'should reload children on parent change' do
20
+ Tennpipes.mount(SystemDemo).to("/")
21
+ assert_equal Child.new.family, 'Danes'
22
+ parent_file = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/models/parent.rb')
23
+ new_class = <<-DOC
24
+ class Parent
25
+ def family
26
+ 'Dancy'
27
+ end
28
+ def shmamily
29
+ 'Shmancy'
30
+ end
31
+ end
32
+ DOC
33
+ begin
34
+ backup = File.read(parent_file)
35
+ Tennpipes::Reloader.reload!
36
+ assert_equal 'Danes', Parent.new.family
37
+ assert_equal 'Danes', Child.new.family
38
+ File.open(parent_file, "w") { |f| f.write(new_class) }
39
+ Tennpipes::Reloader.reload!
40
+ assert_equal 'Dancy', Parent.new.family
41
+ assert_equal 'Shmancy', Parent.new.shmamily
42
+ assert_equal 'Dancy', Child.new.family
43
+ assert_equal 'Shmancy', Child.new.shmamily
44
+ ensure
45
+ File.open(parent_file, "w") { |f| f.write(backup) }
46
+ end
47
+ end
48
+
49
+ it 'should not fail horribly on reload event with non-tennpipes apps' do
50
+ Tennpipes.mount("kiq").to("/")
51
+ Tennpipes.reload!
52
+ end
53
+
54
+ it 'should not reload apps with disabled reload' do
55
+ Tennpipes.mount(StaticDemo).to("/")
56
+ Tennpipes.reload!
57
+ end
58
+ end
59
+
60
+ describe 'reloading external constants' do
61
+ it 'should not touch external constants defining singleton methods' do
62
+ new_class = <<-DOC
63
+ class SingletonClassTest
64
+ def self.external_test
65
+ end
66
+ end
67
+ DOC
68
+ tmp_file = '/tmp/tennpipes_class_demo.rb'
69
+ begin
70
+ File.open(tmp_file, "w") { |f| f.write(new_class) }
71
+ Tennpipes.clear!
72
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/system_class_methods_demo.rb')
73
+ @app = SystemClassMethodsDemo
74
+ Tennpipes.mount(SystemClassMethodsDemo).to("/")
75
+ get '/'
76
+ assert defined?(SingletonClassTest), 'SingletonClassTest undefined'
77
+ assert_includes SingletonClassTest.singleton_methods, :external_test
78
+ FileUtils.touch File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/helpers/class_methods_helpers.rb')
79
+ Tennpipes.reload!
80
+ assert defined?(SingletonClassTest), 'SingletonClassTest undefined'
81
+ assert_includes SingletonClassTest.singleton_methods, :external_test
82
+ ensure
83
+ FileUtils.rm tmp_file
84
+ end
85
+ end
86
+
87
+ it 'should not touch external constants defining instance methods' do
88
+ new_class = <<-DOC
89
+ class InstanceTest
90
+ def instance_test
91
+ end
92
+ end
93
+ DOC
94
+ tmp_file = '/tmp/tennpipes_instance_demo.rb'
95
+ begin
96
+ File.open(tmp_file, "w") { |f| f.write(new_class) }
97
+ Tennpipes.clear!
98
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/system_instance_methods_demo.rb')
99
+ @app = SystemInstanceMethodsDemo
100
+ Tennpipes.mount(SystemInstanceMethodsDemo).to("/")
101
+ get '/'
102
+ assert defined?(InstanceTest), 'InstanceTest undefined'
103
+ assert_includes InstanceTest.new.methods, :instance_test
104
+ FileUtils.touch File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/helpers/instance_methods_helpers.rb')
105
+ Tennpipes.reload!
106
+ assert defined?(InstanceTest), 'InstanceTest undefined'
107
+ assert_includes InstanceTest.new.methods, :instance_test
108
+ ensure
109
+ FileUtils.rm tmp_file
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe "Routing" do
4
+ it 'should perform restul routing' do
5
+ mock_app do
6
+ controller :parent => :parents do
7
+ get :index, :with => :asset_id do
8
+ "#{url_for(:index, params[:parent_id], :asset_id => params[:asset_id])} get"
9
+ end
10
+
11
+ put :index, :with => :asset_id do
12
+ "#{url_for(:index, params[:parent_id], :asset_id => params[:asset_id])} put"
13
+ end
14
+
15
+ post :index, :with => :asset_id do
16
+ "#{url_for(:index, :parent_id => params[:parent_id], :asset_id => params[:asset_id])} post"
17
+ end
18
+
19
+ delete :index, :with => :asset_id do
20
+ "#{url_for(:index, params[:parent_id], :asset_id => params[:asset_id])} delete"
21
+ end
22
+ end
23
+ end
24
+ get "/parents/1/hi"
25
+ assert_equal "/parents/1/hi get", body
26
+ put "/parents/1/hi"
27
+ assert_equal "/parents/1/hi put", body
28
+ post "/parents/1/hi"
29
+ assert_equal "/parents/1/hi post", body
30
+ delete "/parents/1/hi"
31
+ assert_equal "/parents/1/hi delete", body
32
+ end
33
+ end
@@ -0,0 +1,281 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/simple')
3
+
4
+ describe "Router" do
5
+
6
+ def setup
7
+ Tennpipes.clear!
8
+ end
9
+
10
+ it 'should dispatch paths correctly' do
11
+ app = lambda { |env|
12
+ [200, {
13
+ 'X-ScriptName' => env['SCRIPT_NAME'],
14
+ 'X-PathInfo' => env['PATH_INFO'],
15
+ 'Content-Type' => 'text/plain'
16
+ }, [""]]
17
+ }
18
+ map = Tennpipes::Router.new(
19
+ { :path => '/bar', :to => app },
20
+ { :path => '/foo/bar', :to => app },
21
+ { :path => '/foo', :to => app }
22
+ )
23
+
24
+ res = Rack::MockRequest.new(map).get("/")
25
+ assert res.not_found?
26
+
27
+ res = Rack::MockRequest.new(map).get("/qux")
28
+ assert res.not_found?
29
+
30
+ res = Rack::MockRequest.new(map).get("/foo")
31
+ assert res.ok?
32
+ assert_equal "/foo", res["X-ScriptName"]
33
+ assert_equal "/", res["X-PathInfo"]
34
+
35
+ res = Rack::MockRequest.new(map).get("/foo/")
36
+ assert res.ok?
37
+ assert_equal "/foo", res["X-ScriptName"]
38
+ assert_equal "/", res["X-PathInfo"]
39
+
40
+ res = Rack::MockRequest.new(map).get("/foo/bar")
41
+ assert res.ok?
42
+ assert_equal "/foo/bar", res["X-ScriptName"]
43
+ assert_equal "/", res["X-PathInfo"]
44
+
45
+ res = Rack::MockRequest.new(map).get("/foo/bar/")
46
+ assert res.ok?
47
+ assert_equal "/foo/bar", res["X-ScriptName"]
48
+ assert_equal "/", res["X-PathInfo"]
49
+
50
+ res = Rack::MockRequest.new(map).get("/foo///bar//quux")
51
+ assert_equal 200, res.status
52
+ assert res.ok?
53
+ assert_equal "/foo/bar", res["X-ScriptName"]
54
+ assert_equal "//quux", res["X-PathInfo"]
55
+
56
+ res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
57
+ assert res.ok?
58
+ assert_equal "/bleh/foo", res["X-ScriptName"]
59
+ assert_equal "/quux", res["X-PathInfo"]
60
+
61
+ res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org')
62
+ assert res.ok?
63
+ assert_equal "/bar", res["X-ScriptName"]
64
+ assert_equal "/", res["X-PathInfo"]
65
+
66
+ res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org')
67
+ assert res.ok?
68
+ assert_equal "/bar", res["X-ScriptName"]
69
+ assert_equal "/", res["X-PathInfo"]
70
+ end
71
+
72
+ it 'should dispatch requests to cascade mounted apps' do
73
+ app = lambda { |env|
74
+ scary = !!env['PATH_INFO'].match(/scary/)
75
+ [scary ? 404 : 200, {
76
+ 'X-ScriptName' => env['SCRIPT_NAME'],
77
+ 'X-PathInfo' => env['PATH_INFO'],
78
+ 'Content-Type' => 'text/plain'
79
+ }, [""]]
80
+ }
81
+ api = lambda { |env|
82
+ spooky = !!env['QUERY_STRING'].match(/spooky/)
83
+ [spooky ? 200 : 404, {
84
+ 'X-API' => spooky,
85
+ 'X-ScriptName' => env['SCRIPT_NAME'],
86
+ 'X-PathInfo' => env['PATH_INFO'],
87
+ 'Content-Type' => 'application/json'
88
+ }, [""]]
89
+ }
90
+ map = Tennpipes::Router.new(
91
+ { :path => '/bar', :to => api },
92
+ { :path => '/bar', :to => app }
93
+ )
94
+
95
+ res = Rack::MockRequest.new(map).get("/werewolf")
96
+ assert_equal 404, res.status
97
+ assert_equal nil, res["X-API"]
98
+ assert_equal nil, res["X-ScriptName"]
99
+ assert_equal nil, res["X-PathInfo"]
100
+
101
+ res = Rack::MockRequest.new(map).get("/bar/mitzvah")
102
+ assert res.ok?
103
+ assert_equal nil, res["X-API"]
104
+ assert_equal 'text/plain', res["Content-Type"]
105
+ assert_equal "/bar", res["X-ScriptName"]
106
+ assert_equal "/mitzvah", res["X-PathInfo"]
107
+
108
+ res = Rack::MockRequest.new(map).get("/bar?spooky")
109
+ assert res.ok?
110
+ assert_equal true, res["X-API"]
111
+ assert_equal 'application/json', res["Content-Type"]
112
+ assert_equal "/bar", res["X-ScriptName"]
113
+ assert_equal "/", res["X-PathInfo"]
114
+
115
+ res = Rack::MockRequest.new(map).get("/bar/scary")
116
+ assert_equal 404, res.status
117
+ assert_equal nil, res["X-API"]
118
+ assert_equal 'text/plain', res["Content-Type"]
119
+ assert_equal "/bar", res["X-ScriptName"]
120
+ assert_equal "/scary", res["X-PathInfo"]
121
+ end
122
+
123
+ it 'should dispatch requests to cascade mounted apps and not cascade ok statuses' do
124
+
125
+ api = mock_app do
126
+ get 'scary' do
127
+ "1"
128
+ end
129
+ set :cascade, true
130
+ end
131
+
132
+ app = mock_app do
133
+ get 'scary' do
134
+ "2"
135
+ end
136
+ set :cascade, false
137
+ end
138
+
139
+ app2 = mock_app do
140
+ get 'terrifying' do
141
+ ""
142
+ end
143
+ end
144
+
145
+ map = Tennpipes::Router.new(
146
+ { :path => '/bar', :to => api },
147
+ { :path => '/bar', :to => app },
148
+ { :path => '/bar', :to => app2 }
149
+ )
150
+
151
+ res = Rack::MockRequest.new(map).get("/bar/scary")
152
+ assert res.ok?
153
+ #asserting that on ok we're good to go
154
+ assert_equal "1", res.body
155
+
156
+ res = Rack::MockRequest.new(map).get("/bar/terrifying")
157
+ assert !res.ok?
158
+
159
+ end
160
+
161
+ it 'should dispatch requests to cascade mounted apps until it sees a cascade == false or []g' do
162
+ app = mock_app do
163
+ get 'scary' do
164
+ ""
165
+ end
166
+ set :cascade, []
167
+ end
168
+
169
+ app2 = mock_app do
170
+ get 'terrifying' do
171
+ ""
172
+ end
173
+ end
174
+
175
+ map = Tennpipes::Router.new(
176
+ { :path => '/bar', :to => app },
177
+ { :path => '/bar', :to => app2 }
178
+ )
179
+
180
+ request_case = lambda {
181
+ Rack::MockRequest.new(map).get("/bar/terrifying")
182
+ }
183
+
184
+ app.cascade = false
185
+ assert !request_case.call.ok?
186
+
187
+ app.cascade = true
188
+ assert request_case.call.ok?
189
+ end
190
+
191
+ it 'should dispatches hosts correctly' do
192
+ map = Tennpipes::Router.new(
193
+ { :host => "foo.org", :to => lambda { |env|
194
+ [200,
195
+ { "Content-Type" => "text/plain",
196
+ "X-Position" => "foo.org",
197
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
198
+ }, [""]]}},
199
+ { :host => "subdomain.foo.org", :to => lambda { |env|
200
+ [200,
201
+ { "Content-Type" => "text/plain",
202
+ "X-Position" => "subdomain.foo.org",
203
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
204
+ }, [""]]}},
205
+ { :host => /.*\.bar.org/, :to => lambda { |env|
206
+ [200,
207
+ { "Content-Type" => "text/plain",
208
+ "X-Position" => "bar.org",
209
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
210
+ }, [""]]}}
211
+ )
212
+
213
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org")
214
+ assert res.not_found?
215
+
216
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "at.bar.org")
217
+ assert res.ok?
218
+ assert_equal "bar.org", res["X-Position"]
219
+
220
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org")
221
+ assert res.ok?
222
+ assert_equal "foo.org", res["X-Position"]
223
+
224
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org")
225
+ assert res.ok?
226
+ assert_equal "subdomain.foo.org", res["X-Position"]
227
+ end
228
+
229
+ it 'should works with tennpipes core applications' do
230
+ Tennpipes.mount("simple_demo").host("tennpipes.org")
231
+ assert_equal ["simple_demo"], Tennpipes.mounted_apps.map(&:name)
232
+ assert_equal ["tennpipes.org"], Tennpipes.mounted_apps.map(&:app_host)
233
+
234
+ res = Rack::MockRequest.new(Tennpipes.application).get("/")
235
+ assert res.not_found?
236
+
237
+ res = Rack::MockRequest.new(Tennpipes.application).get("/", "HTTP_HOST" => "bar.org")
238
+ assert res.not_found?
239
+
240
+ res = Rack::MockRequest.new(Tennpipes.application).get("/", "HTTP_HOST" => "tennpipes.org")
241
+ assert res.ok?
242
+ end
243
+
244
+ it 'should works with tennpipes applications' do
245
+ Tennpipes.mount("simple_demo").to("/foo").host(/.*\.tennpipes.org/)
246
+
247
+ res = Rack::MockRequest.new(Tennpipes.application).get("/")
248
+ assert res.not_found?
249
+
250
+ res = Rack::MockRequest.new(Tennpipes.application).get("/", "HTTP_HOST" => "bar.org")
251
+ assert res.not_found?
252
+
253
+ res = Rack::MockRequest.new(Tennpipes.application).get("/", "HTTP_HOST" => "tennpipes.org")
254
+ assert res.not_found?
255
+
256
+ res = Rack::MockRequest.new(Tennpipes.application).get("/none", "HTTP_HOST" => "foo.tennpipes.org")
257
+ assert res.not_found?
258
+
259
+ res = Rack::MockRequest.new(Tennpipes.application).get("/foo", "HTTP_HOST" => "bar.tennpipes.org")
260
+ assert res.ok?
261
+
262
+ res = Rack::MockRequest.new(Tennpipes.application).get("/foo/", "HTTP_HOST" => "bar.tennpipes.org")
263
+ assert res.ok?
264
+ end
265
+
266
+ it 'should keep the same environment object' do
267
+ app = lambda { |env|
268
+ env['path'] = env['PATH_INFO']
269
+ [200, {'Content-Type' => 'text/plain'}, [""]]
270
+ }
271
+ map = Tennpipes::Router.new(
272
+ { :path => '/bar', :to => app },
273
+ { :path => '/foo/bar', :to => app },
274
+ { :path => '/foo', :to => app }
275
+ )
276
+
277
+ env = Rack::MockRequest.env_for("/bar/foo")
278
+ map.call(env)
279
+ assert_equal "/foo", env["path"]
280
+ end
281
+ end