contextr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,117 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class ContextRApiFoo
4
+ def non_contextified_method
5
+ "non_contextified_method"
6
+ end
7
+ def foo
8
+ "foo"
9
+ end
10
+ end
11
+
12
+ context 'Each class' do
13
+ specify 'should provide a method to enable a single layer' do
14
+ lambda do
15
+ class ContextRApiFoo
16
+ layer :bar
17
+ end
18
+ end.should_not raise_error
19
+ end
20
+
21
+ specify 'should provide a method to access these layers by name' do
22
+ begin
23
+ class ContextRApiFoo
24
+ bar
25
+ end
26
+ end.layer.should == ContextR::BarLayer
27
+ end
28
+ end
29
+
30
+ context 'Each layer in a class' do
31
+ specify 'should allow the definition of pre method wrappers ' +
32
+ 'with `pre`' do
33
+ lambda do
34
+ class ContextRApiFoo
35
+ bar.pre :foo do
36
+ @pre_visited = true
37
+ @pre_count = ( @pre_count || 0 ) + 1
38
+ end
39
+ end
40
+ end.should_not raise_error
41
+ end
42
+ specify 'should allow the definition of post method wrappers ' +
43
+ 'with `post`' do
44
+ lambda do
45
+ class ContextRApiFoo
46
+ bar.post :foo do
47
+ @post_visited = true
48
+ @post_count = ( @post_count || 0 ) + 1
49
+ end
50
+ end
51
+ end.should_not raise_error
52
+ end
53
+ specify 'should allow the definition of around method wrappers ' +
54
+ 'with `around`' do
55
+ lambda do
56
+ class ContextRApiFoo
57
+ bar.around :foo do | method_nature |
58
+ @around_visited = true
59
+ @around_count = ( @around_count || 0 ) + 1
60
+ method_nature.call_next
61
+ end
62
+ end
63
+ end.should_not raise_error
64
+ end
65
+ specify 'should allow the definition of around method wrappers ' +
66
+ 'with `wrap`' do
67
+ lambda do
68
+ class ContextRApiFoo
69
+ bar.wrap :foo do | method_nature |
70
+ @around_visited = true
71
+ @around_count = ( @around_count || 0 ) + 1
72
+ method_nature.call_next
73
+ end
74
+ end
75
+ end.should_not raise_error
76
+ end
77
+ end
78
+
79
+ context "An instance of a contextified class" do
80
+ setup do
81
+ @instance = ContextRApiFoo.new
82
+ end
83
+
84
+ specify "should run a simple method " +
85
+ "*normally* when all layers are deactivated" do
86
+ @instance.non_contextified_method.should == "non_contextified_method"
87
+ end
88
+
89
+ specify "should run a simple method " +
90
+ "*normally* when any layer is activated" do
91
+ ContextR.with_layers( :bar ) do
92
+ @instance.non_contextified_method.should == "non_contextified_method"
93
+ end
94
+ end
95
+
96
+ specify "should run a contextified method " +
97
+ "*normally* when all layers are deactivated" do
98
+ @instance.foo.should == "foo"
99
+ end
100
+
101
+ specify "should run a contextified method " +
102
+ "*normally* when any layer is activated" do
103
+ ContextR.with_layers( :baz ) do
104
+ @instance.foo.should == "foo"
105
+ end
106
+ end
107
+
108
+ specify "should run a contextified method with " +
109
+ "additional behaviour when a specific layer is activated" do
110
+ ContextR.with_layers( :bar ) do
111
+ @instance.foo.should == "foo"
112
+ end
113
+ @instance.instance_variable_get( :@pre_visited ).should == true
114
+ @instance.instance_variable_get( :@post_visited ).should == true
115
+ @instance.instance_variable_get( :@around_visited ).should == true
116
+ end
117
+ end
@@ -0,0 +1,99 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ context 'Each first level module' do
4
+ specify 'should have the same name and namespace_free_name' do
5
+ Math.namespace_free_name.should == Math.name
6
+ Kernel.namespace_free_name.should == Kernel.name
7
+ end
8
+
9
+ specify 'should have a namespace_free_name matching their constant' do
10
+ Kernel.namespace_free_name.should == Kernel.to_s
11
+ Kernel.namespace_free_name.should == "Kernel"
12
+ end
13
+ end
14
+
15
+ context 'Each sublevel module' do
16
+ setup do
17
+ module ModuleTestA
18
+ module B
19
+ module C
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ specify 'should have a namespace free namespace_free_name' do
26
+ ModuleTestA::B.namespace_free_name.should == "B"
27
+ ModuleTestA::B::C.namespace_free_name.should == "C"
28
+ end
29
+ end
30
+
31
+ context "Each module" do
32
+ specify "should have a attr_accessor_with_default_setter" do
33
+ lambda do
34
+ class ClassSpecA
35
+ attr_accessor_with_default_setter :miau do
36
+ {}
37
+ end
38
+ end
39
+ end.should_not raise_error
40
+ end
41
+ end
42
+
43
+ context "Each instance" do
44
+ setup do
45
+ @instance = ClassSpecA.new
46
+ @instance2 = ClassSpecA.new
47
+ end
48
+ specify "should provide a getter method" do
49
+ @instance.should_respond_to :miau
50
+ end
51
+ specify "should provide a setter method" do
52
+ @instance.should_respond_to :miau=
53
+ end
54
+
55
+ end
56
+
57
+ context "A getter method" do
58
+ setup do
59
+ @getter = ClassSpecA.instance_method( :miau )
60
+ @instance = ClassSpecA.new
61
+ @instance2 = ClassSpecA.new
62
+ end
63
+
64
+ specify "should not expect a parameter" do
65
+ @getter.arity.should == 0
66
+ end
67
+
68
+ specify "should provide the default value" do
69
+ @instance.miau.should == Hash.new
70
+ end
71
+
72
+ specify "should provide the default value also multiple times" do
73
+ @instance.miau.object_id.should == @instance.miau.object_id
74
+ end
75
+
76
+ specify "should provide the different default values for different " +
77
+ "instances" do
78
+ @instance2.miau.object_id.should_not == @instance.miau.object_id
79
+ end
80
+ end
81
+
82
+ context "A setter method" do
83
+ setup do
84
+ @setter = ClassSpecA.instance_method( :miau= )
85
+ @instance = ClassSpecA.new
86
+ @instance2 = ClassSpecA.new
87
+ end
88
+
89
+ specify "should not expect a parameter" do
90
+ @setter.arity.should == 1
91
+ end
92
+
93
+ specify "should allow the setting of the corresonding instance variable" do
94
+ begin
95
+ @instance.miau = "blue"
96
+ end.should == "blue"
97
+ @instance.instance_variable_get( :@miau ).should == "blue"
98
+ end
99
+ end
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ class ProcSpecFoo
4
+ def non_contextified_method
5
+ "non_contextified_method"
6
+ end
7
+ def foo
8
+ "foo"
9
+ end
10
+ end
11
+
12
+ context "A Proc" do
13
+ setup do
14
+ @a = lambda do @a = true; "a" end
15
+ @b = lambda do @b = true; "b" end
16
+ @foo = ProcSpecFoo.new
17
+ end
18
+
19
+ specify "should convert itself to an unbound method" do
20
+ @b.to_unbound_method( ProcSpecFoo ).should_be_kind_of UnboundMethod
21
+ end
22
+
23
+ specify "which should be bindable to an instance of the specified class" do
24
+ lambda do
25
+ @b.to_unbound_method( ProcSpecFoo ).bind( @foo )
26
+ end.should_not raise_error
27
+ end
28
+
29
+ specify "which should execute the proc in turn" do
30
+ @b.to_unbound_method( ProcSpecFoo ).bind( @foo ).call.should == "b"
31
+ @foo.instance_variable_get( :@b ).should == true
32
+ end
33
+
34
+ specify "should respond to `+`" do
35
+ @b.should_respond_to :+
36
+ end
37
+
38
+ specify "should build a joined block with `self.+( other_proc)`" do
39
+ (@a + @b).should_be_kind_of Proc
40
+ end
41
+ end
42
+
43
+ context "The result of `+` of two Procs" do
44
+ setup do
45
+ @a = lambda do | arg |
46
+ arg || "a"
47
+ end
48
+ @b = lambda do | arg |
49
+ arg || "b"
50
+ end
51
+ end
52
+
53
+ specify "should give the correct return value" do
54
+ (@a + @b).call( nil ).should == "b"
55
+ (@b + @a).call( nil ).should == "a"
56
+ end
57
+
58
+ specify "should pass through given parameters" do
59
+ (@a + @b).call( 1 ).should == 1
60
+ end
61
+ end
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/../lib/contextr'
@@ -0,0 +1,107 @@
1
+ # The following copyright applies to this File
2
+ # which we borrowed from rails.
3
+ #
4
+ # Copyright (c) 2004 David Heinemeier Hansson
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ class SourceAnnotationExtractor
25
+ class Annotation < Struct.new(:line, :tag, :text)
26
+ def to_s(options={})
27
+ s = "[%3d] " % line
28
+ s << "[#{tag}] " if options[:tag]
29
+ s << text
30
+ end
31
+ end
32
+
33
+ def self.enumerate(tag, options={})
34
+ extractor = new(tag)
35
+ extractor.display(extractor.find, options)
36
+ end
37
+
38
+ attr_reader :tag
39
+
40
+ def initialize(tag)
41
+ @tag = tag
42
+ end
43
+
44
+ def find(dirs=%w(app lib test))
45
+ dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
46
+ end
47
+
48
+ def find_in(dir)
49
+ results = {}
50
+
51
+ Dir.glob("#{dir}/*") do |item|
52
+ next if File.basename(item)[0] == ?.
53
+
54
+ if File.directory?(item)
55
+ results.update(find_in(item))
56
+ elsif item =~ /\.r(?:b|xml|js)$/
57
+ results.update(extract_annotations_from(item, /#\s*(#{tag}):?\s*(.*)$/))
58
+ elsif item =~ /\.rhtml$/
59
+ results.update(extract_annotations_from(item, /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/))
60
+ end
61
+ end
62
+
63
+ results
64
+ end
65
+
66
+ def extract_annotations_from(file, pattern)
67
+ lineno = 0
68
+ result = File.readlines(file).inject([]) do |list, line|
69
+ lineno += 1
70
+ next list unless line =~ pattern
71
+ list << Annotation.new(lineno, $1, $2)
72
+ end
73
+ result.empty? ? {} : { file => result }
74
+ end
75
+
76
+ def display(results, options={})
77
+ results.keys.sort.each do |file|
78
+ puts "#{file}:"
79
+ results[file].each do |note|
80
+ puts " * #{note.to_s(options)}"
81
+ end
82
+ puts
83
+ end
84
+ end
85
+ end
86
+
87
+ desc "Enumerate all annotations"
88
+ task :notes do
89
+ SourceAnnotationExtractor.enumerate "OPTIMIZE|FIXME|TODO", :tag => true
90
+ end
91
+
92
+ namespace :notes do
93
+ desc "Enumerate all OPTIMIZE annotations"
94
+ task :optimize do
95
+ SourceAnnotationExtractor.enumerate "OPTIMIZE"
96
+ end
97
+
98
+ desc "Enumerate all FIXME annotations"
99
+ task :fixme do
100
+ SourceAnnotationExtractor.enumerate "FIXME"
101
+ end
102
+
103
+ desc "Enumerate all TODO annotations"
104
+ task :todo do
105
+ SourceAnnotationExtractor.enumerate "TODO"
106
+ end
107
+ end
@@ -0,0 +1,165 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class UnitContextRFoo
4
+ layer :pre, :post, :wrap
5
+ layer :stop_wrap, :stop_pre, :stop_post
6
+ layer :order_wrap, :order_pre, :order_post
7
+ layer :group_pre, :group_post
8
+
9
+ def bar( sum )
10
+ sum + 0b00100
11
+ end
12
+
13
+ pre.pre :bar do | nature |
14
+ nature.arguments[ 0 ] += 0b00010
15
+ end
16
+
17
+ post.post :bar do | nature |
18
+ nature.return_value += 0b01000
19
+ end
20
+
21
+ wrap.wrap :bar do | nature |
22
+ nature.arguments[ 0 ] += 0b00001
23
+ nature.call_next
24
+ nature.return_value += 0b10000
25
+ end
26
+
27
+ stop_pre.pre :bar do | nature |
28
+ nature.break! nature.arguments[0]
29
+ end
30
+ stop_wrap.wrap :bar do | nature |
31
+ nature.break! nature.arguments[0]
32
+ end
33
+ stop_post.post :bar do | nature |
34
+ nature.break! nature.return_value
35
+ end
36
+
37
+ order_pre.pre :bar do | nature |
38
+ nature.break! :pre
39
+ end
40
+
41
+ order_post.post :bar do | nature |
42
+ nature.break! :post
43
+ end
44
+
45
+ order_wrap.wrap :bar do | nature |
46
+ nature.break! :wrap
47
+ end
48
+
49
+ group_pre.pre :bar do | nature |
50
+ nature.return_value = :pre
51
+ end
52
+
53
+ group_pre.pre :bar do | nature |
54
+ nature.break! nature.return_value
55
+ end
56
+
57
+ group_post.post :bar do | nature |
58
+ nature.return_value = :post
59
+ end
60
+
61
+ group_post.post :bar do | nature |
62
+ nature.break! nature.return_value
63
+ end
64
+ end
65
+
66
+
67
+ class ContextRTest < Test::Unit::TestCase
68
+ def setup
69
+ @foo = UnitContextRFoo.new
70
+ end
71
+
72
+ def test_01_layer_activiation
73
+ assert_equal 0b00100, @foo.bar( 0 )
74
+
75
+ ContextR.with_layers :wrap do
76
+ assert_equal 0b10101, @foo.bar( 0 )
77
+
78
+ ContextR.without_layers :wrap do
79
+ assert_equal 0b00100, @foo.bar( 0 )
80
+ end
81
+
82
+ assert_equal 0b10101, @foo.bar( 0 )
83
+ end
84
+
85
+ assert_equal 0b00100, @foo.bar( 0 )
86
+ end
87
+
88
+ def test_02_cascading_layers
89
+ assert_equal 0b00100, @foo.bar( 0 )
90
+
91
+ ContextR.with_layers :pre do
92
+ assert_equal 0b00110, @foo.bar( 0 )
93
+
94
+ ContextR.with_layers :post do
95
+ assert_equal 0b01110, @foo.bar( 0 )
96
+
97
+ ContextR.with_layers :wrap do
98
+ assert_equal 0b11111, @foo.bar( 0 )
99
+ end
100
+
101
+ assert_equal 0b01110, @foo.bar( 0 )
102
+ end
103
+
104
+ assert_equal 0b00110, @foo.bar( 0 )
105
+ end
106
+
107
+ assert_equal 0b00100, @foo.bar( 0 )
108
+ end
109
+
110
+ def test_03_breaking_behaviour
111
+ ContextR.with_layers :pre, :post, :stop_wrap do
112
+ assert_equal 0b00010, @foo.bar( 0 )
113
+ end
114
+ end
115
+
116
+ def test_04_ordering_by_selectors
117
+ # pre before post
118
+ ContextR.with_layers :order_pre, :order_post do
119
+ assert_equal :pre, @foo.bar( 0 )
120
+ end
121
+ # pre before wrap
122
+ ContextR.with_layers :order_wrap, :order_pre do
123
+ assert_equal :pre, @foo.bar( 0 )
124
+ end
125
+ # wrap before body
126
+ ContextR.with_layers :order_wrap do
127
+ assert_equal :wrap, @foo.bar( 0 )
128
+ end
129
+ # wrap before post
130
+ ContextR.with_layers :order_wrap, :order_post do
131
+ assert_equal :wrap, @foo.bar( 0 )
132
+ end
133
+ # To be completed...
134
+ end
135
+
136
+ def test_05_ordering_by_layers
137
+ ContextR.with_layers :wrap, :stop_wrap do
138
+ assert_equal 0b00000, @foo.bar( 0 )
139
+ end
140
+ ContextR.with_layers :stop_wrap, :wrap do
141
+ assert_equal 0b00001, @foo.bar( 0 )
142
+ end
143
+ ContextR.with_layers :pre, :stop_pre do
144
+ assert_equal 0b00000, @foo.bar( 0 )
145
+ end
146
+ ContextR.with_layers :stop_pre, :pre do
147
+ assert_equal 0b00010, @foo.bar( 0 )
148
+ end
149
+ ContextR.with_layers :post, :stop_post do
150
+ assert_equal 0b01100, @foo.bar( 0 )
151
+ end
152
+ ContextR.with_layers :stop_post, :post do
153
+ assert_equal 0b00100, @foo.bar( 0 )
154
+ end
155
+ end
156
+
157
+ def test_06_ordering_within_groups
158
+ ContextR.with_layers :group_pre do
159
+ assert_equal nil, @foo.bar( 0 )
160
+ end
161
+ ContextR.with_layers :group_post do
162
+ assert_equal :post, @foo.bar( 0 )
163
+ end
164
+ end
165
+ end