gin 0.0.0 → 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.
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