phenomenal 0.9.0 → 0.11.11.24.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/LICENSE +1 -1
  2. data/README +4 -3
  3. data/Rakefile +0 -3
  4. data/demo.rb +24 -0
  5. data/demo_age.rb +89 -0
  6. data/demo_dsl.rb +28 -0
  7. data/lib/phenomenal.rb +2 -15
  8. data/lib/phenomenal/adaptation.rb +12 -22
  9. data/lib/phenomenal/context.rb +134 -127
  10. data/lib/phenomenal/dsl.rb +14 -41
  11. data/lib/phenomenal/logger.rb +1 -0
  12. data/lib/phenomenal/manager.rb +35 -117
  13. data/phenomenal.gemspec +15 -0
  14. data/{spec → test}/test_classes.rb +0 -3
  15. data/test/test_cop_adaptation.rb +168 -0
  16. data/test/test_cop_composition.rb +84 -0
  17. data/test/test_cop_conflictpolicy.rb +177 -0
  18. data/test/test_cop_infrastructure.rb +129 -0
  19. data/test_declaration.rb +18 -0
  20. metadata +29 -70
  21. data/lib/phenomenal/feature.rb +0 -8
  22. data/lib/phenomenal/relationships/context_relationships.rb +0 -22
  23. data/lib/phenomenal/relationships/dsl.rb +0 -18
  24. data/lib/phenomenal/relationships/feature_relationships.rb +0 -42
  25. data/lib/phenomenal/relationships/implication.rb +0 -35
  26. data/lib/phenomenal/relationships/relationship.rb +0 -42
  27. data/lib/phenomenal/relationships/relationships_manager.rb +0 -63
  28. data/lib/phenomenal/relationships/relationships_store.rb +0 -73
  29. data/lib/phenomenal/relationships/requirement.rb +0 -26
  30. data/lib/phenomenal/relationships/suggestion.rb +0 -41
  31. data/lib/phenomenal/version.rb +0 -3
  32. data/spec/adaptation_spec.rb +0 -64
  33. data/spec/behavior/adaptation_spec.rb +0 -5
  34. data/spec/behavior/combined_contexts_spec.rb +0 -5
  35. data/spec/behavior/composition_spec.rb +0 -5
  36. data/spec/behavior/conflict_policy_spec.rb +0 -5
  37. data/spec/behavior/open_context.rb +0 -5
  38. data/spec/behavior/relationships_spec.rb +0 -249
  39. data/spec/context_spec.rb +0 -268
  40. data/spec/dsl_spec.rb +0 -181
  41. data/spec/feature_spec.rb +0 -5
  42. data/spec/manager_spec.rb +0 -84
  43. data/spec/proc_spec.rb +0 -20
  44. data/spec/relationships/context_relationships_spec.rb +0 -13
  45. data/spec/relationships/dsl_spec.rb +0 -13
  46. data/spec/relationships/feature_relationships_spec.rb +0 -13
  47. data/spec/relationships/relationship_spec.rb +0 -31
  48. data/spec/relationships/relationships_manager_spec.rb +0 -15
  49. data/spec/relationships/relationships_store_spec.rb +0 -19
  50. data/spec/spec_helper.rb +0 -18
@@ -8,16 +8,17 @@ module Phenomenal::DSL
8
8
  Phenomenal::Context.new(name,priority)
9
9
  end
10
10
  # Define context with adaptations
11
- def phen_context(context,*contexts,&block)
12
- Phenomenal::Context.create(context,*contexts,false,nil,&block)
11
+ def phen_context(*args,&block)
12
+ Phenomenal::Context.create(*args,&block)
13
13
  end
14
- Phenomenal::DSL.phen_alias(:context,klass)
14
+ #TODO check kernel repond to method
15
+ alias_method :context, :phen_context
15
16
 
16
17
  # Define context with adaptations
17
- def phen_feature(context,*contexts,&block)
18
- Phenomenal::Feature.create(context,*contexts,false,nil,&block)
18
+ def phen_feature(*args,&block)
19
+ Phenomenal::Context.create_feature(*args,&block)
19
20
  end
