raw 0.49.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.
Files changed (148) hide show
  1. data/doc/CONTRIBUTORS +106 -0
  2. data/doc/LICENSE +32 -0
  3. data/doc/coding_conventions.txt +11 -0
  4. data/lib/raw.rb +42 -0
  5. data/lib/raw/adapter.rb +113 -0
  6. data/lib/raw/adapter/cgi.rb +41 -0
  7. data/lib/raw/adapter/fastcgi.rb +48 -0
  8. data/lib/raw/adapter/mongrel.rb +146 -0
  9. data/lib/raw/adapter/script.rb +94 -0
  10. data/lib/raw/adapter/webrick.rb +144 -0
  11. data/lib/raw/adapter/webrick/vcr.rb +91 -0
  12. data/lib/raw/cgi.rb +323 -0
  13. data/lib/raw/cgi/cookie.rb +47 -0
  14. data/lib/raw/cgi/http.rb +62 -0
  15. data/lib/raw/compiler.rb +138 -0
  16. data/lib/raw/compiler/filter/cleanup.rb +21 -0
  17. data/lib/raw/compiler/filter/elements.rb +166 -0
  18. data/lib/raw/compiler/filter/elements/element.rb +210 -0
  19. data/lib/raw/compiler/filter/localization.rb +23 -0
  20. data/lib/raw/compiler/filter/markup.rb +32 -0
  21. data/lib/raw/compiler/filter/morph.rb +123 -0
  22. data/lib/raw/compiler/filter/morph/each.rb +34 -0
  23. data/lib/raw/compiler/filter/morph/for.rb +11 -0
  24. data/lib/raw/compiler/filter/morph/if.rb +26 -0
  25. data/lib/raw/compiler/filter/morph/selected_if.rb +43 -0
  26. data/lib/raw/compiler/filter/morph/standard.rb +55 -0
  27. data/lib/raw/compiler/filter/morph/times.rb +27 -0
  28. data/lib/raw/compiler/filter/script.rb +116 -0
  29. data/lib/raw/compiler/filter/squeeze.rb +16 -0
  30. data/lib/raw/compiler/filter/static_include.rb +74 -0
  31. data/lib/raw/compiler/filter/template.rb +121 -0
  32. data/lib/raw/compiler/reloader.rb +96 -0
  33. data/lib/raw/context.rb +154 -0
  34. data/lib/raw/context/flash.rb +157 -0
  35. data/lib/raw/context/global.rb +88 -0
  36. data/lib/raw/context/request.rb +338 -0
  37. data/lib/raw/context/response.rb +57 -0
  38. data/lib/raw/context/session.rb +198 -0
  39. data/lib/raw/context/session/drb.rb +11 -0
  40. data/lib/raw/context/session/file.rb +15 -0
  41. data/lib/raw/context/session/memcached.rb +13 -0
  42. data/lib/raw/context/session/memory.rb +12 -0
  43. data/lib/raw/context/session/og.rb +15 -0
  44. data/lib/raw/context/session/pstore.rb +13 -0
  45. data/lib/raw/control.rb +18 -0
  46. data/lib/raw/control/attribute.rb +91 -0
  47. data/lib/raw/control/attribute/checkbox.rb +25 -0
  48. data/lib/raw/control/attribute/datetime.rb +21 -0
  49. data/lib/raw/control/attribute/file.rb +20 -0
  50. data/lib/raw/control/attribute/fixnum.rb +26 -0
  51. data/lib/raw/control/attribute/float.rb +26 -0
  52. data/lib/raw/control/attribute/options.rb +38 -0
  53. data/lib/raw/control/attribute/password.rb +16 -0
  54. data/lib/raw/control/attribute/text.rb +16 -0
  55. data/lib/raw/control/attribute/textarea.rb +16 -0
  56. data/lib/raw/control/none.rb +16 -0
  57. data/lib/raw/control/relation.rb +59 -0
  58. data/lib/raw/control/relation/belongs_to.rb +0 -0
  59. data/lib/raw/control/relation/has_many.rb +97 -0
  60. data/lib/raw/control/relation/joins_many.rb +0 -0
  61. data/lib/raw/control/relation/many_to_many.rb +0 -0
  62. data/lib/raw/control/relation/refers_to.rb +29 -0
  63. data/lib/raw/controller.rb +37 -0
  64. data/lib/raw/controller/publishable.rb +160 -0
  65. data/lib/raw/dispatcher.rb +209 -0
  66. data/lib/raw/dispatcher/format.rb +108 -0
  67. data/lib/raw/dispatcher/format/atom.rb +31 -0
  68. data/lib/raw/dispatcher/format/css.rb +0 -0
  69. data/lib/raw/dispatcher/format/html.rb +42 -0
  70. data/lib/raw/dispatcher/format/json.rb +31 -0
  71. data/lib/raw/dispatcher/format/rss.rb +33 -0
  72. data/lib/raw/dispatcher/format/xoxo.rb +31 -0
  73. data/lib/raw/dispatcher/mounter.rb +60 -0
  74. data/lib/raw/dispatcher/router.rb +111 -0
  75. data/lib/raw/errors.rb +19 -0
  76. data/lib/raw/helper.rb +86 -0
  77. data/lib/raw/helper/benchmark.rb +23 -0
  78. data/lib/raw/helper/buffer.rb +60 -0
  79. data/lib/raw/helper/cookie.rb +32 -0
  80. data/lib/raw/helper/debug.rb +28 -0
  81. data/lib/raw/helper/default.rb +16 -0
  82. data/lib/raw/helper/feed.rb +451 -0
  83. data/lib/raw/helper/form.rb +284 -0
  84. data/lib/raw/helper/javascript.rb +59 -0
  85. data/lib/raw/helper/layout.rb +40 -0
  86. data/lib/raw/helper/navigation.rb +87 -0
  87. data/lib/raw/helper/pager.rb +305 -0
  88. data/lib/raw/helper/table.rb +247 -0
  89. data/lib/raw/helper/xhtml.rb +218 -0
  90. data/lib/raw/helper/xml.rb +125 -0
  91. data/lib/raw/mixin/magick.rb +35 -0
  92. data/lib/raw/mixin/sweeper.rb +71 -0
  93. data/lib/raw/mixin/thumbnails.rb +1 -0
  94. data/lib/raw/mixin/webfile.rb +165 -0
  95. data/lib/raw/render.rb +271 -0
  96. data/lib/raw/render/builder.rb +26 -0
  97. data/lib/raw/render/caching.rb +81 -0
  98. data/lib/raw/render/call.rb +43 -0
  99. data/lib/raw/render/send_file.rb +46 -0
  100. data/lib/raw/render/stream.rb +39 -0
  101. data/lib/raw/scaffold.rb +13 -0
  102. data/lib/raw/scaffold/controller.rb +25 -0
  103. data/lib/raw/scaffold/model.rb +157 -0
  104. data/lib/raw/test.rb +5 -0
  105. data/lib/raw/test/assertions.rb +169 -0
  106. data/lib/raw/test/context.rb +55 -0
  107. data/lib/raw/test/testcase.rb +79 -0
  108. data/lib/raw/util/attr.rb +128 -0
  109. data/lib/raw/util/encode_uri.rb +149 -0
  110. data/lib/raw/util/html_filter.rb +538 -0
  111. data/lib/raw/util/markup.rb +130 -0
  112. data/test/glue/tc_webfile.rb +1 -0
  113. data/test/nitro/CONFIG.rb +3 -0
  114. data/test/nitro/adapter/raw_post1.bin +9 -0
  115. data/test/nitro/adapter/tc_webrick.rb +16 -0
  116. data/test/nitro/cgi/tc_cookie.rb +14 -0
  117. data/test/nitro/cgi/tc_request.rb +61 -0
  118. data/test/nitro/compiler/tc_client_morpher.rb +47 -0
  119. data/test/nitro/compiler/tc_compiler.rb +25 -0
  120. data/test/nitro/dispatcher/tc_mounter.rb +47 -0
  121. data/test/nitro/helper/tc_feed.rb +135 -0
  122. data/test/nitro/helper/tc_navbar.rb +74 -0
  123. data/test/nitro/helper/tc_pager.rb +35 -0
  124. data/test/nitro/helper/tc_table.rb +68 -0
  125. data/test/nitro/helper/tc_xhtml.rb +19 -0
  126. data/test/nitro/tc_caching.rb +19 -0
  127. data/test/nitro/tc_cgi.rb +222 -0
  128. data/test/nitro/tc_context.rb +17 -0
  129. data/test/nitro/tc_controller.rb +103 -0
  130. data/test/nitro/tc_controller_aspect.rb +32 -0
  131. data/test/nitro/tc_controller_params.rb +885 -0
  132. data/test/nitro/tc_dispatcher.rb +109 -0
  133. data/test/nitro/tc_element.rb +85 -0
  134. data/test/nitro/tc_flash.rb +59 -0
  135. data/test/nitro/tc_helper.rb +47 -0
  136. data/test/nitro/tc_render.rb +119 -0
  137. data/test/nitro/tc_router.rb +61 -0
  138. data/test/nitro/tc_server.rb +35 -0
  139. data/test/nitro/tc_session.rb +66 -0
  140. data/test/nitro/tc_template.rb +71 -0
  141. data/test/nitro/util/tc_encode_url.rb +87 -0
  142. data/test/nitro/util/tc_markup.rb +31 -0
  143. data/test/public/blog/another/very_litle/index.xhtml +1 -0
  144. data/test/public/blog/inc1.xhtml +2 -0
  145. data/test/public/blog/inc2.xhtml +1 -0
  146. data/test/public/blog/list.xhtml +9 -0
  147. data/test/public/dummy_mailer/registration.xhtml +5 -0
  148. metadata +244 -0
