manveru-innate 2009.02.25 → 2009.03.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/CHANGELOG +383 -0
  2. data/MANIFEST +17 -8
  3. data/README.md +222 -136
  4. data/Rakefile +7 -2
  5. data/example/provides.rb +28 -0
  6. data/innate.gemspec +19 -10
  7. data/lib/innate/action.rb +21 -47
  8. data/lib/innate/adapter.rb +65 -56
  9. data/lib/innate/cache.rb +16 -8
  10. data/lib/innate/dynamap.rb +39 -29
  11. data/lib/innate/helper/aspect.rb +60 -0
  12. data/lib/innate/helper/cgi.rb +2 -0
  13. data/lib/innate/helper/link.rb +43 -11
  14. data/lib/innate/helper/partial.rb +6 -5
  15. data/lib/innate/helper.rb +10 -13
  16. data/lib/innate/log/hub.rb +1 -0
  17. data/lib/innate/log.rb +3 -6
  18. data/lib/{rack → innate}/middleware_compiler.rb +19 -12
  19. data/lib/innate/mock.rb +3 -2
  20. data/lib/innate/node.rb +573 -179
  21. data/lib/innate/options/dsl.rb +46 -6
  22. data/lib/innate/options/stub.rb +7 -0
  23. data/lib/innate/options.rb +14 -93
  24. data/lib/innate/request.rb +21 -7
  25. data/lib/innate/response.rb +12 -0
  26. data/lib/innate/route.rb +2 -3
  27. data/lib/innate/session.rb +37 -20
  28. data/lib/innate/spec.rb +4 -0
  29. data/lib/innate/state/fiber.rb +14 -7
  30. data/lib/innate/state/thread.rb +10 -2
  31. data/lib/innate/state.rb +8 -11
  32. data/lib/innate/traited.rb +14 -6
  33. data/lib/innate/trinity.rb +0 -4
  34. data/lib/innate/version.rb +1 -1
  35. data/lib/innate/view/erb.rb +4 -2
  36. data/lib/innate/view/none.rb +2 -2
  37. data/lib/innate/view.rb +14 -21
  38. data/lib/innate.rb +49 -30
  39. data/spec/helper.rb +8 -0
  40. data/spec/innate/action/layout.rb +9 -6
  41. data/spec/innate/cache/common.rb +3 -3
  42. data/spec/innate/helper/aspect.rb +3 -5
  43. data/spec/innate/helper/flash.rb +1 -1
  44. data/spec/innate/helper/link.rb +45 -2
  45. data/spec/innate/helper/partial.rb +34 -10
  46. data/spec/innate/helper/view/loop.erb +1 -1
  47. data/spec/innate/helper/view/recursive.erb +1 -1
  48. data/spec/innate/node/mapping.rb +37 -0
  49. data/spec/innate/node/node.rb +142 -0
  50. data/spec/innate/node/resolve.rb +82 -0
  51. data/spec/innate/node/{another_layout → view/another_layout}/another_layout.erb +0 -0
  52. data/spec/innate/node/{bar.html → view/bar.erb} +0 -0
  53. data/spec/innate/node/{foo.html.erb → view/foo.html.erb} +0 -0
  54. data/spec/innate/node/{only_view.html → view/only_view.erb} +0 -0
  55. data/spec/innate/node/view/with_layout.erb +1 -0
  56. data/spec/innate/node/wrap_action_call.rb +83 -0
  57. data/spec/innate/options.rb +28 -6
  58. data/spec/innate/provides/list.html.erb +1 -0
  59. data/spec/innate/provides/list.txt.erb +1 -0
  60. data/spec/innate/provides.rb +99 -0
  61. data/spec/innate/request.rb +23 -10
  62. data/spec/innate/route.rb +2 -4
  63. data/spec/innate/session.rb +1 -1
  64. data/spec/innate/state/fiber.rb +57 -0
  65. data/spec/innate/state/thread.rb +40 -0
  66. metadata +20 -11
  67. data/lib/rack/reloader.rb +0 -192
  68. data/spec/innate/node/with_layout.erb +0 -3
  69. data/spec/innate/node.rb +0 -224