20
- Phenomenal::DSL.phen_alias(:feature,klass)
21
+ alias_method :feature, :phen_feature
21
22
 
22
23
 
23
24
  # Forget Context
@@ -28,26 +29,14 @@ module Phenomenal::DSL
28
29
  # Add adaptation
29
30
  def phen_add_adaptation(context,klass, method_name, &implementation)
30
31
  Phenomenal::Manager.instance.find_context(context).add_adaptation(
31
- klass, method_name,true, &implementation
32
- )
33
- end
34
-
35
- def phen_add_class_adaptation(context,klass, method_name, &implementation)
36
- Phenomenal::Manager.instance.find_context(context).add_adaptation(
37
- klass, method_name,false, &implementation
32
+ klass, method_name, &implementation
38
33
  )
39
34
  end
40
35
 
41
36
  # Remove Adaptation
42
37
  def phen_remove_adaptation(context,klass,method_name)
43
38
  Phenomenal::Manager.instance.find_context(context).remove_adaptation(
44
- klass,method_name,true
45
- )
46
- end
47
-
48
- def phen_remove_class_adaptation(context,klass,method_name)
49
- Phenomenal::Manager.instance.find_context(context).remove_adaptation(
50
- klass,method_name,false
39
+ klass,method_name
51
40
  )
52
41
  end
53
42
 
@@ -55,13 +44,13 @@ module Phenomenal::DSL
55
44
  def phen_activate_context(context)
56
45
  Phenomenal::Manager.instance.find_context(context).activate
57
46
  end
58
- Phenomenal::DSL.phen_alias(:activate_context,klass)
47
+ alias_method :activate_context, :phen_activate_context
59
48
 
60
49
  # Deactivate Context
61
50
  def phen_deactivate_context(context)
62
51
  Phenomenal::Manager.instance.find_context(context).deactivate
63
52
  end
64
- Phenomenal::DSL.phen_alias(:deactivate_context,klass)
53
+ alias_method :deactivate_context, :phen_deactivate_context
65
54
 
66
55
  # Context is active?
67
56
  def phen_context_active?(context)
@@ -69,8 +58,8 @@ module Phenomenal::DSL
69
58
  end
70
59
 
71
60
  # Context informations
72
- def phen_context_information(context)
73
- Phenomenal::Manager.instance.find_context(context).information
61
+ def phen_context_informations(context)
62
+ Phenomenal::Manager.instance.find_context(context).informations
74
63
  end
75
64
 
76
65
  # Default Context
@@ -87,29 +76,13 @@ module Phenomenal::DSL
87
76
  def phen_proceed(*args,&block)
88
77
  Phenomenal::Manager.instance.proceed(caller,self,*args,&block)
89
78
  end
90
- Phenomenal::DSL.phen_alias(:proceed,klass)
79
+ alias_method :proceed, :phen_proceed
91
80
 
92
81
  # Change conflict resolution policy (for the proceed call)
93
82
  def phen_change_conflict_policy(&block)
94
83
  Phenomenal::Manager.instance.change_conflict_policy(&block)
95
84
  end
96
85
  end
97
- # Add relationships specific DSL
98
- define_relationships(klass)
99
- end
100
-
101
- private
102
- def self.phen_alias(method,klass)
103
- if Kernel.respond_to? method
104
- Phenomenal::Logger.instance.warn(
105
- "The Phenomenal DSL keyword #{method} wasn't defined, use"+
106
- " phen_#{method} instead"
107
- )
108
- else
109
- klass.class_eval do
110
- alias_method method, "phen_#{method}"
111
- end
112
- end
113
86
  end
114
87
  end
115
88
 
@@ -20,6 +20,7 @@ class Phenomenal::Logger
20
20
  end
21
21
 
22
22
  def error(msg)
23
+ logger.error(msg)
23
24
  raise(Phenomenal::Error, msg)
24
25
  end
25
26
 
@@ -4,8 +4,8 @@ class Phenomenal::Manager
4
4
  include Singleton
5
5
  include Phenomenal::ConflictPolicies