@@ -0,0 +1,103 @@
1
+ require File.join(File.dirname(__FILE__), 'CONFIG.rb')
2
+
3
+ require 'test/unit'
4
+ require 'ostruct'
5
+
6
+ require 'glue'
7
+ require 'glue/logger'
8
+ require 'nitro'
9
+
10
+ class TC_Controller < Test::Unit::TestCase # :nodoc: all
11
+ include Nitro
12
+
13
+ class FirstController < Controller
14
+ def list
15
+ end
16
+ end
17
+
18
+ class SecondController < Controller
19
+ attr_reader :aqflag, :tflag
20
+
21
+ def self.setup_template_root(path)
22
+ @template_root << File.expand_path(File.join(Nitro::LibPath, "../test/public/#{path}"))
23
+ end
24
+
25
+ def list
26
+ @aqflag = true
27
+ end
28
+
29
+ def another(oid)
30
+ # nop
31
+ end
32
+
33
+ private
34
+
35
+ def encode_myself
36
+ encode_url :list
37
+ end
38
+
39
+ def encode_first
40
+ encode_url FirstController, :list
41
+ end
42
+ end
43
+
44
+ def setup
45
+ @disp = Dispatcher.new '/first' => FirstController,
46
+ '/second' => SecondController
47
+ @conf = OpenStruct.new
48
+ @conf.dispatcher = @disp
49
+ end
50
+
51
+ def test_render
52
+ ctx = Context.new(@conf)
53
+ ctx.headers = {}
54
+ ctx.params = {}
55
+ ctx.headers['REQUEST_URI'] = '/second/list'
56
+ ctx.instance_eval '@session = {}'
57
+ klass, action = ctx.dispatcher.dispatch(ctx.path, ctx)
58
+ c = klass.new(ctx)
59
+
60
+ begin
61
+ c.send(action)
62
+ rescue RenderExit
63
+ # drink
64
+ end
65
+
66
+ assert_equal('/second/list', c.send(:encode_myself))
67
+ assert_equal('/first/list', c.send(:encode_first))
68
+
69
+ # handle action with arity.
70
+ assert_equal('/second/another/32', c.send(:encode_url, :another, :oid, 32))
71
+
72
+ assert_equal true, c.aqflag
73
+ =begin
74
+ # if anybody has an idea what this is for, go, fix it :)
75
+ assert_equal true, $include1
76
+ assert_equal true, $include2
77
+
78
+ # the template is compiled
79
+ assert_equal true, c.tflag
80
+ =end
81
+ end
82
+
83
+ def test_action_methods
84
+ assert_equal ['list'], FirstController.action_methods
85
+ assert_equal 1, FirstController.action_methods.size
86
+ assert_equal 4, SecondController.action_methods.size
87
+ assert FirstController.action_methods.include?('list')
88
+ assert SecondController.action_methods.include?('list')
89
+ end
90
+
91
+ def test_encode_decode_methods
92
+
93
+ end
94
+
95
+ def test_mount_path
96
+ assert_equal '/first', FirstController.mount_path
97
+ assert_equal '/second', SecondController.mount_path
98
+ # path is private
99
+ assert_equal '/first', FirstController.allocate.send(:mount_path)
100
+ assert_equal '/second', SecondController.allocate.send(:mount_path)
101
+ end
102
+
103
+ end
@@ -0,0 +1,32 @@
1
+ require File.join(File.dirname(__FILE__), 'CONFIG.rb')
2
+
3
+ require 'test/unit'
4
+
5
+ require 'nitro'
6
+
7
+ class TestControllerAspect < Test::Unit::TestCase # :nodoc: all
8
+ include Nitro
9
+
10
+ class TestController < Controller
11
+ attr_reader :aflag, :tflag
12
+
13
+ @template_root = []
14
+
15
+ post "@aflag = 25", :on => :list
16
+
17
+ def list
18
+ @aflag = 3
19
+ end
20
+ end
21
+
22
+ def test_aspect
23
+ ctx = Context.new(Server.new)
24
+ ctx.instance_variable_set '@session', {}
25
+ ctx.instance_variable_set '@headers', {}
26
+ c = TestController.new(ctx)
27
+ c.list_action
28
+
29
+ assert_equal 25, c.aflag
30
+ end
31
+
32
+ end
@@ -0,0 +1,885 @@
1
+ require File.join(File.dirname(__FILE__), 'CONFIG.rb')
2
+
3
+ $DBG = true
4
+
5
+ require 'test/unit'
6
+ require 'ostruct'
7
+
8
+ require 'nitro'
9
+ require 'nitro/cgi'
10
+
11
+
12
+ class String
13
+ def clear
14
+ gsub!(/.*/m, '')
15
+ end
16
+ end
17
+
18
+ class TC_ControllerParams < Test::Unit::TestCase # :nodoc: all
19
+
20
+ module Common
21
+ def return_results *arguments
22
+ from = caller[0][/`.*?'/][1..-2].intern
23
+ hash = {}
24
+ request.params.each do |k,v|
25
+ hash[k] = if v.kind_of?(Tempfile) || v.kind_of?(StringIO) || v.kind_of?(IO)
26
+ { :filename => v.original_filename, :size => v.size }
27
+ else
28
+ v
29
+ end
30
+ request.params = hash
31
+ end
32
+
33
+ @out.clear
34
+ @out << {
35
+ :action => from,
36
+ :params => request.params,
37
+ :arguments => arguments,
38
+ :klass => self.class,
39
+ :method => request.method
40
+ }.inspect
41
+ end
42
+ private :return_results
43
+ end # end module Common
44
+
45
+ class TestController < Nitro::Controller
46
+ include Common
47
+
48
+ def index
49
+ return_results
50
+ end
51
+
52
+ # Arity 0
53
+
54
+ def none
55
+ return_results
56
+ end
57
+
58
+ # Arity 1 - 3
59
+
60
+ def single(arg)
61
+ return_results arg
62
+ end
63
+
64
+ def double(arg1, arg2)
65
+ return_results arg1, arg2
66
+ end
67
+
68
+ def triple(arg1, arg2, arg3)
69
+ return_results arg1, arg2, arg3
70
+ end
71
+
72
+ def double__foo(arg)
73
+ return_results arg
74
+ end
75
+
76
+ # Arity -1
77
+
78
+ def m1(*args)
79
+ return_results *args
80
+ end
81
+
82
+ def m1_2(arg1 = nil, arg2 = nil)
83
+ return_results arg1, arg2
84
+ end
85
+
86
+ # Arity -2
87
+
88
+ def m2(klass, parent_symbol = nil, parent_oid = nil, *args)
89
+ return_results klass, parent_symbol, parent_oid, args
90
+ end
91
+
92
+ def m2_2(klass, parent_symbol = nil, parent_oid = nil)
93
+ return_results klass, parent_symbol, parent_oid
94
+ end
95
+
96
+ # Overridden by C2?
97
+
98
+ def c2
99
+ return_results
100
+ end
101
+
102
+ # Error handler
103
+
104
+ def error
105
+ "(error)"
106
+ end
107
+
108
+ end # end class TestController
109
+
110
+ class TestController2 < Nitro::Controller
111
+ include Common
112
+
113
+ def index(arg1 = nil, arg2 = nil)
114
+ return_results arg1, arg2
115
+ end
116
+
117
+ end # end class TestController2
118
+
119
+ module TestTestController3Helper
120
+ def login
121
+ return_results
122
+ end
123
+ end
124
+
125
+ class TestController3 < Nitro::Controller
126
+ include Common
127
+ include TestTestController3Helper
128
+
129
+ def index(arg1)
130
+ return_results arg1
131
+ end
132
+
133
+ def document(oid=nil, del=nil, add=nil)
134
+ return_results oid, del, add
135
+ end
136
+
137
+ def post(one = nil)
138
+ return_results one
139
+ end
140
+
141
+ end # end class TestController2
142
+
143
+
144
+ class TestControllerRouter < Nitro::Controller
145
+ include Common
146
+
147
+ def routed_one(name)
148
+ return_results name
149
+ end
150
+ ::Nitro::Router.add_rule :match => /^\/routed_one\/(.*)/, :controller => TestControllerRouter, :action => :routed_one, :param => :name
151
+
152
+ end
153
+
154
+ #
155
+ # Defined assertions
156
+ #
157
+
158
+ # Check against reference hash, only compare available values
159
+
160
+ def cmp(reference, checked)
161
+ reference.each do |k,v|
162
+ return false if checked[k] != v
163
+ end
164
+
165
+ return true
166
+ end
167
+
168
+ def handle_request(url, value)
169
+ conf = OpenStruct.new
170
+ disp = Nitro::Dispatcher.new(
171
+ '/' => TestController,
172
+ '/c2' => TestController2,
173
+ '/c3' => TestController3,
174
+ '/c4' => TestControllerRouter)
175
+ conf.dispatcher = disp
176
+ @ctx = Nitro::Context.new(conf)
177
+ @ctx.headers = { 'REQUEST_METHOD' => 'GET' }
178
+ @ctx.params = {}
179
+ @ctx.instance_variable_set '@session', {}
180
+
181
+ if value[:in]
182
+ @ctx.in = value.delete(:in)
183
+ @ctx.headers['CONTENT_LENGTH'] = value.delete(:in_size) || @ctx.in.size
184
+ end
185
+
186
+ if value[:method]
187
+ @ctx.headers['REQUEST_METHOD'] = value[:method].to_s
188
+ end
189
+
190
+ if value['CONTENT_TYPE']
191
+ @ctx.headers['CONTENT_TYPE'] = value.delete('CONTENT_TYPE')
192
+ end
193
+
194
+ @ctx.headers['REQUEST_URI'] = url
195
+
196
+ if (!@ctx.query_string || @ctx.query_string.empty?) and @ctx.uri =~ /\?/
197
+ @ctx.headers['QUERY_STRING'] = @ctx.uri.split('?').last
198
+ end
199
+
200
+ Nitro::Cgi.parse_params(@ctx)
201
+ Nitro::Cgi.parse_cookies(@ctx)
202
+
203
+ @ctx.render url
204
+
205
+ #retrieve the stuff from @out again as a hash
206
+ result = @ctx.out
207
+
208
+ return result
209
+ end
210
+
211
+ def assert_request_good(url, value, message = nil)
212
+ result = handle_request(url, value)
213
+
214
+ message = build_message(message, "<?> returned error. \nResult: ?\nInstead of: ?", url, result, value)
215
+
216
+ assert_block message do
217
+ if result =~ /error/
218
+ false
219
+ else
220
+ cmp(value, eval(result))
221
+ end
222
+ end
223
+ end
224
+
225
+ def assert_request_bad(url, value, message = nil)
226
+ result = handle_request(url, value)
227
+
228
+ message = build_message(message, '<?> did not return error.', url)
229
+ assert_block message do
230
+ result = @ctx.out
231
+
232
+ result =~ /error/
233
+ end
234
+ end
235
+
236
+ ###################################################################
237
+ # Simple Testcases
238
+ ###################################################################
239
+
240
+ def test_simple
241
+ tests = {
242
+ '/none' => {
243
+ :action => :none,
244
+ :params => {},
245
+ :arguments => []
246
+ },
247
+ '/single/arg' => {
248
+ :action => :single,
249
+ :params => {},
250
+ :arguments => ['arg']
251
+ },
252
+ '/double/arg1/arg2' => {
253
+ :action => :double,
254
+ :params => {},
255
+ :arguments => ['arg1', 'arg2']
256
+ },
257
+ '/triple/arg1/arg2/arg3' => {
258
+ :action => :triple,
259
+ :params => {},
260
+ :arguments => ['arg1', 'arg2', 'arg3']
261
+ },
262
+ # George: none hase no arity, so the following *IS* valid!
263
+ '/none/one/two' => {
264
+ :action => :none,
265
+ :params => {},
266
+ :arguments => []
267
+ }
268
+ }
269
+
270
+ tests.each do |url, value|
271
+ assert_request_good url, value
272
+ end
273
+ end
274
+
275
+ def test_simple_params
276
+ tests = {
277
+ '/none/?first=one&second=two' => {
278
+ :action => :none,
279
+ :params => {'first' => 'one', 'second' => 'two'},
280
+ :arguments => []
281
+ },
282
+ '/none/?first=one&second=two' => {
283
+ :action => :none,
284
+ :params => {'first' => 'one', 'second' => 'two'},
285
+ :arguments => []
286
+ },
287
+ '/none/?first' => {
288
+ :action => :none,
289
+ :params => {'first' => nil},
290
+ :arguments => []
291
+ },
292
+ '/none/?first&second' => {
293
+ :action => :none,
294
+ :params => {'first' => nil, 'second' => nil},
295
+ :arguments => []
296
+ }
297
+ }
298
+
299
+ tests.each do |url, value|
300
+ assert_request_good url, value
301
+ end
302
+ end
303
+
304
+ def test_simple_bad
305
+ tests = {
306
+ '/single' => {
307
+ :action => :single,
308
+ :params => {},
309
+ :arguments => [],
310
+ :errmsg => 'Too few arguments. Should be one.'
311
+ },
312
+ '/double/arg1' => {
313
+ :action => :double,
314
+ :params => {},
315
+ :arguments => [],
316
+ :errmsg => 'Too few arguments. Should be two.'
317
+ },
318
+ '/triple/arg1/arg2' => {
319
+ :action => :triple,
320
+ :params => {},
321
+ :arguments => [],
322
+ :errmsg => 'Too few arguments. Should be 3.'
323
+ },
324
+ '/triple/arg1/arg2/arg3/arg4' => {
325
+ :action => :triple,
326
+ :params => {},
327
+ :arguments => [],
328
+ :errmsg => 'Too many arguments. Should be 3.'
329
+ }
330
+ }
331
+
332
+ tests.each do |url, value|
333
+ assert_request_bad url, value, value.delete(:errmsg)
334
+ end
335
+ end
336
+
337
+ def test_mixed
338
+ tests = {
339
+ '/single/foo?first=one&second=two' => {
340
+ :action => :single,
341
+ :params => {'first' => 'one', 'second' => 'two'},
342
+ :arguments => ['foo']
343
+ },
344
+ '/double/foo/bar?first=one&second=two' => {
345
+ :action => :double,
346
+ :params => {'first' => 'one', 'second' => 'two'},
347
+ :arguments => ['foo', 'bar']
348
+ }
349
+ }
350
+
351
+ tests.each do |url, value|
352
+ assert_request_good url, value
353
+ end
354
+ end
355
+
356
+ def test_slashes
357
+ tests = {
358
+ '/single/foo' => {
359
+ :action => :single,
360
+ :params => {},
361
+ :arguments => ['foo']
362
+ },
363
+ '/double/foo/bar' => {
364
+ :action => :double__foo,
365
+ :params => {},
366
+ :arguments => []
367
+ },
368
+ '/double/foo/bar/' => {
369
+ :action => :double,
370
+ :params => {},
371
+ :arguments => ['foo', 'bar']
372
+ },
373
+ '/double/foo/bar' => {
374
+ :action => :double,
375
+ :params => {},
376
+ :arguments => ['foo', 'bar']
377
+ },
378
+ '/double/foo/bar/' => {
379
+ :action => :double,
380
+ :params => {},
381
+ :arguments => ['foo', 'bar']
382
+ },
383
+ '/none' => {
384
+ :action => :none,
385
+ :params => {},
386
+ :arguments => []
387
+ },
388
+ '/none/' => {
389
+ :action => :none,
390
+ :params => {},
391
+ :arguments => []
392
+ }
393
+ }
394
+
395
+ tests.each do |url, value|
396
+ assert_request_good url, value
397
+ end
398
+ end
399
+
400
+ ###################################################################
401
+ # Arity -2 tests
402
+ ###################################################################
403
+
404
+ def test_m2
405
+ tests = {
406
+ '/m2/OgModule/user/5' => {
407
+ :action => :m2,
408
+ :params => {},
409
+ :arguments => ['OgModule', 'user', '5', []]
410
+ },
411
+ '/m2/OgModule' => {
412
+ :action => :m2,
413
+ :params => {},
414
+ :arguments => ['OgModule', nil, nil, []]
415
+ },
416
+ '/m2/OgModule/' => {
417
+ :action => :m2,
418
+ :params => {},
419
+ :arguments => ['OgModule', nil, nil, []]
420
+ },
421
+ '/m2/OgModule/user/5/more/garbage' => {
422
+ :action => :m2,
423
+ :params => {},
424
+ :arguments => ['OgModule', 'user', '5', ['more', 'garbage']]
425
+ },
426
+ '/m2_2/OgModule/user/5' => {
427
+ :action => :m2_2,
428
+ :params => {},
429
+ :arguments => ['OgModule', 'user', '5']
430
+ },
431
+ '/m2_2/OgModule' => {
432
+ :action => :m2_2,
433
+ :params => {},
434
+ :arguments => ['OgModule', nil, nil]
435
+ }
436
+ }
437
+
438
+ tests.each do |url, value|
439
+ assert_request_good url, value
440
+ end
441
+ end
442
+
443
+ def test_m2_bad
444
+ tests = {
445
+ '/m2_2/OgModule/user/5/foo/bar' => {
446
+ :action => :m2_2,
447
+ :params => {},
448
+ :arguments => [],
449
+ :errmsg => 'Too many arguments.'
450
+ },
451
+ '/m2_2/' => {
452
+ :action => :m2_2,
453
+ :params => {},
454
+ :arguments => [],
455
+ :errmsg => 'Not enough arguments.'
456
+ },
457
+ '/m2' => {
458
+ :action => :m2,
459
+ :params => {},
460
+ :arguments => [],
461
+ :errmsg => 'Not enough arguments.'
462
+ }
463
+ }
464
+
465
+ tests.each do |url, value|
466
+ assert_request_bad url, value, value.delete(:errmsg)
467
+ end
468
+ end
469
+
470
+ ###################################################################
471
+ # Arity -1 Tests
472
+ ###################################################################
473
+
474
+ def test_m1
475
+ tests = {
476
+ '/m1_2/' => {
477
+ :action => :m1_2,
478
+ :params => {},
479
+ :arguments => [nil, nil]
480
+ },
481
+ '/m1_2' => {
482
+ :action => :m1_2,
483
+ :params => {},
484
+ :arguments => [nil, nil]
485
+ },
486
+ '/m1_2/One' => {
487
+ :action => :m1_2,
488
+ :params => {},
489
+ :arguments => ['One', nil]
490
+ },
491
+ '/m1_2/One/Two' => {
492
+ :action => :m1_2,
493
+ :params => {},
494
+ :arguments => ['One', 'Two']
495
+ },
496
+ }
497
+
498
+ tests.each do |url, value|
499
+ assert_request_good url, value
500
+ end
501
+ end
502
+
503
+ def test_sub_zero_mixed
504
+ tests = {
505
+ '/m1/OgModule/user/5?more=garbage' => {
506
+ :action => :m1,
507
+ :params => {'more' => 'garbage'},
508
+ :arguments => ['OgModule', 'user', '5']
509
+ },
510
+ '/m2/OgModule/user/5?more=garbage' => {
511
+ :action => :m2,
512
+ :params => {'more' => 'garbage'},
513
+ :arguments => ['OgModule', 'user', '5', []]
514
+ },
515
+ '/m2/OgModule?more=garbage' => {
516
+ :action => :m2,
517
+ :params => {'more' => 'garbage'},
518
+ :arguments => ['OgModule', nil, nil, []]
519
+ }
520
+ }
521
+
522
+ tests.each do |url, value|
523
+ assert_request_good url, value
524
+ end
525
+ end
526
+
527
+ ###################################################################
528
+ # Used Controller Tests
529
+ ###################################################################
530
+
531
+ def test_controllers
532
+ tests = {
533
+ '/c2' => {
534
+ :action => :index,
535
+ :klass => TestController2,
536
+ :arguments => [nil, nil]
537
+ },
538
+ '/c2/' => {
539
+ :action => :index,
540
+ :klass => TestController2,
541
+ :arguments => [nil, nil]
542
+ },
543
+ '/' => {
544
+ :action => :index,
545
+ :klass => TestController
546
+ }
547
+ }
548
+
549
+ tests.each do |url, value|
550
+ assert_request_good url, value
551
+ end
552
+ end
553
+
554
+ def test_index_handling
555
+ tests = {
556
+ '/c2/One' => {
557
+ :action => :index,
558
+ :klass => TestController2,
559
+ :arguments => ['One', nil]
560
+ },
561
+ '/c2/One/Two' => {
562
+ :action => :index,
563
+ :klass => TestController2,
564
+ :arguments => ['One', 'Two']
565
+ },
566
+ '/c2/index/One' => {
567
+ :action => :index,
568
+ :klass => TestController2,
569
+ :arguments => ['One', nil]
570
+ },
571
+ '/c2/index/One/Two' => {
572
+ :action => :index,
573
+ :klass => TestController2,
574
+ :arguments => ['One', 'Two']
575
+ },
576
+ '/c3/index/One' => {
577
+ :action => :index,
578
+ :klass => TestController3,
579
+ :arguments => ['One']
580
+ },
581
+ '/c3/One' => {
582
+ :action => :index,
583
+ :klass => TestController3,
584
+ :arguments => ['One']
585
+ }
586
+ }
587
+
588
+ tests.each do |url, value|
589
+ assert_request_good url, value
590
+ end
591
+ end
592
+
593
+ def test_index_handling_bad
594
+ tests = {
595
+ '/c2/One/Two/Three' => {
596
+ :action => :index,
597
+ :klass => TestController2
598
+ },
599
+ '/c2/index/One/Two/Three' => {
600
+ :action => :index,
601
+ :klass => TestController2
602
+ },
603
+ '/c3/One/Two' => {
604
+ :action => :index,
605
+ :klass => TestController3
606
+ },
607
+ '/c3' => {
608
+ :action => :index,
609
+ :klass => TestController3
610
+ },
611
+ '/c3/index' => {
612
+ :action => :index,
613
+ :klass => TestController3
614
+ }
615
+ }
616
+
617
+ tests.each do |url, value|
618
+ assert_request_bad url, value
619
+ end
620
+ end
621
+
622
+ ###################################################################
623
+ # Test Bug Reports
624
+ ###################################################################
625
+
626
+ def test_bug_report_ray
627
+ tests = {
628
+ '/c3/document/new/1' => {
629
+ :action => :document,
630
+ :klass => TestController3,
631
+ :arguments => ['new', '1', nil]
632
+ }
633
+ }
634
+
635
+ tests.each do |url, value|
636
+ assert_request_good url, value
637
+ end
638
+ end
639
+
640
+ def test_bug_report_fabian
641
+ tests = {
642
+ '/c3/login' => {
643
+ :action => :login,
644
+ :klass => TestController3,
645
+ :arguments => []
646
+ }
647
+ }
648
+
649
+ assert TestController3.ancestors.include?(TestTestController3Helper)
650
+ assert TestController3.instance_methods.include?('login')
651
+ assert TestController3.action_methods.include?('login')
652
+
653
+ tests.each do |url, value|
654
+ assert_request_good url, value
655
+ end
656
+
657
+ end
658
+
659
+ def test_bug_report_kartesus
660
+ tests = {
661
+ '/none' => {
662
+ :action => :none,
663
+ :klass => TestController,
664
+ :arguments => [],
665
+ :params => {"test_file_a" => {:size=>10028,
666
+ :filename=>"test_case.txt"},
667
+ "test_file_b" => {:size=>10240,
668
+ :filename=>"test_case.txt"},
669
+ "empty_field" => {:size=>0, :filename=>""}},
670
+ :method => :post
671
+ }
672
+ }
673
+
674
+ tests.each do |url, value|
675
+ create_multipart(value)
676
+ assert_request_good url, value
677
+ end
678
+ end
679
+
680
+ ###################################################################
681
+ # Test Routed Parameters
682
+ ###################################################################
683
+
684
+ def test_routed_one
685
+ tests = {
686
+ '/routed_one/some/name/I/got/here...' => {
687
+ :action => :routed_one,
688
+ :klass => TestControllerRouter,
689
+ :arguments => ['some/name/I/got/here...'],
690
+ :params => {}
691
+ }
692
+ }
693
+
694
+ tests.each do |url, value|
695
+ assert_request_good url, value
696
+ end
697
+ end
698
+
699
+ ###################################################################
700
+ # Mix-in GET Parameter Tests
701
+ ###################################################################
702
+
703
+ def test_mixin_get_parameters
704
+ ::Nitro::Compiler.mixin_get_parameters = true
705
+
706
+ tests = {
707
+ '/double?arg1=bar;arg2=foo' => {
708
+ :action => :double,
709
+ :params => {'arg1' => 'bar', 'arg2' => 'foo'},
710
+ :arguments => ['bar', 'foo']
711
+ }
712
+ }
713
+
714
+ tests.each do |url, value|
715
+ assert_request_good url, value
716
+ end
717
+ ensure
718
+ ::Nitro::Compiler.mixin_get_parameters = false
719
+ end
720
+
721
+ ###################################################################
722
+ # Non-strict Action Calling Tests
723
+ ###################################################################
724
+
725
+ def test_non_strict_action_calling
726
+ ::Nitro::Compiler.non_strict_action_calling = true
727
+
728
+ tests = {
729
+ '/double' => {
730
+ :action => :double,
731
+ :params => {},
732
+ :arguments => [nil, nil]
733
+ }
734
+ }
735
+
736
+ tests.each do |url, value|
737
+ assert_request_good url, value
738
+ end
739
+ ensure
740
+ ::Nitro::Compiler.non_strict_action_calling = false
741
+ end
742
+
743
+ ###################################################################
744
+ # Test POST Multipart
745
+ ###################################################################
746
+
747
+ def test_multipart
748
+ tests = {
749
+ '/c3/post' => {
750
+ :action => :post,
751
+ :klass => TestController3,
752
+ :arguments => [nil],
753
+ :params => {"test_file_a" => {:size=>10028,
754
+ :filename=>"test_case.txt"},
755
+ "test_file_b" => {:size=>10240,
756
+ :filename=>"test_case.txt"},
757
+ "empty_field" => {:size=>0, :filename=>""}},
758
+ :method => :post
759
+ },
760
+ '/c3/post/1' => {
761
+ :action => :post,
762
+ :klass => TestController3,
763
+ :arguments => ['1'],
764
+ :params => {"test_file_a" => {:size=>10028,
765
+ :filename=>"test_case.txt"},
766
+ "test_file_b" => {:size=>10240,
767
+ :filename=>"test_case.txt"},
768
+ "empty_field" => {:size=>0, :filename=>""}},
769
+ :method => :post
770
+ },
771
+ '/c3/post/1?more=data' => {
772
+ :action => :post,
773
+ :klass => TestController3,
774
+ :arguments => ['1'],
775
+ :params => {"test_file_a" => {:size=>10028,
776
+ :filename=>"test_case.txt"},
777
+ "test_file_b" => {:size=>10240,
778
+ :filename=>"test_case.txt"},
779
+ "empty_field" => {:size=>0, :filename=>""},
780
+ "more" => "data"},
781
+ :method => :post
782
+ }
783
+ }
784
+
785
+ tests.each do |url, value|
786
+ create_multipart(value)
787
+ assert_request_good url, value
788
+ end
789
+ end
790
+
791
+ def create_multipart(options, boundary = "---------------------------15773515131648678014689318540")
792
+ # MIME block close falls on read boundary, also contains an empty field.
793
+ closure = "#{Nitro::Cgi::EOL}--#{boundary}--#{Nitro::Cgi::EOL}"
794
+ block_size = Nitro::Cgi.buffer_size
795
+
796
+ input = StringIO.new
797
+ input << "--#{boundary}#{Nitro::Cgi::EOL}"
798
+ input << "Content-Disposition: form-data; name=\"test_file_a\"; filename=\"test_case.txt\"#{Nitro::Cgi::EOL}Content-Type: application/octet-stream#{Nitro::Cgi::EOL}#{Nitro::Cgi::EOL}"
799
+ fake_file_a = String.random(block_size - input.size - (closure.size/2))
800
+ input << fake_file_a
801
+ input_after_fake_file = input.size
802
+ input << "#{Nitro::Cgi::EOL}--#{boundary}#{Nitro::Cgi::EOL}"
803
+
804
+ #Boundary fell inbetween two reads?
805
+ assert_equal((block_size > input_after_fake_file) && (block_size < input.size),true)
806
+
807
+ input << "Content-Disposition: form-data; name=\"test_file_b\"; filename=\"test_case.txt\"#{Nitro::Cgi::EOL}Content-Type: application/octet-stream#{Nitro::Cgi::EOL}#{Nitro::Cgi::EOL}"
808
+ fake_file_b = Tempfile.new("TCCGI")
809
+
810
+ i = 0
811
+ file_size = 1024*10 # 1MB
812
+ i += fake_file_b.write String.random(1024*10) while i < file_size
813
+
814
+ fake_file_b.rewind
815
+ input << fake_file_b.read
816
+ fake_file_b.rewind
817
+ input << "#{Nitro::Cgi::EOL}--#{boundary}#{Nitro::Cgi::EOL}"
818
+
819
+ input << "Content-Disposition: form-data; name=\"empty_field\"#{Nitro::Cgi::EOL}#{Nitro::Cgi::EOL}"
820
+ input << closure
821
+ input.rewind
822
+
823
+ options[:in] = input
824
+ options[:in_size] = input.size
825
+ options['CONTENT_TYPE'] = "multipart/form-data boundary=\"#{boundary}\""
826
+ end
827
+
828
+ end
829
+
830
+ # Random data for multipart param test
831
+
832
+ class String
833
+ class << self
834
+
835
+ begin
836
+ require 'inline'
837
+
838
+ inline do |builder|
839
+ builder.c_raw <<-EOS
840
+ static VALUE rnd(int argc, VALUE* args, VALUE self)
841
+ {
842
+ if (!argc)
843
+ rb_raise(rb_eArgError, "not enough arguments");
844
+ if (argc > 0)
845
+ Check_Type(args[0], T_FIXNUM);
846
+ if (argc > 1)
847
+ Check_Type(args[1], T_FIXNUM);
848
+
849
+ int size = FIX2INT(args[0]);
850
+ int seed = argc > 1 ? FIX2INT(args[1]) : 0;
851
+ int i = 0;
852
+ VALUE str = rb_str_new((char*)0, size);
853
+
854
+ srandom(seed);
855
+
856
+ for (; i < size; i++) {
857
+ RSTRING(str)->ptr[i] = (char)(((random() % ('z' - ' ')) + ' '));
858
+ }
859
+
860
+ return str;
861
+ }
862
+ EOS
863
+ end
864
+
865
+ def random(size, seed = 22)
866
+ return rnd(size.to_i, seed.to_i)
867
+ end
868
+
869
+ rescue Exception => e
870
+ puts "please install Ruby::Inline (gem install RubyInline) to speed up this test"
871
+
872
+ def random(size)
873
+ s = String.new
874
+ range = (' '..'z').to_a
875
+ r_size = range.size
876
+ for i in (0...size)
877
+ s << range[Kernel.rand(r_size)] # ascii range
878
+ end
879
+ s
880
+ end
881
+
882
+ end
883
+
884
+ end
885
+ end