nyara 0.0.1.pre
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.
- checksums.yaml +7 -0
- data/example/design.rb +62 -0
- data/example/fib.rb +15 -0
- data/example/hello.rb +5 -0
- data/example/stream.rb +10 -0
- data/ext/accept.c +133 -0
- data/ext/event.c +89 -0
- data/ext/extconf.rb +34 -0
- data/ext/hashes.c +130 -0
- data/ext/http-parser/AUTHORS +41 -0
- data/ext/http-parser/CONTRIBUTIONS +4 -0
- data/ext/http-parser/LICENSE-MIT +23 -0
- data/ext/http-parser/contrib/parsertrace.c +156 -0
- data/ext/http-parser/contrib/url_parser.c +44 -0
- data/ext/http-parser/http_parser.c +2175 -0
- data/ext/http-parser/http_parser.h +304 -0
- data/ext/http-parser/test.c +3425 -0
- data/ext/http_parser.c +1 -0
- data/ext/inc/epoll.h +60 -0
- data/ext/inc/kqueue.h +77 -0
- data/ext/inc/status_codes.inc +64 -0
- data/ext/inc/str_intern.h +66 -0
- data/ext/inc/version.inc +1 -0
- data/ext/mime.c +107 -0
- data/ext/multipart-parser-c/README.md +18 -0
- data/ext/multipart-parser-c/multipart_parser.c +309 -0
- data/ext/multipart-parser-c/multipart_parser.h +48 -0
- data/ext/multipart_parser.c +1 -0
- data/ext/nyara.c +56 -0
- data/ext/nyara.h +59 -0
- data/ext/request.c +474 -0
- data/ext/route.cc +325 -0
- data/ext/url_encoded.c +304 -0
- data/hello.rb +5 -0
- data/lib/nyara/config.rb +64 -0
- data/lib/nyara/config_hash.rb +51 -0
- data/lib/nyara/controller.rb +336 -0
- data/lib/nyara/cookie.rb +31 -0
- data/lib/nyara/cpu_counter.rb +65 -0
- data/lib/nyara/header_hash.rb +18 -0
- data/lib/nyara/mime_types.rb +612 -0
- data/lib/nyara/nyara.rb +82 -0
- data/lib/nyara/param_hash.rb +5 -0
- data/lib/nyara/request.rb +144 -0
- data/lib/nyara/route.rb +138 -0
- data/lib/nyara/route_entry.rb +43 -0
- data/lib/nyara/session.rb +104 -0
- data/lib/nyara/view.rb +317 -0
- data/lib/nyara.rb +25 -0
- data/nyara.gemspec +20 -0
- data/rakefile +91 -0
- data/readme.md +35 -0
- data/spec/ext_mime_match_spec.rb +27 -0
- data/spec/ext_parse_accept_value_spec.rb +29 -0
- data/spec/ext_parse_spec.rb +138 -0
- data/spec/ext_route_spec.rb +70 -0
- data/spec/hashes_spec.rb +71 -0
- data/spec/path_helper_spec.rb +77 -0
- data/spec/request_delegate_spec.rb +67 -0
- data/spec/request_spec.rb +56 -0
- data/spec/route_entry_spec.rb +12 -0
- data/spec/route_spec.rb +84 -0
- data/spec/session_spec.rb +66 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/view_spec.rb +87 -0
- data/tools/bench-cookie.rb +22 -0
- metadata +111 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
module Nyara
|
4
|
+
describe Ext, "route" do
|
5
|
+
before :each do
|
6
|
+
Ext.clear_route
|
7
|
+
@e1 = RouteEntry.new{
|
8
|
+
@http_method = 'GET'
|
9
|
+
@scope = '/hello'
|
10
|
+
@prefix = '/hello/'
|
11
|
+
@suffix = '(\d+)world'
|
12
|
+
@id = :'#1'
|
13
|
+
@conv = [:to_i]
|
14
|
+
@controller = 'stub'
|
15
|
+
}
|
16
|
+
@e2 = RouteEntry.new{
|
17
|
+
@http_method = 'GET'
|
18
|
+
@scope = '/hello'
|
19
|
+
@prefix = '/hello'
|
20
|
+
@suffix = ''
|
21
|
+
@id = :'#second'
|
22
|
+
@conv = []
|
23
|
+
@controller = 'stub2'
|
24
|
+
}
|
25
|
+
@e3 = RouteEntry.new{
|
26
|
+
@http_method = 'GET'
|
27
|
+
@scope = '/a目录'
|
28
|
+
@prefix = '/a目录/'
|
29
|
+
@suffix = '(\d+)-(\d+)-(\d+)'
|
30
|
+
@id = :'#dir'
|
31
|
+
@conv = [:to_i, :to_i, :to_i]
|
32
|
+
@controller = 'stub3'
|
33
|
+
}
|
34
|
+
Ext.register_route @e1
|
35
|
+
Ext.register_route @e2
|
36
|
+
Ext.register_route @e3
|
37
|
+
end
|
38
|
+
|
39
|
+
after :all do
|
40
|
+
Ext.clear_route
|
41
|
+
end
|
42
|
+
|
43
|
+
it '#register_route sub-prefix optimization' do
|
44
|
+
rules = Ext.list_route['GET']
|
45
|
+
assert_equal 3, rules.size
|
46
|
+
|
47
|
+
assert_equal false, rules[0].first # first
|
48
|
+
assert_equal true, rules[1].first # is sub of prev
|
49
|
+
assert_equal false, rules[2].first # not sub of prev
|
50
|
+
end
|
51
|
+
|
52
|
+
it '#lookup_route' do
|
53
|
+
scope, cont, args = Ext.lookup_route 'GET', '/hello'
|
54
|
+
assert_equal @e2.scope, scope
|
55
|
+
assert_equal @e2.controller, cont
|
56
|
+
assert_equal [:'#second'], args
|
57
|
+
|
58
|
+
scope, cont, args = Ext.lookup_route 'GET', '/hello/3world'
|
59
|
+
assert_equal @e1.scope, scope
|
60
|
+
assert_equal @e1.controller, cont
|
61
|
+
assert_equal [3, :'#1'], args
|
62
|
+
|
63
|
+
scope, _ = Ext.lookup_route 'GET', '/world'
|
64
|
+
assert_equal nil, scope
|
65
|
+
|
66
|
+
scope, _, args = Ext.lookup_route 'GET', '/a目录/2013-6-1'
|
67
|
+
assert_equal [2013, 6, 1, :'#dir'], args
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/spec/hashes_spec.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
module Nyara
|
4
|
+
describe ParamHash do
|
5
|
+
it "symbol/string keys in ParamHash are the same" do
|
6
|
+
h = ParamHash.new
|
7
|
+
h[:a] = 3
|
8
|
+
assert_equal 3, h['a']
|
9
|
+
assert_equal true, h.key?(:a)
|
10
|
+
assert_equal true, h.key?('a')
|
11
|
+
assert_equal 1, h.size
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe HeaderHash do
|
16
|
+
it "ignores case in key" do
|
17
|
+
h = HeaderHash.new
|
18
|
+
h['a-bc'] = 'good'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "headerlizes key and stringify value" do
|
22
|
+
h = HeaderHash.new
|
23
|
+
h['Content-type'] = 'text/html'
|
24
|
+
h[:'content-tYpe'] = :'text/plain'
|
25
|
+
assert_equal 1, h.size
|
26
|
+
assert_equal ['Content-Type', 'text/plain'], h.to_a.first
|
27
|
+
end
|
28
|
+
|
29
|
+
class HaHash < HeaderHash
|
30
|
+
end
|
31
|
+
|
32
|
+
it "#reverse_merge! raises error if other is not HeaderHash" do
|
33
|
+
h = HeaderHash.new
|
34
|
+
h.reverse_merge! HaHash.new # :)
|
35
|
+
assert_raise ArgumentError do
|
36
|
+
h.reverse_merge!({})
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "#reverse_merge!" do
|
41
|
+
h = HeaderHash.new
|
42
|
+
g = HeaderHash.new
|
43
|
+
h['a'] = 'h'
|
44
|
+
g['a'] = 'g'
|
45
|
+
g['b'] = 'b'
|
46
|
+
h.reverse_merge! g
|
47
|
+
assert_equal 2, h.size
|
48
|
+
assert_equal 'h', h['a']
|
49
|
+
assert_equal 'b', h['b']
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe ConfigHash do
|
54
|
+
it "deep key assignment" do
|
55
|
+
h = ConfigHash.new
|
56
|
+
h['a', 'deep', 'key1'] = 'value1'
|
57
|
+
h['a', 'deep', :key2] = 'value2'
|
58
|
+
assert_equal 'value1', h['a', 'deep', :key1]
|
59
|
+
assert_equal 'value2', h['a']['deep']['key2']
|
60
|
+
end
|
61
|
+
|
62
|
+
it "works when last available key exists as other hash type" do
|
63
|
+
h = ConfigHash.new
|
64
|
+
other_h = {}
|
65
|
+
h['a'] = other_h
|
66
|
+
h['a', 'b'] = 3
|
67
|
+
assert_equal 3, h['a', 'b']
|
68
|
+
assert_equal other_h.object_id, h['a'].object_id
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
class FooController < Nyara::Controller
|
4
|
+
meta '#index'
|
5
|
+
get '/%d' do |id|
|
6
|
+
end
|
7
|
+
|
8
|
+
class BarController < Nyara::Controller
|
9
|
+
meta '#index'
|
10
|
+
get '/' do
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class BazController < Nyara::Controller
|
15
|
+
set_name 'baz'
|
16
|
+
|
17
|
+
meta '#index'
|
18
|
+
get '/%d' do |id|
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Nyara
|
24
|
+
describe [Controller, Route] do
|
25
|
+
before :all do
|
26
|
+
Route.clear
|
27
|
+
Config.configure do
|
28
|
+
set 'host', 'yavaeye.com'
|
29
|
+
map '/', 'foo'
|
30
|
+
map '/bar-prefix', 'foo_controller::bar'
|
31
|
+
map '/baz-prefix', 'foo_controller::baz'
|
32
|
+
end
|
33
|
+
Route.compile
|
34
|
+
end
|
35
|
+
|
36
|
+
context '#path_for' do
|
37
|
+
it "local query" do
|
38
|
+
c = FooController.new :stub_request
|
39
|
+
assert_equal '/12', c.path_for('#index', 12)
|
40
|
+
assert_raise ArgumentError do
|
41
|
+
c.path_for '#index'
|
42
|
+
end
|
43
|
+
assert_raise ArgumentError do
|
44
|
+
c.path_for('#index', 'a')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "global query" do
|
49
|
+
c = FooController::BarController.new :stub_request
|
50
|
+
assert_equal '/bar-prefix/', c.path_for('foo_controller::bar#index')
|
51
|
+
assert_equal '/baz-prefix/1', c.path_for('baz#index', 1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "generates for nested query" do
|
55
|
+
pending
|
56
|
+
end
|
57
|
+
|
58
|
+
it "perserves _method query" do
|
59
|
+
pending
|
60
|
+
end
|
61
|
+
|
62
|
+
it "appends format and query" do
|
63
|
+
c = FooController.new :stub_request
|
64
|
+
generated = c.path_for '#index', 1, format: 'js', 'utm_source' => 'a spam'
|
65
|
+
assert_equal "/1.js?utm_source=a+spam", generated
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context '#url_for' do
|
70
|
+
it "works" do
|
71
|
+
c = FooController::BazController.new :stub_request
|
72
|
+
assert_equal '//yavaeye.com/baz-prefix/1', c.url_for('#index', 1)
|
73
|
+
assert_equal 'https://localhost:4567/1', c.url_for('foo#index', 1, scheme: 'https', host: 'localhost:4567')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
module Nyara
|
4
|
+
describe [Controller, Request] do
|
5
|
+
class DelegateController < Controller
|
6
|
+
end
|
7
|
+
|
8
|
+
before :all do
|
9
|
+
Ext.set_skip_on_url true
|
10
|
+
end
|
11
|
+
|
12
|
+
after :all do
|
13
|
+
Ext.set_skip_on_url false
|
14
|
+
end
|
15
|
+
|
16
|
+
before :each do
|
17
|
+
@client, @server = Socket.pair :UNIX, :STREAM
|
18
|
+
Ext.set_nonblock @server.fileno
|
19
|
+
@request = Ext.handle_request @server.fileno
|
20
|
+
Ext.set_request_attrs @request, {
|
21
|
+
method_num: HTTP_METHODS['GET'],
|
22
|
+
path: '/search',
|
23
|
+
param: ParamHash.new.tap{|h| h['q'] = 'nyara' },
|
24
|
+
fiber: Fiber.new{},
|
25
|
+
scope: '/scope',
|
26
|
+
header: HeaderHash.new.tap{|h| h['Accept'] = 'en-US' }
|
27
|
+
# ext: nil
|
28
|
+
# response_header:
|
29
|
+
# response_header_extra_lines:
|
30
|
+
}
|
31
|
+
@c = DelegateController.new @request
|
32
|
+
end
|
33
|
+
|
34
|
+
it "#content_type" do
|
35
|
+
@c.content_type :js
|
36
|
+
assert_equal 'application/javascript', @request.response_content_type
|
37
|
+
end
|
38
|
+
|
39
|
+
it "#status" do
|
40
|
+
assert_raise ArgumentError do
|
41
|
+
@c.status 1000
|
42
|
+
end
|
43
|
+
@c.status 404
|
44
|
+
assert_equal 404, @request.status
|
45
|
+
end
|
46
|
+
|
47
|
+
it "request header" do
|
48
|
+
assert_equal 'en-US', @c.header['accept']
|
49
|
+
end
|
50
|
+
|
51
|
+
it "set response header and send" do
|
52
|
+
pending
|
53
|
+
@c.set_header
|
54
|
+
@c.add_header_line
|
55
|
+
@c.send_header
|
56
|
+
@client
|
57
|
+
end
|
58
|
+
|
59
|
+
it "set / delete / clear cookie" do
|
60
|
+
pending
|
61
|
+
end
|
62
|
+
|
63
|
+
it "#session" do
|
64
|
+
pending
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
module Nyara
|
4
|
+
describe Request do
|
5
|
+
before :all do
|
6
|
+
Ext.set_skip_on_url true
|
7
|
+
end
|
8
|
+
|
9
|
+
after :all do
|
10
|
+
Ext.set_skip_on_url false
|
11
|
+
end
|
12
|
+
|
13
|
+
before :each do
|
14
|
+
@server, @client = Socket.pair :UNIX, :STREAM, 0
|
15
|
+
Ext.set_nonblock @server.fileno
|
16
|
+
Ext.set_nonblock @client.fileno
|
17
|
+
@request = Ext.handle_request @server.fileno
|
18
|
+
@request_attrs = {
|
19
|
+
method_num: HTTP_METHODS['GET'],
|
20
|
+
path: '/',
|
21
|
+
param: HeaderHash.new.tap{|h| h['id'] = 1 },
|
22
|
+
fiber: nil,
|
23
|
+
scope: '/',
|
24
|
+
ext: nil
|
25
|
+
}
|
26
|
+
set_request_attrs
|
27
|
+
end
|
28
|
+
|
29
|
+
context "#scheme detect by forwarded.." do
|
30
|
+
it "ssl" do
|
31
|
+
@request.header['X-Forwarded-Ssl'] = 'on'
|
32
|
+
assert_equal 'https', @request.scheme
|
33
|
+
end
|
34
|
+
|
35
|
+
it "scheme" do
|
36
|
+
@request.header['X-Forwarded-Scheme'] = 'ical'
|
37
|
+
assert_equal 'ical', @request.scheme
|
38
|
+
end
|
39
|
+
|
40
|
+
it "protocol" do
|
41
|
+
@request.header['X-Forwarded-Proto'] = 'https,http'
|
42
|
+
assert_equal 'https', @request.scheme
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "#domain and #port" do
|
47
|
+
@request.header['Host'] = "yavaeye.com:3000"
|
48
|
+
assert_equal 'yavaeye.com', @request.domain
|
49
|
+
assert_equal 3000, @request.port
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_request_attrs
|
53
|
+
Ext.set_request_attrs @request, @request_attrs
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
module Nyara
|
4
|
+
describe RouteEntry do
|
5
|
+
it "#set_accept_exts" do
|
6
|
+
r = RouteEntry.new
|
7
|
+
r.set_accept_exts ['html', :js]
|
8
|
+
assert_equal [%w"text html html", %w"application javascript js"], r.accept_mimes
|
9
|
+
assert_equal ({'html'=>true, 'js'=>true}), r.accept_exts
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/spec/route_spec.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
module Nyara
|
4
|
+
describe Route do
|
5
|
+
# fixme: ugly code
|
6
|
+
it "#process" do
|
7
|
+
entries1 = [
|
8
|
+
RouteEntry.new{
|
9
|
+
@http_method = 'GET',
|
10
|
+
@path = '/hello/%f',
|
11
|
+
@id = :'#hello_f'
|
12
|
+
},
|
13
|
+
RouteEntry.new{
|
14
|
+
@http_method = 'POST',
|
15
|
+
@path = '/%s/%u-%d',
|
16
|
+
@id = :'#post'
|
17
|
+
}
|
18
|
+
]
|
19
|
+
entries2 = [
|
20
|
+
RouteEntry.new{
|
21
|
+
@http_method = 'GET',
|
22
|
+
@path = '/',
|
23
|
+
@id = :'#hel'
|
24
|
+
}
|
25
|
+
]
|
26
|
+
entries3 = [
|
27
|
+
RouteEntry.new{
|
28
|
+
@http_method = 'GET',
|
29
|
+
@path = '/%s',
|
30
|
+
@id = :'#ello_s'
|
31
|
+
}
|
32
|
+
]
|
33
|
+
|
34
|
+
preprocessed_rules = [
|
35
|
+
['/', 'Stub1', entries1],
|
36
|
+
['/hel', 'Stub2', entries2],
|
37
|
+
['/ello', 'Stub3', entries3]
|
38
|
+
]
|
39
|
+
|
40
|
+
rules = Route.process preprocessed_rules
|
41
|
+
e_prefices, e_scopes, e_ids = [
|
42
|
+
['/hello/', '/', :'#hello_f'],
|
43
|
+
['/hel', '/hel', :'#hel'],
|
44
|
+
['/ello/', '/ello', :'#ello_s'],
|
45
|
+
['/', '/', :'#post']
|
46
|
+
].transpose
|
47
|
+
|
48
|
+
assert_equal e_prefices, rules.map(&:prefix)
|
49
|
+
assert_equal e_scopes, rules.map(&:scope)
|
50
|
+
assert_equal e_ids, rules.map(&:id)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "#compile_re" do
|
54
|
+
re, conv = Route.compile_re '%s/%u/%d/%f/%x'
|
55
|
+
assert_equal [:to_s, :to_i, :to_i, :to_f, :hex], conv
|
56
|
+
s = '1/2/-3/4.5/F'
|
57
|
+
assert_equal [s, *s.split('/')], s.match(Regexp.new re).to_a
|
58
|
+
|
59
|
+
re, conv = Route.compile_re '/'
|
60
|
+
assert_equal '^/$', re
|
61
|
+
assert_equal [], conv
|
62
|
+
end
|
63
|
+
|
64
|
+
it "#compile_re with utf-8 chars" do
|
65
|
+
re, conv = Route.compile_re '/目录/%da/也可以'
|
66
|
+
assert_equal [:to_i], conv
|
67
|
+
s = "/目录/12a/也可以"
|
68
|
+
assert_equal [s, '12'], s.match(Regexp.new re).to_a
|
69
|
+
end
|
70
|
+
|
71
|
+
it "#analyse_path" do
|
72
|
+
r = Route.analyse_path '/hello/%d-world%u/%s/'
|
73
|
+
assert_equal ['/hello/', '%d-world%u/%s'], r
|
74
|
+
|
75
|
+
prefix, suffix = Route.analyse_path '/hello'
|
76
|
+
assert_equal '/hello', prefix
|
77
|
+
assert_equal nil, suffix
|
78
|
+
|
79
|
+
prefix, suffix = Route.analyse_path '/'
|
80
|
+
assert_equal '/', prefix
|
81
|
+
assert_equal nil, suffix
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
module Nyara
|
4
|
+
describe Session do
|
5
|
+
context "no cipher" do
|
6
|
+
before :all do
|
7
|
+
Config['session', 'cipher_key'] = nil
|
8
|
+
Session.init
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should encode and decode" do
|
12
|
+
cookie = {}
|
13
|
+
session = {'hello' => 'world'}
|
14
|
+
Session.encode session, cookie
|
15
|
+
|
16
|
+
assert_includes cookie[Session.name], 'world'
|
17
|
+
|
18
|
+
session2 = Session.decode cookie
|
19
|
+
assert_equal 'world', session2[:hello]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "drops bad signature" do
|
23
|
+
cookie = {}
|
24
|
+
session = {'hello' => 'world'}
|
25
|
+
Session.encode session, cookie
|
26
|
+
|
27
|
+
cookie[Session.name].sub!(/\w/, &:swapcase)
|
28
|
+
|
29
|
+
session = Session.decode cookie
|
30
|
+
assert_empty session
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with cipher" do
|
35
|
+
before :all do
|
36
|
+
Config['session', 'cipher_key'] = "some cipher key"
|
37
|
+
Session.init
|
38
|
+
end
|
39
|
+
|
40
|
+
it "encode and decode" do
|
41
|
+
cookie = {}
|
42
|
+
session = {'hello' => 'world'}
|
43
|
+
Session.encode session, cookie
|
44
|
+
|
45
|
+
assert_not_includes cookie[Session.name], 'world'
|
46
|
+
|
47
|
+
session2 = Session.decode cookie
|
48
|
+
assert_equal 'world', session2[:hello]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "cipher should not be pure" do
|
52
|
+
message = 'OCB is by far the best mode, as it allows encryption and authentication in a single pass. However there are patents on it in USA.'
|
53
|
+
r1 = Session.cipher message
|
54
|
+
r2 = Session.cipher message
|
55
|
+
assert_not_equal r1, r2
|
56
|
+
end
|
57
|
+
|
58
|
+
it "decipher returns blank str when message too short" do
|
59
|
+
r = Session.decipher Base64.urlsafe_encode64 'short one'
|
60
|
+
assert_empty r
|
61
|
+
r = Session.decipher Base64.urlsafe_encode64 's' * (256/8)
|
62
|
+
assert_empty r
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative "../lib/nyara/nyara"
|
2
|
+
require 'rspec/core'
|
3
|
+
require 'rspec/mocks'
|
4
|
+
require 'rspec/autorun'
|
5
|
+
require "pry"
|
6
|
+
require "slim"
|
7
|
+
require "erb"
|
8
|
+
require "haml"
|
9
|
+
require "liquid"
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.expect_with :stdlib
|
13
|
+
if config.formatters.first.class.to_s =~ /TextMate/
|
14
|
+
def puts *xs
|
15
|
+
xs.each do |x|
|
16
|
+
$stdout.puts "<pre style='word-wrap:break-word;word-break:break-all;'>#{CGI.escape_html x.to_s}</pre>"
|
17
|
+
end
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def print *xs
|
22
|
+
$stdout.print "<span style='word-wrap:break-word;word-break:break-all;'>"
|
23
|
+
xs.each do |x|
|
24
|
+
$stdout.print CGI.escape_html x.to_s
|
25
|
+
end
|
26
|
+
$stdout.print "</span>"
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def p *xs
|
31
|
+
xs.each do |x|
|
32
|
+
$stdout.puts "<pre style='word-wrap:break-word;word-break:break-all;'>#{CGI.escape_html x.inspect}</pre>"
|
33
|
+
end
|
34
|
+
xs
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'pp'
|
38
|
+
module Kernel
|
39
|
+
def pp obj
|
40
|
+
s = CGI.escape_html(PP.pp obj, '')
|
41
|
+
$stdout.puts "<pre style='word-wrap:break-word;word-break:break-all;'>#{s}</pre>"
|
42
|
+
obj
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
configure do
|
49
|
+
set :env, 'test'
|
50
|
+
end
|
51
|
+
|
52
|
+
# todo a test helper to compile routes after app loaded
|
data/spec/view_spec.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
class RenderableMock
|
4
|
+
include Nyara::Renderable
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@result = ''
|
8
|
+
end
|
9
|
+
attr_reader :result
|
10
|
+
|
11
|
+
def send_chunk data
|
12
|
+
@result << data
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Nyara
|
17
|
+
describe [View, Renderable] do
|
18
|
+
before :all do
|
19
|
+
Config['views'] = __dir__ + '/views'
|
20
|
+
View.init
|
21
|
+
end
|
22
|
+
|
23
|
+
def render *xs
|
24
|
+
@instance = RenderableMock.new
|
25
|
+
view = View.new @instance, *xs
|
26
|
+
Fiber.new{ view.render }.resume
|
27
|
+
end
|
28
|
+
|
29
|
+
it "inline render with locals" do
|
30
|
+
render nil, nil, {a: 3}, erb: '<%= a %>'
|
31
|
+
assert_equal '3', @instance.result
|
32
|
+
end
|
33
|
+
|
34
|
+
it "file render" do
|
35
|
+
render 'show', nil, {a: 3}, {}
|
36
|
+
assert_equal '3', @instance.result
|
37
|
+
end
|
38
|
+
|
39
|
+
it "file render with layouts" do
|
40
|
+
render 'show', 'layout', {a: 3}, {}
|
41
|
+
assert_equal "<html>3</html>\n", @instance.result
|
42
|
+
end
|
43
|
+
|
44
|
+
it "raises for ambiguous template" do
|
45
|
+
assert_raise ArgumentError do
|
46
|
+
render 'edit', nil, nil, {}
|
47
|
+
end
|
48
|
+
render 'edit.slim', nil, nil, {}
|
49
|
+
assert_equal "<div>slim:edit</div>", @instance.result.gsub(/\s/, '')
|
50
|
+
render 'edit.haml', nil, nil, {}
|
51
|
+
assert_equal "<div>haml:edit</div>", @instance.result.gsub(/\s/, '')
|
52
|
+
end
|
53
|
+
|
54
|
+
context "fallback to tilt" do
|
55
|
+
it "inline render" do
|
56
|
+
render nil, nil, {a: 3}, {liquid: '{{a}}'}
|
57
|
+
assert_equal '3', @instance.result
|
58
|
+
end
|
59
|
+
|
60
|
+
it "forbids tilt layout" do
|
61
|
+
assert_raise RuntimeError do
|
62
|
+
render nil, 'invalid_layout', nil, {liquid: 'page'}
|
63
|
+
end
|
64
|
+
assert_raise RuntimeError do
|
65
|
+
render 'show', ['invalid_layout'], nil, {}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "allows tilt page with stream-friendly layout" do
|
70
|
+
render nil, 'layout', nil, {liquid: 'page'}
|
71
|
+
assert_equal "<html>page</html>\n", @instance.result
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it "stream render" do
|
76
|
+
@instance = RenderableMock.new
|
77
|
+
view = View.new @instance, nil, 'layout', nil, {erb: '<% 3.times do |i| %><%= i %><% Fiber.yield %><% end %>'}
|
78
|
+
v = view.stream
|
79
|
+
v.resume
|
80
|
+
assert_equal "<html>0", @instance.result
|
81
|
+
v.resume
|
82
|
+
assert_equal "<html>01", @instance.result
|
83
|
+
Fiber.new{ v.end }.resume
|
84
|
+
assert_equal "<html>012</html>\n", @instance.result
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "../lib/nyara/nyara"
|
2
|
+
include Nyara
|
3
|
+
require "benchmark"
|
4
|
+
|
5
|
+
def cookie1 s
|
6
|
+
res = ParamHash.new
|
7
|
+
s.split(/[,;] */n).reverse_each do |seg|
|
8
|
+
Ext.parse_url_encoded_seg res, seg, false
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def cookie2 s
|
13
|
+
res = ParamHash.new
|
14
|
+
Ext.parse_cookie res, s
|
15
|
+
end
|
16
|
+
|
17
|
+
history = CGI.escape '历史'
|
18
|
+
s = "pgv_pvi; pgv_si=; pgv_pvi=som; sid=1d6c75f0 ; PLHistory=<#{history}>;"
|
19
|
+
|
20
|
+
puts Benchmark.measure{ 1000.times{cookie1 s} }
|
21
|
+
puts Benchmark.measure{ 1000.times{cookie2 s} }
|
22
|
+
# cookie2 should be faster
|