6
6
 
7
- attr_accessor :active_adaptations, :deployed_adaptations, :contexts,
8
- :default_context, :combined_contexts, :shared_contexts, :rmanager
7
+ attr_accessor :active_adaptations, :deployed_adaptations,
8
+ :contexts, :default_context
9
9
 
10
10
  # Register a new context
11
11
  def register_context(context)
@@ -20,7 +20,7 @@ class Phenomenal::Manager
20
20
  " If you want to have named context it has to be a globally unique name"
21
21
  )
22
22
  end
23
- contexts[context]=context
23
+ contexts[context.__id__]=context
24
24
  end
25
25
 
26
26
  # Unregister a context (forget)
@@ -30,17 +30,7 @@ class Phenomenal::Manager
30
30
  "Default context can only be forgotten when alone"
31
31
  )
32
32
  else
33
- contexts.delete(context)
34
-
35
- # Forgot combined contexts
36
- combined_contexts.delete(context)
37
- if shared_contexts[context]
38
- shared_contexts[context].each do |c|
39
- c.forget
40
- end
41
- end
42
-
43
- # Restore default context
33
+ contexts.delete(context.__id__)
44
34
  init_default() if context==default_context
45
35
  end
46
36
  end
@@ -48,10 +38,10 @@ class Phenomenal::Manager
48
38
  # Register a new adaptation for a registered context
49
39
  def register_adaptation(adaptation)
50
40
  default_adaptation = default_context.adaptations.find do|i|
51
- i.concern?(adaptation.klass,adaptation.method_name,adaptation.instance_adaptation?)
41
+ i.concern?(adaptation.klass,adaptation.method_name)
52
42
  end
53
43
  if adaptation.context!=default_context && !default_adaptation
54
- save_default_adaptation(adaptation.klass, adaptation.method_name,adaptation.instance_adaptation?)
44
+ save_default_adaptation(adaptation.klass, adaptation.method_name)
55
45
  end
56
46
  activate_adaptation(adaptation) if adaptation.context.active?
57
47
  end
@@ -64,23 +54,7 @@ class Phenomenal::Manager
64
54
  # Activate the context 'context' and deploy the related adaptation
65
55
  def activate_context(context)
66
56
  begin
67
- # Relationships managment
68
- rmanager.activate_relationships(context) if context.just_activated?
69
-
70
- # Activation of adaptations
71
57
  context.adaptations.each{ |i| activate_adaptation(i) }
72
- #puts "activation of #{context}"
73
- if shared_contexts[context]
74
- #puts "trigger activation of #{shared_contexts[context].first.information}"
75
- shared_contexts[context].each do |combined_context|
76
- need_activation=true
77
- combined_contexts[combined_context].each do |shared_context|
78
- need_activation=false if !shared_context.active?
79
- end
80
- combined_context.activate if need_activation
81
- end
82
- end
83
-
84
58
  rescue Phenomenal::Error
85
59
  context.deactivate # rollback the deployed adaptations
86
60
  raise # throw up the exception
@@ -89,30 +63,19 @@ class Phenomenal::Manager
89
63
 
90
64
  # Deactivate the adaptations (undeploy if needed)
91
65
  def deactivate_context(context)
92
- #Relationships managment
93
- rmanager.deactivate_relationships(context)
94
- #Adaptations deactivation
95
- context.adaptations.each do |i|
96
- deactivate_adaptation(i)
97
- end
98
- if shared_contexts[context]
99
- shared_contexts[context].each do |combined_context|
100
- while combined_context.active? do
101
- combined_context.deactivate
102
- end
103
- end
104
- end
66
+ context.adaptations.each{ |i|
67
+ deactivate_adaptation(i) }
105
68
  end
106
69
 
107
70
  # Call the old implementation of the method 'caller.caller_method'
108
71
  def proceed(calling_stack,instance,*args,&block)
109
72
  calling_adaptation = find_adapatation(calling_stack)
110
- # IMPROVE Problems will appears if proceed called in a file where
73
+ #TODO Problems will appears if proceed called in a file where
111
74
  # adaptations are defined but not in one of them=> how to check?