@@ -0,0 +1,142 @@
1
+ require 'spec/helper'
2
+
3
+ Innate.options.merge!(:views => 'view', :layouts => 'view')
4
+
5
+ class SpecNode
6
+ Innate.node('/')
7
+ provide(:html, :ERB)
8
+ provide(:erb, :None)
9
+
10
+ def foo; end
11
+ def bar; end
12
+ def one(arg) end
13
+ def two(arg1, arg2) end
14
+ def more(*args) end
15
+ def default(arg = nil) end
16
+ end
17
+
18
+ class SpecNodeProvide
19
+ Innate.node('/provide')
20
+
21
+ provide(:html, :ERB)
22
+ provide(:erb, :None)
23
+
24
+ def foo
25
+ '<%= 21 * 2 %>'
26
+ end
27
+
28
+ def bar
29
+ '<%= 84 / 2 %>'
30
+ end
31
+ end
32
+
33
+ class SpecNodeProvideTemplate
34
+ Innate.node('/provide_template')
35
+
36
+ provide :html, :ERB
37
+ provide :erb, :None
38
+
39
+ map_views '/'
40
+ end
41
+
42
+ class SpecNodeSub < SpecNode
43
+ map '/sub'
44
+
45
+ def bar(arg) end
46
+ end
47
+
48
+ class SpecNodeWithLayout < SpecNodeProvide
49
+ map '/layout'
50
+ layout 'with_layout'
51
+
52
+ map_layouts '/'
53
+ end
54
+
55
+ class SpecNodeWithLayoutView < SpecNodeProvide
56
+ map '/another_layout'
57
+ layout 'another_layout'
58
+
59
+ map_views 'node/another_layout'
60
+ end
61
+
62
+ class SpecNodeWithLayoutMethod < SpecNodeProvide
63
+ map '/layout_method'
64
+ layout 'layout_method'
65
+
66
+ def layout_method
67
+ '<div class="content"><%= @content %></div>'
68
+ end
69
+ end
70
+
71
+ class SpecNodeIndex
72
+ Innate.node('/spec_index')
73
+
74
+ def index
75
+ "I have no parameters"
76
+ end
77
+ end
78
+
79
+ class SpecNodeAliasView < SpecNodeProvideTemplate
80
+ map '/alias_view'
81
+ map_views '/'
82
+
83
+ alias_view :aliased, :bar
84
+ end
85
+
86
+ describe 'Innate::Node' do
87
+ behaves_like :mock
88
+
89
+ should 'respond with 404 if no action was found' do
90
+ got = Innate::Mock.get('/does_not_exist')
91
+ got.status.should == 404
92
+ got.body.should == 'No action found at: "/does_not_exist"'
93
+ got['Content-Type'].should == 'text/plain'
94
+ end
95
+
96
+ should 'wrap with layout' do
97
+ got = Innate::Mock.get('/layout/bar')
98
+ got.status.should == 200
99
+ got.body.should == %(<div class="content">42</div>\n)
100
+ got['Content-Type'].should == 'text/html'
101
+ end
102
+
103
+ should 'find layout with view_root' do
104
+ got = Innate::Mock.get('/another_layout/bar')
105
+ got.status.should == 200
106
+ got.body.should == %(<div class="content">\n 42\n</div>\n)
107
+ got['Content-Type'].should == 'text/html'
108
+ end
109
+
110
+ should 'find layout from method' do
111
+ got = Innate::Mock.get('/layout_method/bar')
112
+ got.status.should == 200
113
+ got.body.should == %(<div class="content">42</div>)
114
+ got['Content-Type'].should == 'text/html'
115
+ end
116
+
117
+ should 'not get an action with wrong parameters' do
118
+ got = Innate::Mock.get('/spec_index/bar')
119
+ got.status.should == 404
120
+ got.body.should == 'No action found at: "/bar"'
121
+ end
122
+
123
+ should 'get an action view if there is no method' do
124
+ got = Innate::Mock.get('/provide_template/only_view')
125
+ got.status.should == 200
126
+ got.body.strip.should == "Only template"
127
+ got['Content-Type'].should == 'text/html'
128
+ end
129
+
130
+ should 'not get an action view with params if there is no method' do
131
+ got = Innate::Mock.get('/provide_template/only_view/param')
132
+ got.status.should == 404
133
+ got.body.strip.should == 'No action found at: "/only_view/param"'
134
+ end
135
+
136
+ should 'use alias_view' do
137
+ got = get('/alias_view/aliased')
138
+ got.status.should == 200
139
+ got.body.strip.should == "<h1>Hello, World!</h1>"
140
+ got['Content-Type'].should == 'text/html'
141
+ end
142
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecNodeResolve
4
+ Innate.node('/')
5
+
6
+ def foo; end
7
+ def bar; end
8
+ def one(arg) end
9
+ def two(arg1, arg2) end
10
+ def more(*args) end
11
+ def default(arg = nil) end
12
+ end
13
+
14
+ class SpecNodeResolveSub < SpecNodeResolve
15
+ map '/sub'
16
+
17
+ def bar(arg) end
18
+ end
19
+
20
+ class SpecNodeResolveIndex
21
+ Innate.node('/arg')
22
+
23
+ def index(arg) end
24
+ end
25
+
26
+ describe 'Node.resolve' do
27
+ def compare(url, hash)
28
+ result = SpecNodeResolve.resolve(url)
29
+ result.should.not.be.nil
30
+ hash.each do |key, value|
31
+ result[key.to_s].should == value
32
+ end
33
+ end
34
+
35
+ should 'resolve actions with methods' do
36
+ SpecNodeResolve.resolve('/').should.be.nil
37
+ SpecNodeResolve.resolve('/index').should.be.nil
38
+
39
+ compare '/foo', :method => 'foo', :params => []
40
+ SpecNodeResolve.resolve('/foo/one/two').should.be.nil
41
+
42
+ compare '/bar', :method => 'bar', :params => []
43
+ SpecNodeResolve.resolve('/bar/one').should.be.nil
44
+
45
+ SpecNodeResolve.resolve('/one').should.be.nil
46
+ compare '/one/1', :method => 'one', :params => ['1']
47
+ SpecNodeResolve.resolve('/one/1/2').should.be.nil
48
+ SpecNodeResolve.resolve('/one/1/2/3').should.be.nil
49
+
50
+ SpecNodeResolve.resolve('/two').should.be.nil
51
+ SpecNodeResolve.resolve('/two/1').should.be.nil
52
+ compare '/two/1/2', :method => 'two', :params => %w[1 2]
53
+ SpecNodeResolve.resolve('/two/1/2/3').should.be.nil
54
+
55
+ compare '/more', :method => 'more', :params => []
56
+ compare '/more/1', :method => 'more', :params => %w[1]
57
+ compare '/more/1/2', :method => 'more', :params => %w[1 2]
58
+ compare '/more/1/2/3', :method => 'more', :params => %w[1 2 3]
59
+
60
+ compare '/default', :method => 'default', :params => []
61
+ compare '/default/1', :method => 'default', :params => %w[1]
62
+
63
+ # NOTE: these are actually bound to fail when called, but we cannot
64
+ # introspect enough to anticipate this failure
65
+ compare '/default/1/2', :method => 'default', :params => %w[1 2]
66
+ compare '/default/1/2/3', :method => 'default', :params => %w[1 2 3]
67
+ end
68
+
69
+ should 'inherit action methods from superclasses' do
70
+ SpecNodeResolveSub.resolve('/foo').should.not.be.nil
71
+ SpecNodeResolveSub.resolve('/foo/one/two').should.be.nil
72
+ end
73
+
74
+ should 'select correct method from subclasses' do
75
+ SpecNodeResolveSub.resolve('/bar/one').should.not.be.nil
76
+ SpecNodeResolveSub.resolve('/bar').should.be.nil
77
+ end
78
+
79
+ it "doesn't select index as action with index parameter if arity is 1" do
80
+ SpecNodeResolveIndex.resolve('/index').should.be.nil
81
+ end
82
+ end
File without changes
@@ -0,0 +1 @@
1
+ <div class="content"><%= @content %></div>
@@ -0,0 +1,83 @@
1
+ require 'spec/helper'
2
+
3
+ SPEC_WRAP_LOG = []
4
+
5
+ class SpecWrapActionCall
6
+ Innate.node '/'
7
+
8
+ def first; end
9
+ def second; end
10
+ def third; end
11
+
12
+ private
13
+
14
+ def wrap_before(action)
15
+ SPEC_WRAP_LOG << [:before, action.name]
16
+ yield
17
+ end
18
+
19
+ def wrap_after(action)
20
+ SPEC_WRAP_LOG << [:after, action.name]
21
+ yield
22
+ end
23
+ end
24
+
25
+ class SpecWrapActionCallStop
26
+ Innate.node '/stop'
27
+
28
+ def index; 'Hello'; end
29
+
30
+ def wrap_pass(action)
31
+ yield
32
+ end
33
+
34
+ def wrap_stop(action)
35
+ 'No Hello'
36
+ end
37
+ end
38
+
39
+
40
+ describe 'Node#wrap_action_call' do
41
+ behaves_like :mock
42
+
43
+ it 'executes our wrapper' do
44
+ SPEC_WRAP_LOG.clear
45
+ SpecWrapActionCall.add_action_wrapper(2.0, :wrap_after)
46
+
47
+ get('/first')
48
+ SPEC_WRAP_LOG.should == [[:after, 'first']]
49
+
50
+ get('/second')
51
+ SPEC_WRAP_LOG.should == [[:after, 'first'], [:after, 'second']]
52
+
53
+ get('/third')
54
+ SPEC_WRAP_LOG.should == [[:after, 'first'], [:after, 'second'], [:after, 'third']]
55
+ end
56
+
57
+ it 'executes wrappers in correct order' do
58
+ SPEC_WRAP_LOG.clear
59
+ SpecWrapActionCall.add_action_wrapper(1.0, :wrap_before)
60
+
61
+ get('/first')
62
+ SPEC_WRAP_LOG.should == [[:before, 'first'], [:after, 'first']]
63
+
64
+ get('/second')
65
+ SPEC_WRAP_LOG.should == [
66
+ [:before, 'first'], [:after, 'first'],
67
+ [:before, 'second'], [:after, 'second']]
68
+
69
+ get('/third')
70
+ SPEC_WRAP_LOG.should == [
71
+ [:before, 'first'], [:after, 'first'],
72
+ [:before, 'second'], [:after, 'second'],
73
+ [:before, 'third'], [:after, 'third']]
74
+ end
75
+
76
+ it 'stops in the chain when not yielded' do
77
+ SpecWrapActionCallStop.add_action_wrapper(1.0, :wrap_pass)
78
+ get('/stop').body.should == 'Hello'
79
+
80
+ SpecWrapActionCallStop.add_action_wrapper(2.0, :wrap_stop)
81
+ get('/stop').body.should == 'No Hello'
82
+ end
83
+ end
@@ -57,19 +57,41 @@ describe Options do
57
57
  @options.deep.port.should == 7000
