gin 0.0.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,15 @@
1
+
2
+ ##
3
+ # App made for testing
4
+
5
+ class AppFoo < Gin::App
6
+
7
+ errors ErrorController
8
+
9
+ mount FooController, "/foo" do
10
+ get :index, "/"
11
+ post :create, "/"
12
+ end
13
+
14
+ mount BlahController
15
+ end
@@ -0,0 +1,16 @@
1
+ class AppController < Gin::Controller
2
+
3
+ error 401 do
4
+ # handle error here
5
+ end
6
+
7
+
8
+ error /[45]\d\d/ do
9
+ # handle error here
10
+ end
11
+
12
+
13
+ filter :logged_in, 401 do
14
+ # Make sure we're logged in
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ class FooController < AppController
2
+
3
+ end
@@ -0,0 +1,7 @@
1
+ default:
2
+ host: backend.example.com
3
+ connections: 5
4
+
5
+ development:
6
+ host: dev.backend.example.com
7
+ connections: 1
@@ -0,0 +1,10 @@
1
+ default: &default
2
+ host: example.com
3
+ connections: 5
4
+ prefix: my_app
5
+
6
+ development:
7
+ host: localhost
8
+ connections: 1
9
+
10
+ production: *default
File without changes
@@ -0,0 +1,592 @@
1
+ require "test/test_helper"
2
+ require "stringio"
3
+
4
+ class FooController < Gin::Controller;
5
+ def index; "FOO"; end
6
+ def create; end
7
+ def error; raise "Something bad happened"; end
8
+ end
9
+
10
+ class BadErrDelegate < Gin::Controller
11
+ error{ raise "Bad error handler, bad!" }
12
+ end
13
+
14
+ class ErrDelegate < Gin::Controller
15
+ error{|err| body err.message }
16
+ end
17
+
18
+
19
+ class FooApp < Gin::App
20
+ mount FooController do
21
+ get :index, "/"
22
+ post :create, "/"
23
+ get :error, "/error"
24
+ end
25
+
26
+ def reloaded?
27
+ @reloaded ||= false
28
+ end
29
+
30
+ def reload!
31
+ @reloaded = true
32
+ end
33
+ end
34
+
35
+ class MissingRouteApp < Gin::App
36
+ mount FooController do
37
+ get :index, "/"
38
+ end
39
+ end
40
+
41
+ class ExtraRouteApp < Gin::App
42
+ mount FooController do
43
+ get :index, "/"
44
+ post :create, "/"
45
+ post :delete, "/delete"
46
+ end
47
+ end
48
+
49
+ class FooMiddleware
50
+ @@called = false
51
+ attr_reader :app, :args
52
+ def initialize app, *args
53
+ @app = app
54
+ @args = args
55
+ @@called = false
56
+ end
57
+
58
+ def self.reset!
59
+ @@called = false
60
+ end
61
+
62
+ def self.called?
63
+ @@called
64
+ end
65
+
66
+ def call env
67
+ @@called = true
68
+ @app.call env
69
+ end
70
+ end
71
+
72
+
73
+ class AppTest < Test::Unit::TestCase
74
+ class NamespacedApp < Gin::App; end
75
+
76
+ def setup
77
+ FooApp.instance_variable_set("@environment", nil)
78
+ FooApp.instance_variable_set("@asset_host", nil)
79
+ FooApp.instance_variable_set("@middleware", nil)
80
+ FooApp.instance_variable_set("@instance", nil)
81
+ FooApp.instance_variable_set("@config", nil)
82
+ FooApp.instance_variable_set("@config_dir", nil)
83
+ FooApp.instance_variable_set("@error_delegate", nil)
84
+ FooApp.instance_variable_set("@public_dir", nil)
85
+ FooApp.instance_variable_set("@session", nil)
86
+ FooApp.instance_variable_set("@protection", nil)
87
+ FooApp.instance_variable_set("@autoreload", nil)
88
+
89
+ @error_io = StringIO.new
90
+ @app = FooApp.new Logger.new(@error_io)
91
+ @rapp = FooApp.new lambda{|env| [200,{'Content-Type'=>'text/html'},["HI"]]}
92
+ end
93
+
94
+
95
+ def teardown
96
+ ENV.delete 'RACK_ENV'
97
+ end
98
+
99
+
100
+ def test_class_proxies
101
+ proxies = [:protection, :sessions, :session_secret, :middleware,
102
+ :error_delegate, :router, :root_dir, :public_dir, :load_config, :config,
103
+ :config_dir, :environment, :development?, :test?, :staging?, :production?,
104
+ :mime_type, :asset_host_for, :asset_host, :asset_version]
105
+
106
+ proxies.each do |name|
107
+ assert FooApp.respond_to?(name), "Gin::App should respond to #{name}"
108
+ assert @app.respond_to?(name), "Gin::App instance should respond to #{name}"
109
+ end
110
+ end
111
+
112
+
113
+ def test_class_call
114
+ assert_nil FooApp.instance_variable_get("@instance")
115
+
116
+ env = {'rack.input' => "", 'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'}
117
+ resp = FooApp.call env
118
+ assert_equal 200, resp[0]
119
+ assert_equal "3", resp[1]['Content-Length']
120
+ assert_equal ["FOO"], resp[2]
121
+
122
+ assert FooApp === FooApp.instance_variable_get("@instance")
123
+ app = FooApp.instance_variable_get("@instance")
124
+
125
+ FooApp.call env
126
+ assert_equal app, FooApp.instance_variable_get("@instance")
127
+ end
128
+
129
+
130
+ def test_namespace
131
+ assert_nil FooApp.namespace
132
+ assert_equal self.class, NamespacedApp.namespace
133
+ end
134
+
135
+
136
+ def test_protection
137
+ assert_equal true, FooApp.protection
138
+
139
+ FooApp.protection(test: "thing")
140
+ assert_equal({test:"thing"}, FooApp.protection)
141
+
142
+ FooApp.protection false
143
+ assert_equal false, FooApp.protection
144
+ end
145
+
146
+
147
+ def test_autoreload
148
+ FooApp.environment "production"
149
+ assert_equal false, FooApp.autoreload
150
+ assert_equal false, @app.autoreload
151
+
152
+ FooApp.autoreload true
153
+ assert_equal true, FooApp.autoreload
154
+ assert_equal true, @app.autoreload
155
+
156
+ FooApp.autoreload false
157
+ assert_equal false, FooApp.autoreload
158
+ assert_equal false, @app.autoreload
159
+ end
160
+
161
+
162
+ def test_autoreload_dev
163
+ FooApp.environment "development"
164
+ assert_equal true, FooApp.autoreload
165
+ assert_equal true, @app.autoreload
166
+
167
+ FooApp.autoreload false
168
+ assert_equal false, FooApp.autoreload
169
+ assert_equal false, @app.autoreload
170
+ end
171
+
172
+
173
+ def test_sessions
174
+ assert_equal true, FooApp.sessions
175
+
176
+ FooApp.sessions(test: "thing")
177
+ assert_equal({test:"thing"}, FooApp.sessions)
178
+
179
+ FooApp.sessions false
180
+ assert_equal false, FooApp.sessions
181
+ end
182
+
183
+
184
+ def test_session_secret
185
+ assert_equal 64, FooApp.session_secret.length
186
+ FooApp.session_secret "this is my secret!"
187
+ assert_equal "this is my secret!", FooApp.session_secret
188
+ end
189
+
190
+
191
+ def test_source_class
192
+ old_name = FooApp.instance_variable_get("@source_class")
193
+ assert_equal FooApp, FooApp.source_class
194
+
195
+ FooApp.instance_variable_set("@source_class", "MissingRouteApp")
196
+ assert_equal MissingRouteApp, FooApp.source_class
197
+
198
+ ensure
199
+ FooApp.instance_variable_set("@source_class", old_name)
200
+ end
201
+
202
+
203
+ def test_config_dir
204
+ assert_equal File.join(FooApp.root_dir, "config"), FooApp.config_dir
205
+
206
+ FooApp.config_dir "/foo/blah"
207
+ assert_equal "/foo/blah", FooApp.config_dir
208
+ end
209
+
210
+
211
+ def test_config
212
+ assert Gin::Config === FooApp.config
213
+ assert FooApp.config.instance_variable_get("@data").empty?
214
+ end
215
+
216
+
217
+ def test_config_with_dir
218
+ FooApp.config_dir "./test/mock_config"
219
+ assert_equal 1, FooApp.config.backend['connections']
220
+ end
221
+
222
+
223
+ def test_load_config
224
+ FooApp.config
225
+ FooApp.config_dir "./test/mock_config"
226
+ assert_raises(NoMethodError){ FooApp.config.backend }
227
+
228
+ FooApp.load_config
229
+ assert FooApp.config.backend
230
+ end
231
+
232
+
233
+ def test_error_delegate
234
+ assert_equal Gin::Controller, FooApp.error_delegate
235
+ FooApp.error_delegate FooController
236
+ assert_equal FooController, FooApp.error_delegate
237
+ end
238
+
239
+
240
+ def test_use_middleware
241
+ FooApp.use FooMiddleware, :foo, :bar
242
+ assert_equal [FooMiddleware, :foo, :bar], FooApp.middleware[0]
243
+ assert !FooMiddleware.called?
244
+
245
+ myapp = FooApp.new
246
+ myapp.call({'rack.input' => "", 'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'})
247
+ assert FooMiddleware.called?
248
+
249
+ FooMiddleware.reset!
250
+ myapp.call!({'rack.input' => "", 'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'})
251
+ assert !FooMiddleware.called?
252
+ end
253
+
254
+
255
+ def test_call_reload
256
+ FooApp.autoreload true
257
+ myapp = FooApp.new
258
+
259
+ assert !myapp.reloaded?
260
+ myapp.call 'rack.input' => "", 'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'
261
+
262
+ assert myapp.reloaded?
263
+ end
264
+
265
+
266
+ def test_call_static
267
+ resp = @app.call 'rack.input' => "",
268
+ 'PATH_INFO' => '/gin.css',
269
+ 'REQUEST_METHOD' => 'GET'
270
+
271
+ assert_equal 200, resp[0]
272
+ assert_equal File.read(@app.asset("gin.css")), resp[2].read
273
+ end
274
+
275
+
276
+ def test_call!
277
+ resp = @app.call! 'rack.input' => "",
278
+ 'PATH_INFO' => '/foo',
279
+ 'REQUEST_METHOD' => 'GET'
280
+ assert_equal 200, resp[0]
281
+ assert_equal "3", resp[1]['Content-Length']
282
+ assert_equal 'text/html;charset=UTF-8', resp[1]['Content-Type']
283
+ assert_equal ["FOO"], resp[2]
284
+ end
285
+
286
+
287
+ def test_dispatch
288
+ FooApp.environment 'test'
289
+ env = {'rack.input' => "", 'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'}
290
+
291
+ resp = @app.dispatch env, FooController, :index
292
+ assert_equal 200, resp[0]
293
+ assert_equal "3", resp[1]['Content-Length']
294
+ assert_equal 'text/html;charset=UTF-8', resp[1]['Content-Type']
295
+ assert_equal ["FOO"], resp[2]
296
+ end
297
+
298
+
299
+ def test_dispatch_not_found
300
+ FooApp.environment 'test'
301
+ env = {'rack.input' => "", 'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'}
302
+
303
+ resp = @app.dispatch env, FooController, :bad
304
+ assert_equal 404, resp[0]
305
+ assert_equal "288", resp[1]['Content-Length']
306
+ assert_equal 'text/html;charset=UTF-8', resp[1]['Content-Type']
307
+ assert_equal @app.asset("404.html"), resp[2].path
308
+ end
309
+
310
+
311
+ def test_dispatch_no_handler
312
+ FooApp.environment 'test'
313
+ env = {'rack.input' => "", 'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'}
314
+
315
+ resp = @app.dispatch env, FooController, nil
316
+ assert_equal 404, resp[0]
317
+ assert_equal "288", resp[1]['Content-Length']
318
+ assert_equal 'text/html;charset=UTF-8', resp[1]['Content-Type']
319
+ assert_equal @app.asset("404.html"), resp[2].path
320
+
321
+ msg = "ERROR -- : Gin::NotFound: No route exists for: GET /foo"
322
+ @error_io.rewind
323
+ assert @error_io.read.include?(msg)
324
+ end
325
+
326
+
327
+ def test_dispatch_rack_app
328
+ env = {'rack.input' => "", 'PATH_INFO' => '/bad', 'REQUEST_METHOD' => 'GET'}
329
+ expected = [200, {'Content-Length'=>"5"}, "AHOY!"]
330
+ myapp = lambda{|env| expected }
331
+ @app = FooApp.new myapp
332
+
333
+ resp = @app.dispatch env, nil, nil
334
+ assert_equal expected, resp
335
+ end
336
+
337
+
338
+ def test_dispatch_error
339
+ FooApp.environment 'test'
340
+ env = {'rack.input' => "", 'PATH_INFO' => '/bad', 'REQUEST_METHOD' => 'GET'}
341
+ resp = @app.dispatch env, FooController, :error
342
+
343
+ assert_equal 500, resp[0]
344
+ assert_equal @app.asset("500.html"), resp[2].path
345
+ @error_io.rewind
346
+ assert @error_io.read.empty?
347
+ end
348
+
349
+
350
+ def test_handle_error
351
+ FooApp.error_delegate ErrDelegate
352
+ env = {'rack.input' => "", 'PATH_INFO' => '/bad', 'REQUEST_METHOD' => 'GET'}
353
+ err = ArgumentError.new("Unexpected Argument")
354
+
355
+ resp = @app.handle_error err, env
356
+
357
+ assert_equal 500, resp[0]
358
+ assert_equal ["Unexpected Argument"], resp[2]
359
+ assert_equal({"Content-Type"=>"text/html;charset=UTF-8", "Content-Length"=>"19"}, resp[1])
360
+
361
+ assert_equal err, env['gin.errors'].first
362
+ end
363
+
364
+
365
+ def test_handle_error_no_delegate
366
+ FooApp.environment "production"
367
+ env = {'rack.input' => "", 'PATH_INFO' => '/bad', 'REQUEST_METHOD' => 'GET'}
368
+ resp = @app.handle_error ArgumentError.new("Unexpected Argument"), env
369
+
370
+ assert_equal 500, resp[0]
371
+ assert_equal File.read(@app.asset("500.html")), resp[2].read
372
+ assert_equal({"Content-Type"=>"text/html;charset=UTF-8", "Content-Length"=>"348"}, resp[1])
373
+ end
374
+
375
+
376
+ def test_handle_error_bad_delegate
377
+ FooApp.environment "production"
378
+ FooApp.error_delegate BadErrDelegate
379
+
380
+ env = {'rack.input' => "", 'PATH_INFO' => '/bad', 'REQUEST_METHOD' => 'GET'}
381
+ err = ArgumentError.new("Unexpected Argument")
382
+
383
+ resp = @app.handle_error ArgumentError.new("Unexpected Argument"), env
384
+ assert_equal 500, resp[0]
385
+ assert_equal File.read(@app.asset("500.html")), resp[2].read
386
+ assert_equal({"Content-Type"=>"text/html;charset=UTF-8", "Content-Length"=>"348"}, resp[1])
387
+
388
+ assert_equal err, env['gin.errors'].first
389
+ assert RuntimeError === env['gin.errors'].last
390
+ end
391
+
392
+
393
+ def test_handle_error_gin_controller_issue
394
+ env = {'rack.input' => "", 'PATH_INFO' => '/bad', 'REQUEST_METHOD' => 'GET'}
395
+ err = ArgumentError.new("Unexpected Argument")
396
+ old_handler = Gin::Controller.error_handlers[Exception]
397
+ Gin::Controller.error_handlers[Exception] = lambda{|err| raise Gin::Error, "FRAMEWORK IST KAPUT"}
398
+
399
+ assert_raises(Gin::Error){ @app.handle_error err, env }
400
+ ensure
401
+ Gin::Controller.error_handlers[Exception] = old_handler
402
+ end
403
+
404
+
405
+ def test_mime_type
406
+ assert_equal "foo/blah", Gin::App.mime_type("foo/blah")
407
+ assert_equal "text/html", Gin::App.mime_type(:html)
408
+ assert_equal "application/json", Gin::App.mime_type(:json)
409
+ assert_equal "text/plain", Gin::App.mime_type(".txt")
410
+
411
+ assert_equal Gin::App.mime_type(:json), @app.mime_type(:json)
412
+ end
413
+
414
+
415
+ def test_set_mime_type
416
+ assert_nil Gin::App.mime_type(:foo)
417
+ Gin::App.mime_type(:foo, "application/foo")
418
+ assert_equal "application/foo", @app.mime_type(:foo)
419
+ end
420
+
421
+
422
+ def test_asset_version
423
+ old_dir = FooApp.public_dir
424
+ FooApp.public_dir File.dirname(__FILE__)
425
+
426
+ md5_cmd = RUBY_PLATFORM =~ /darwin/ ? 'md5 -q' : 'md5sum'
427
+ expected = `#{md5_cmd} #{__FILE__}`[0...8]
428
+
429
+ assert_equal expected, FooApp.asset_version(File.basename(__FILE__))
430
+
431
+ ensure
432
+ FooApp.public_dir old_dir
433
+ end
434
+
435
+
436
+ def test_asset_host_for
437
+ FooApp.asset_host do |name|
438
+ "http://#{File.extname(name)[1..-1] << "." if name}foo.com"
439
+ end
440
+ assert_equal "http://js.foo.com", FooApp.asset_host_for("app.js")
441
+ assert_equal "http://js.foo.com", @app.asset_host_for("app.js")
442
+ end
443
+
444
+
445
+ def test_asset_host
446
+ FooApp.asset_host "http://example.com"
447
+ assert_equal "http://example.com", FooApp.asset_host
448
+ assert_equal "http://example.com", @app.asset_host
449
+
450
+ FooApp.asset_host{ "https://foo.com" }
451
+ assert_equal "https://foo.com", FooApp.asset_host
452
+ assert_equal "https://foo.com", @app.asset_host
453
+ end
454
+
455
+
456
+ def test_asset
457
+ FooApp.public_dir "./test/mock_config"
458
+ assert @app.asset("backend.yml") =~ %r{/gin/test/mock_config/backend\.yml$}
459
+ assert @app.asset("500.html") =~ %r{/gin/public/500\.html$}
460
+ assert_nil @app.asset("bad_file")
461
+ assert_nil @app.asset("../../History.rdoc")
462
+ end
463
+
464
+
465
+ def test_static
466
+ env = {'rack.input' => "", 'PATH_INFO' => '/foo', 'REQUEST_METHOD' => 'GET'}
467
+ assert !@app.static?(env)
468
+
469
+ env['PATH_INFO'] = '/500.html'
470
+ assert @app.static?(env) =~ %r{/gin/public/500\.html$}
471
+
472
+ env['PATH_INFO'] = '../../../500.html'
473
+ assert @app.static?(env) =~ %r{/gin/public/500\.html$}
474
+
475
+ env['REQUEST_METHOD'] = 'HEAD'
476
+ assert @app.static?(env) =~ %r{/gin/public/500\.html$}
477
+
478
+ env['PATH_INFO'] = '/backend.yml'
479
+ assert !@app.static?(env)
480
+
481
+ FooApp.public_dir "./test/mock_config"
482
+ assert @app.static?(env) =~ %r{/gin/test/mock_config/backend\.yml$}
483
+
484
+ %w{POST PUT DELETE TRACE OPTIONS}.each do |verb|
485
+ env['REQUEST_METHOD'] = verb
486
+ assert !@app.static?(env), "#{verb} should not be a static request"
487
+ end
488
+ end
489
+
490
+
491
+ def test_default_dirs
492
+ assert_equal File.expand_path("..",__FILE__), FooApp.root_dir
493
+ assert_equal File.expand_path("../public",__FILE__), FooApp.public_dir
494
+ assert_equal File.expand_path("..",__FILE__), @app.root_dir
495
+ assert_equal File.expand_path("../public",__FILE__), @app.public_dir
496
+ end
497
+
498
+
499
+ def test_init
500
+ assert Logger === @app.logger, "logger attribute should be a Logger"
501
+ assert Logger === @rapp.logger, "logger attribute should be a Logger"
502
+ assert_nil @app.rack_app, "Rack application should be nil by default"
503
+ assert Proc === @rapp.rack_app, "Rack application should be a Proc"
504
+ assert Gin::Router === @app.router, "Should have a Gin::Router"
505
+ assert @app.router.resources_for("get", "/foo"),
506
+ "App should route GET /foo"
507
+ end
508
+
509
+
510
+ def test_init_missing_routes
511
+ assert_raises Gin::App::RouterError do
512
+ MissingRouteApp.new
513
+ end
514
+ end
515
+
516
+
517
+ def test_init_extra_routes
518
+ assert_raises Gin::App::RouterError do
519
+ ExtraRouteApp.new
520
+ end
521
+ end
522
+
523
+
524
+ def test_default_environment
525
+ assert FooApp.development?
526
+ assert !FooApp.test?
527
+ assert !FooApp.staging?
528
+ assert !FooApp.production?
529
+ end
530
+
531
+
532
+ def test_default_inst_environment
533
+ assert @app.development?
534
+ assert !@app.test?
535
+ assert !@app.staging?
536
+ assert !@app.production?
537
+ end
538
+
539
+
540
+ def test_environment
541
+ FooApp.instance_variable_set("@environment", nil)
542
+ ENV['RACK_ENV'] = 'production'
543
+ assert !FooApp.development?
544
+ assert !FooApp.test?
545
+ assert !FooApp.staging?
546
+ assert FooApp.production?
547
+ end
548
+
549
+
550
+ def test_inst_environment
551
+ FooApp.instance_variable_set("@environment", nil)
552
+ ENV['RACK_ENV'] = 'production'
553
+ @app = FooApp.new
554
+ assert !@app.development?
555
+ assert !@app.test?
556
+ assert !@app.staging?
557
+ assert @app.production?
558
+ end
559
+
560
+
561
+ def test_set_environment
562
+ %w{development test staging production}.each do |name|
563
+ FooApp.environment name
564
+ mname = name + "?"
565
+ assert @app.send(mname), "Instance environment should be #{name}"
566
+ assert FooApp.send(mname), "Class environment should be #{name}"
567
+ end
568
+ end
569
+
570
+
571
+ def test_build_default_middleware
572
+ stack = @app.instance_variable_get("@stack")
573
+ assert Rack::Session::Cookie === stack
574
+ assert Rack::Protection::FrameOptions === stack.instance_variable_get("@app")
575
+
576
+ while stack = stack.instance_variable_get("@app")
577
+ app = stack
578
+ break if @app == app
579
+ end
580
+
581
+ assert_equal @app, app
582
+ end
583
+
584
+
585
+ def test_build_no_middleware
586
+ FooApp.sessions false
587
+ FooApp.protection false
588
+ @app = FooApp.new
589
+ stack = @app.instance_variable_get("@stack")
590
+ assert_equal @app, stack
591
+ end
592
+ end