112
- # IMPROVE Problems will also appears if two adaptations are defined on the same
75
+ #TODO Problems will also appears if two adaptations are defined on the same
113
76
  # line using the ';' some check needed at add_adaptation ?
114
77
  adaptations_stack = sorted_adaptations_for(calling_adaptation.klass,
115
- calling_adaptation.method_name,calling_adaptation.instance_adaptation?)
78
+ calling_adaptation.method_name)
116
79
  calling_adaptation_index = adaptations_stack.find_index(calling_adaptation)
117
80
 
118
81
  next_adaptation = adaptations_stack[calling_adaptation_index+1]
@@ -131,38 +94,15 @@ class Phenomenal::Manager
131
94
  # currently registered.
132
95
  # The 'context' parameter can be either a reference to a context instance or
133
96
  # a Symbol with the name of a named (not anonymous) context.
134
- def find_context(context, *contexts)
135
- if contexts.length==0
136
- find_simple_context(context)
137
- else #Combined contexts
138
- contexts.insert(0,context)
139
- find_combined_context(contexts)
140
- end
141
- end
142
-
143
- # Check wether context 'context' exist in the context manager
144
- # Context can be either the context name or the context instance itself
145
- # Return the context if found, or nil otherwise
146
- def context_defined?(context, *contexts)
147
- c=nil
148
- begin
149
- c = find_context(context,*contexts)
150
- rescue Phenomenal::Error
151
- return nil
152
- end
153
- return c
154
- end
155
- # ==== Private methods ==== #
156
- private
157
- def find_simple_context(context)
97
+ def find_context(context)
158
98
  find=nil
159
- if !context.kind_of?(Phenomenal::Context)
99
+ if context.class!=Phenomenal::Context
160
100
  a = contexts.find{|k,v| v.name==context}
161
101
  if a
162
102
  find = a[1]
163
103
  end
164
104
  else
165
- find = context if contexts.has_key?(context)
105
+ find = context if contexts.has_key?(context.__id__)
166
106
  end
167
107
  if find
168
108
  find
@@ -172,43 +112,24 @@ class Phenomenal::Manager
172
112
  )
173
113
  end
174
114
  end
175
-
176
- def find_combined_context(contexts)
177
- list=Array.new
178
- contexts.each do |c|
179
- # Use the object instance if already available
180
- # otherwise use the symbol name
181
- c = find_simple_context(c) if context_defined?(c)
182
- if shared_contexts[c]==nil
183
- list.clear
184
- break
185
- elsif list.length==0
186
- # clone otherwise list.clear empty shared_contexts[c]
187
- list=shared_contexts[c].clone
188
- else
189
- list=shared_contexts[c].find_all{|i| list.include?(i) }
190
- end
191
- end
192
- if list.length==0
193
- Phenomenal::Logger.instance.error(
194
- "Unknown combined context #{contexts}"
195
- )
196
- elsif list.length==1
197
- return list.first
115
+ # Check wether context 'context' exist in the context manager
116
+ # Context can be either the context name or the context instance itself
117
+ def context_defined?(context)
118
+ if context.class==Phenomenal::Context
119
+ contexts.has_key?(context.__id__)
198
120
  else
199
- Phenomenal::Logger.instance.error(
200
- "Multiple definition of combined context #{contexts}"
201
- )
121
+ contexts.find{|k,v| v.name==context}!=nil
202
122
  end
203
123
  end
204
-
124
+ # ==== Private methods ==== #
125
+ private
205
126
  # Activate the adaptation and redeploy the adaptations to take the new one
206
127
  # one in account
207
128
  def activate_adaptation(adaptation)
208
129
  if !active_adaptations.include?(adaptation)
209
130
  active_adaptations.push(adaptation)
210
131
  end
211
- redeploy_adaptation(adaptation.klass,adaptation.method_name,adaptation.instance_adaptation?)
132
+ redeploy_adaptation(adaptation.klass,adaptation.method_name)
212
133
  end
213
134
 
214
135
  # Deactivate the adaptation and redeploy the adaptations if necessary