58
58
  end
59
59
 
60
+ should '#set_value to set a nested value directly' do
61
+ @options.set_value([:deep, :down, :me], 'me deep down')
62
+ @options.deep.down.me.should == 'me deep down'
63
+ end
64
+
60
65
  should 'merge! existing options with other Enumerable' do
61
66
  @options.merge!(:port => 4000, :name => 'feagliir')
62
67
  @options.port.should == 4000
63
68
  @options.name.should == 'feagliir'
64
69
  end
65
70
 
66
- should 'Be Enumerable' do
67
- keys, values = [], []
71
+ should 'iterate via #each_pair' do
72
+ given_keys = [:deep, :name, :port]
73
+ given_values = [@options[:deep], @options[:name], @options[:port]]
74
+
75
+ @options.each_pair do |key, value|
76
+ given_keys.delete(key)
77
+ given_values.delete(value)
78
+ end
79
+
80
+ given_keys.should.be.empty
81
+ given_values.should.be.empty
82
+ end
83
+
84
+ should 'iterate via #each_option' do
85
+ given_keys = [:deep, :name, :port]
86
+ given_values = [@options.get(:deep), @options.get(:name), @options.get(:port)]
68
87
 
69
- @options.each{|k, v| keys << k; values << v }
88
+ @options.each_option do |key, option|
89
+ given_keys.delete(key)
90
+ given_values.delete(option)
91
+ end
70
92
 