@@ -216,14 +137,14 @@ class Phenomenal::Manager
216
137
  active_adaptations.delete(adaptation)
217
138
  if deployed_adaptations.include?(adaptation)
218
139
  deployed_adaptations.delete(adaptation)
219
- redeploy_adaptation(adaptation.klass,adaptation.method_name,adaptation.instance_adaptation?)
140
+ redeploy_adaptation(adaptation.klass,adaptation.method_name)
220
141
  end
221
142
  end
222
143
 
223
144
  # Redeploy the adaptations concerning klass.method_name according to the
224
145
  # conflict policy
225
- def redeploy_adaptation(klass, method_name,instance)
226
- to_deploy = resolve_conflict(klass,method_name,instance)
146
+ def redeploy_adaptation(klass, method_name)
147
+ to_deploy = resolve_conflict(klass,method_name)
227
148
  # Do nothing when to_deploy==nil to break at default context deactivation
228
149
  if !deployed_adaptations.include?(to_deploy) && to_deploy!=nil
229
150
  deploy_adaptation(to_deploy)
@@ -233,7 +154,7 @@ class Phenomenal::Manager
233
154
  # Deploy the adaptation
234
155
  def deploy_adaptation(adaptation)
235
156
  to_undeploy = deployed_adaptations.find do |i|
236
- i.concern?(adaptation.klass,adaptation.method_name,adaptation.instance_adaptation?)
157
+ i.concern?(adaptation.klass,adaptation.method_name)
237
158
  end
238
159
  if to_undeploy!=adaptation # if new adaptation
239
160
  deployed_adaptations.delete(to_undeploy)
@@ -243,13 +164,13 @@ class Phenomenal::Manager
243
164
  end
244
165
 
245
166
  # Save the default adaptation of a method, ie: the initial method
246
- def save_default_adaptation(klass, method_name,instance)
247
- if instance
167
+ def save_default_adaptation(klass, method_name)
168
+ if klass.instance_methods.include?(method_name)
248
169
  method = klass.instance_method(method_name)
249
170
  else
250
171
  method = klass.method(method_name)
251
172
  end
252
- adaptation = default_context.add_adaptation(klass,method_name,instance,method)
173
+ adaptation = default_context.add_adaptation(klass,method_name,method)
253
174
  end
254
175
 
255
176
  # Return the adaptation that math the calling_stack, on the basis of the
@@ -281,15 +202,15 @@ class Phenomenal::Manager
281
202
  end
282
203
 
283
204
  # Return the best adaptation according to the resolution policy
284
- def resolve_conflict(klass,method_name,instance)
285
- sorted_adaptations_for(klass,method_name,instance).first
205
+ def resolve_conflict(klass,method_name)
206
+ sorted_adaptations_for(klass,method_name).first
286
207
  end
287
208
 
288
209
  # Return the adaptations for a particular method sorted with the
289
210
  # conflict policy
290
- def sorted_adaptations_for(klass,method_name,instance)
211
+ def sorted_adaptations_for(klass,method_name)
291
212
  relevant_adaptations =
292
- active_adaptations.find_all { |i| i.concern?(klass, method_name,instance) }
213
+ active_adaptations.find_all { |i| i.concern?(klass, method_name) }
293
214
  relevant_adaptations.sort!{|a,b| conflict_policy(a,b)}
294
215
  end
295
216
 
@@ -300,7 +221,7 @@ class Phenomenal::Manager
300
221
 
301
222
  # Set the default context
302
223
  def init_default
303
- self.default_context= Phenomenal::Feature.new(nil,self)
224
+ self.default_context= Phenomenal::Context.new(nil,nil,true,self)
304
225
  self.default_context.activate
305
226
  end
306
227
 
@@ -309,9 +230,6 @@ class Phenomenal::Manager
309
230
  @contexts = Hash.new
310
231
  @deployed_adaptations = Array.new
311
232
  @active_adaptations = Array.new
312
- @combined_contexts = Hash.new
313
- @shared_contexts = Hash.new
314
- @rmanager = Phenomenal::RelationshipsManager.instance
315
233
  init_default()