71
- keys.compact.sort_by{|k| k.to_s }.should == [:deep, :name, :port]
72
- values.compact.size.should == 3
93
+ given_keys.should.be.empty
94
+ given_values.should.be.empty
73
95
  end
74
96
 
75
97
  should "raise when trying to assign to key that doesn't exist" do
@@ -80,7 +102,7 @@ describe Options do
80
102
  require 'pp'
81
103
  p = PP.new
82
104
  @options.pretty_print(p)
83
- p.output.should =~ /:value=>4000/
105
+ p.output.should =~ /:value=>:mom/
84
106
  end
85
107
 
86
108
  should 'trigger block when option is changed' do
@@ -0,0 +1 @@
1
+ <ul><% @users.each do |user| %><li><%= user %></li><% end %></ul>
@@ -0,0 +1 @@
1
+ <% @users.each do |user| %><%= "#{user}\n" %><% end %>
@@ -0,0 +1,99 @@
1
+ begin
2
+ require 'json'
3
+ rescue LoadError
4
+ exit
5
+ end
6
+
7
+ require 'spec/helper'
8
+ require 'yaml'
9
+
10
+ Innate.options.merge!(:views => 'provides', :layouts => 'provides')
11
+
12
+ class SpecNodeProvides
13
+ Innate.node '/'
14
+
15
+ provide(:html, :None)
16
+ provide(:yaml, :type => 'text/yaml'){|a,s| s.to_yaml }
17
+ provide(:json, :type => 'application/json'){|a,s| s.to_json }
18
+
19
+ def object
20
+ {'intro' => 'Hello, World!'}
21
+ end
22
+
23
+ def string
24
+ 'Just 42'
25
+ end
26
+ end
27
+
28
+ class SpecNodeProvidesTemplates
29
+ Innate.node '/template'
30
+ map_views '/'
31
+
32
+ provide(:yaml, :type => 'text/yaml'){|a,s| s.to_yaml }
33
+ provide(:json, :type => 'application/json'){|a,s| s.to_json }
34
+ provide(:txt, :engine => :ERB, :type => 'text/plain')
35
+
36
+ def list
37
+ @users = %w[starbucks apollo athena]
38
+ end
39
+ end
40
+
41
+ shared :assert_wish do
42
+ def assert_wish(uri, body, content_type)
43
+ got = get(uri)
44
+ got.status.should == 200
45
+ got.body.strip.should == body.strip
46
+ got['Content-Type'].should == content_type
47
+ end
48
+ end
49
+
50
+ describe 'Content representation' do
51
+ describe 'without template' do
52
+ behaves_like :mock, :assert_wish
53
+
54
+ it 'provides yaml for an object' do
55
+ assert_wish('/object.yaml', {'intro' => 'Hello, World!'}.to_yaml, 'text/yaml')
56
+ end
57
+
58
+ it 'provides json for an object' do
59
+ assert_wish('/object.json', {'intro' => 'Hello, World!'}.to_json, 'application/json')
60
+ end
61
+
62
+ it 'provides html for an object' do
63
+ assert_wish('/string.html', 'Just 42', 'text/html')
64
+ end
65
+
66
+ it 'defaults to html presentation' do
67
+ assert_wish('/string', 'Just 42', 'text/html')
68
+ end
69
+ end
70
+
71
+ describe 'with templates' do
72
+ behaves_like :mock, :assert_wish
73
+
74
+ it 'defaults to <name>.html.<engine>' do
75
+ body = '<ul><li>starbucks</li><li>apollo</li><li>athena</li></ul>'
76
+ assert_wish('/template/list', body, 'text/html')
77
+ end
78
+
79
+ it 'uses explicit wish for <name>.html.<engine>' do
80
+ body = '<ul><li>starbucks</li><li>apollo</li><li>athena</li></ul>'
81
+ assert_wish('/template/list.html', body, 'text/html')
82
+ end
83
+
84
+ it 'fails when the wish cannot be satisfied' do
85
+ got = get('/template/list.svg')
86
+ got.status.should == 404
87
+ end
88
+
89
+ it 'uses the object returned from the action method for block provides' do
90
+ body = %w[starbucks apollo athena].to_yaml
91
+ assert_wish('/template/list.yaml', body, 'text/yaml')
92
+ end
93
+
94
+ it 'uses explicit wish for <name>.txt.<engine>' do
95
+ body = "starbucks\napollo\nathena"
96
+ assert_wish('/template/list.txt', body, 'text/plain')
97
+ end
98
+ end
99
+ end
@@ -2,7 +2,7 @@ require 'spec/helper'
2
2
 