316
234
  end
317
235
  end
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "phenomenal"
3
+ s.summary = "A context oriented programing framework for ruby"
4
+ s.description = File.read(File.join(File.dirname(__FILE__),'README'))
5
+ s.version = "0.11.11.24.3"
6
+ s.authors = "Loic Vigneron - Thibault Poncelet"
7
+ s.email = "thibault.poncelet@student.uclouvain.be - loic.vigneron@student.uclouvain.be"
8
+ s.date = "2011-10-07"
9
+ s.platform = Gem::Platform::RUBY
10
+ s.required_ruby_version = '>=1.9.2'
11
+ s.files = Dir['**/**']
12
+ s.has_rdoc = false
13
+ s.test_files = Dir['test/*.rb']
14
+ s.homepage = "http://www.phenomenal-gem.com"
15
+ end
@@ -1,7 +1,4 @@
1
1
  # Define the test classes
2
- class TestString < String
3
- end
4
-
5
2
  class TestClass < String
6
3
  @klass_inst_var = 2
7
4
  @@klass_var = 1
@@ -0,0 +1,168 @@
1
+ require_relative "../lib/phenomenal.rb"
2
+ require_relative "./test_classes.rb"
3
+ require "test/unit"
4
+
5
+ class TestCopAdaptation < Test::Unit::TestCase
6
+ def setup
7
+ phen_define_context(:quiet)
8
+ phen_define_context(:offHook)
9
+ phen_add_adaptation(:quiet,Phone,:advertise){|a_call| "vibrator" }
10
+ phen_add_adaptation(:offHook,Phone,:advertise) do |a_call|
11
+ "call waiting signal"
12
+ end
13
+ phen_define_context(:test)
14
+ phen_add_adaptation(:test,TestClass,:to_s) do
15
+ @value + " @access " + value + " attr_accessor_access"
16
+ end
17
+
18
+ phen_define_context(:test_2)
19
+ phen_add_adaptation(:test_2,TestClass,:klass_var_access) do
20
+ @@klass_var+1
21
+ end
22
+
23
+ phen_define_context(:test_3)
24
+ phen_add_adaptation(:test_3,TestClass,:klass_inst_var_access) do
25
+ @klass_inst_var+1
26
+ end
27
+ end
28
+
29
+ def teardown
30
+ while phen_context_active?(:quiet) do
31
+ phen_deactivate_context(:quiet)
32
+ end
33
+ phen_forget_context(:quiet)
34
+
35
+ while phen_context_active?(:offHook) do
36
+ phen_deactivate_context(:offHook)
37
+ end
38
+ phen_forget_context(:offHook)
39
+
40
+ while phen_context_active?(:test) do
41
+ phen_deactivate_context(:test)
42
+ end
43
+ phen_forget_context(:test)
44
+
45
+ while phen_context_active?(:test_2) do
46
+ phen_deactivate_context(:test_2)
47
+ end
48
+ phen_forget_context(:test_2)
49
+
50
+ while phen_context_active?(:test_3) do
51
+ phen_deactivate_context(:test_3)
52
+ end
53
+ phen_forget_context(:test_3)
54
+ end
55
+
56
+ def test_overriding_adaptation
57
+ phone = Phone.new
58
+ call = Call.new("Bob")
59
+ phone.receive(call)
60
+ assert((phone.advertise(call))=="ringtone",
61
+ "Default behaviour should be expressed")
62
+ phen_activate_context(:quiet)
63
+ assert((phone.advertise(call))=="vibrator",
64
+ "Behavior adapted to quiet environments should be expressed")
65
+ phen_deactivate_context(:quiet)
66
+ assert((phone.advertise(call))=="ringtone",
67
+ "Default behaviour should be expressed")
68
+ end
69
+
70
+ def test_conflicting_adaptation
71
+ assert_raise(Phenomenal::Error,
72
+ "A context cannot have two different adaptations for the same method.")do
73
+ phen_add_adaptation(:quiet,Phone,:advertise) do |a_call|
74
+ "call waiting signal"
75
+ end
76
+ end
77
+ end
78
+
79
+ def test_invalid_adaptation
80
+ phen_define_context(:temp)
81
+ assert_raise(Phenomenal::Error,
82
+ "Adaptation of inexistent methods should be forbidden.") do
83
+ phen_add_adaptation(:temp,Phone,:phonyAdvertise){|a_call| "vibrator"}
84
+ phen_activate_context(:temp)
85
+ end
86
+ phen_forget_context(:temp)
87
+ end
88
+
89
+ def test_conflicting_activation
90
+ assert(!phen_context_active?(:quiet))
91
+ assert_nothing_raised(Phenomenal::Error,
92
+ "Shoud be OK to activate the quiet context") do
93
+ phen_activate_context(:quiet)
94
+ end
95
+ assert(phen_context_active?(:quiet))
96
+ assert(!phen_context_active?(:offHook))
97
+ assert_raise(Phenomenal::Error,
98
+ "Should conflict with currently active quiet context") do
99
+ phen_activate_context(:offHook)
100
+ end
101
+ assert(!phen_context_active?(:offHook),
102
+ "Should not be mistakenly activated after error")
103
+ end
104
+
105
+ def test_runtime_adding_removing_adaptation
106
+ phone = Phone.new
107
+ call = Call.new("Bob")
108
+ phone.receive(call)
109
+ phen_activate_context(:quiet)
110
+ assert(phen_context_active?(:quiet))
111
+ assert_nothing_raised("Should be ok to remove an active adaptation") do
112
+ phen_remove_adaptation(:quiet,Phone,:advertise)
113
+ end
114
+ assert((phone.advertise(call))=="ringtone",
115
+ "Default behaviour should be expressed")
116
+ assert_nothing_raised("Should be ok to add an active adaptation") do
117
+ phen_add_adaptation(:quiet,Phone,:advertise){|a_call| "vibrator" }
118
+ end
119
+ assert((phone.advertise(call))=="vibrator",
120
+ "Adapted behaviour should be expressed")
121
+ assert_nothing_raised("Should be ok to deactivate the context") do
122
+ phen_deactivate_context(:quiet)
123
+ end
124
+ assert((phone.advertise(call))=="ringtone",
125
+ "Default behaviour should be expressed")
126
+ end
127
+
128
+ def test_instance_variable_access
129
+ t = TestClass.new("VAR")
130
+ assert("VAR"==t.to_s, %(Default to_s should acess var and return
131
+ string value))
132
+ phen_activate_context(:test)
133
+ assert("VAR @access VAR attr_accessor_access"==t.to_s, %(Adapted to_s should
134
+ acess both instance var and accessor meth and return string value))
135
+ phen_deactivate_context(:test)
136
+ assert("VAR"==t.to_s, %(Default to_s should acess var and return
137
+ string value))
138
+ end
139
+
140
+ def test_class_variable_access
141
+ assert(1==TestClass.klass_var_access, %(Default meth should acess var and
142
+ return val))
143
+ phen_activate_context(:test_2)
144
+
145
+ # Doesn't work: Adaptations doesn't have access to class variables
146
+ # Seems to be a Ruby bug
147
+ #TODO
148
+
149
+ #assert(2==TestClass.klass_var_access, %(Adapted meth should
150
+ # acess klass variable and return its value +1))
151
+ phen_deactivate_context(:test_2)
152
+ assert(1==TestClass.klass_var_access, %(Default meth should acess var and
153
+ return val))
154
+ end
155
+
156
+ def test_class_instance_variable_access
157
+ assert(2==TestClass.klass_inst_var_access, %(Default meth should acess var
158
+ and return val))
159
+ phen_activate_context(:test_3)
160
+
161
+ assert(3==TestClass.klass_inst_var_access, %(Adapted meth should
162
+ acess klass variable and return its value +1))
163
+ phen_deactivate_context(:test_3)
164
+ assert(2==TestClass.klass_inst_var_access, %(Default meth should acess var
165
+ and return string value))
166
+ end
167
+ end
168
+