3
3
  describe Innate::Request do
4
4
  def request(env = {})
5
- Innate::Request.new(env)
5
+ Innate::Request.new(@env.merge(env))
6
6
  end
7
7
 
8
8
  @env = {
@@ -18,7 +18,7 @@ describe Innate::Request do
18
18
  "HTTP_USER_AGENT" => "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008123017 Firefox/3.0.4 Ubiquity/0.1.4",
19
19
  "HTTP_VERSION" => "HTTP/1.1",
20
20
  "PATH_INFO" => "/",
21
- "QUERY_STRING" => "?a=b",
21
+ "QUERY_STRING" => "a=b",
22
22
  "REMOTE_ADDR" => "127.0.0.1",
23
23
  "REMOTE_HOST" => "delta.local",
24
24
  "REQUEST_METHOD" => "GET",
@@ -32,7 +32,7 @@ describe Innate::Request do
32
32
 
33
33
  should 'provide #request_uri' do
34
34
  request('REQUEST_URI' => '/?a=b').request_uri.should == '/?a=b'
35
- request('PATH_INFO' => '/').request_uri.should == '/'
35
+ request('REQUEST_URI' => '/').request_uri.should == '/'
36
36
  end
37
37
 
38
38
  should 'provide #local_net?' do
@@ -53,13 +53,26 @@ describe Innate::Request do
53
53
  req.subset(:a, :c).should == {'a' => 'b', 'c' => 'd'}
54
54
  end
55
55
 
56
- should 'provide #domain' do
57
- request(@env.merge('rack.url_scheme' => 'http')).domain.should ==
58
- URI('http://localhost:7000/')
59
- request(@env.merge('rack.url_scheme' => 'https')).domain.should ==
60
- URI('https://localhost:7000/')
61
- request(@env.merge('rack.url_scheme' => 'https')).domain('/foo').should ==
62
- URI('https://localhost:7000/foo')
56
+ should 'provide #domain on http' do
57
+ request('rack.url_scheme' => 'http').domain.
58
+ should == URI('http://localhost:7000/')
59
+
60
+ request('rack.url_scheme' => 'http').domain('/foo').
61
+ should == URI('http://localhost:7000/foo')
62
+
63
+ request('rack.url_scheme' => 'http').domain('/foo', :keep_query => true).
64
+ should == URI('http://localhost:7000/foo?a=b')
65
+ end
66
+
67
+ should 'provide #domain on https' do
68
+ request('rack.url_scheme' => 'https').domain.
69
+ should == URI('https://localhost:7000/')
70
+
71
+ request('rack.url_scheme' => 'https').domain('/foo').
72
+ should == URI('https://localhost:7000/foo')
73
+
74
+ request('rack.url_scheme' => 'https').domain('/foo', :keep_query => true).
75
+ should == URI('https://localhost:7000/foo?a=b')
63
76
  end
64
77
 
65
78
  should 'provide #accept_language' do
data/spec/innate/route.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  require 'spec/helper'
2
2
 
3
3
  class SpecRouter
4
- include Innate::Node
5
- map '/'
6
- provide :html => :None
4
+ Innate.node('/').provide(:html, :None)
7
5
 
8
6
  def float(flt)
9
7
  "Float: %3.3f" % flt
@@ -126,7 +124,7 @@ describe Innate::Rewrite do
126
124
  got.status.should == 200
127
125
  got.body.should == 'this is bar'
128
126
  end
129
-
127
+
130
128
  it 'should rewite with (key, val)' do
131
129
  Innate::Rewrite[ %r!^/(.+)$! ] = nil
132
130
  Innate::Rewrite(%r!^/(.+)$!, "/string/%s")
@@ -1,7 +1,7 @@
1
1
  require 'spec/helper'
2
2
 
3
3
  class SpecSession
4
- Innate.node('/').provide(:html => :none)
4
+ Innate.node('/').provide(:html, :None)
5
5
 
6
6
  def index
7
7
  'No session here'
@@ -0,0 +1,57 @@
1
+ begin
2
+ require 'fiber'
3
+ rescue LoadError
4
+ exit
5
+ end
6
+
7
+ require 'spec/helper'
8
+
9
+ describe Innate::State::Fiber do
10
+ F = Innate::State::Fiber
11
+
12
+ it 'sets value in current thread with #[]=' do
13
+ Innate::Fiber.new{
14
+ t = F.new
15
+ t[:a] = :b
16
+ Fiber.current[:a].should == :b
17
+ }.resume
18
+ end
19
+
20
+ it 'gets value in current thread with #[]' do
21
+ Innate::Fiber.new{
22
+ t = F.new
23
+ Fiber.current[:b] = :c
24
+ t[:b].should == :c
25
+ }.resume
26
+ end
27
+
28
+ it 'executes block in #wrap' do
29
+ Innate::Fiber.new{
30
+ t = F.new
31
+ t.wrap{ :foo }.should == :foo
32
+ }.resume
33
+ end
34
+
35
+ it 'reraises exceptions occured in #wrap thread' do
36
+ Innate::Fiber.new{
37
+ t = F.new
38
+ Thread.abort_on_exception = false
39
+ lambda{ t.wrap{ raise 'foo' } }.should.raise
40
+ }.resume
41
+ end
42
+
43
+ it 'defers execution of passed block in #defer' do
44
+ Innate::Fiber.new{
45
+ t = F.new
46
+ t.defer{ :foo }.value.should == :foo
47
+ }.resume
48
+ end
49
+
50
+ it 'copies thread variables to thread spawned in #defer' do
51
+ Innate::Fiber.new{
52
+ t = F.new
53
+ t[:a] = :b
54
+ t.defer{ Fiber.current[:a] }.value.should == :b
55
+ }.resume
56
+ end
57
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec/helper'
2
+ require 'innate/state/thread'
3
+
4
+ describe Innate::State::Thread do
5
+ T = Innate::State::Thread
6
+
7
+ it 'sets value in current thread with #[]=' do
8
+ t = T.new
9
+ t[:a] = :b
10
+ Thread.current[:a].should == :b
11
+ end
12
+
13
+ it 'gets value in current thread with #[]' do
14
+ t = T.new
15
+ Thread.current[:b] = :c
16
+ t[:b].should == :c
17
+ end
18
+
19
+ it 'executes block in #wrap' do
20
+ t = T.new
21
+ t.wrap{ :foo }.should == :foo
22
+ end
23
+
24
+ it 'reraises exceptions occured in #wrap thread' do
25
+ t = T.new
26
+ Thread.abort_on_exception = false
27
+ lambda{ t.wrap{ raise 'foo' } }.should.raise
28
+ end
29
+
30
+ it 'defers execution of passed block in #defer' do
31
+ t = T.new
32
+ t.defer{ :foo }.value.should == :foo
33
+ end
34
+
35
+ it 'copies thread variables to thread spawned in #defer' do
36
+ t = T.new
37
+ t[:a] = :b
38
+ t.defer{ Thread.current[:a] }.value.should == :b
39
+ end
40
+ end