reflekt 1.0.5 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/accessor.rb +45 -0
  3. data/lib/action.rb +127 -0
  4. data/lib/action_stack.rb +44 -0
  5. data/lib/{Clone.rb → clone.rb} +11 -11
  6. data/lib/config.rb +48 -0
  7. data/lib/control.rb +81 -0
  8. data/lib/experiment.rb +99 -0
  9. data/lib/meta.rb +75 -0
  10. data/lib/meta/array_meta.rb +32 -0
  11. data/lib/meta/boolean_meta.rb +26 -0
  12. data/lib/meta/float_meta.rb +26 -0
  13. data/lib/meta/integer_meta.rb +26 -0
  14. data/lib/meta/{NullMeta.rb → null_meta.rb} +21 -19
  15. data/lib/meta/object_meta.rb +35 -0
  16. data/lib/meta/string_meta.rb +26 -0
  17. data/lib/meta_builder.rb +100 -0
  18. data/lib/reflection.rb +123 -0
  19. data/lib/reflekt.rb +277 -0
  20. data/lib/renderer.rb +38 -0
  21. data/lib/rule.rb +54 -0
  22. data/lib/rule_set.rb +110 -0
  23. data/lib/rule_set_aggregator.rb +260 -0
  24. data/lib/rules/array_rule.rb +94 -0
  25. data/lib/rules/boolean_rule.rb +43 -0
  26. data/lib/rules/float_rule.rb +55 -0
  27. data/lib/rules/integer_rule.rb +55 -0
  28. data/lib/rules/null_rule.rb +35 -0
  29. data/lib/rules/object_rule.rb +42 -0
  30. data/lib/rules/string_rule.rb +75 -0
  31. data/lib/web/index.html +3 -4
  32. metadata +46 -29
  33. data/lib/Accessor.rb +0 -37
  34. data/lib/Action.rb +0 -88
  35. data/lib/ActionStack.rb +0 -44
  36. data/lib/Aggregator.rb +0 -260
  37. data/lib/Config.rb +0 -42
  38. data/lib/Control.rb +0 -83
  39. data/lib/Meta.rb +0 -71
  40. data/lib/MetaBuilder.rb +0 -84
  41. data/lib/Reflection.rb +0 -195
  42. data/lib/Reflekt.rb +0 -243
  43. data/lib/Renderer.rb +0 -39
  44. data/lib/Rule.rb +0 -52
  45. data/lib/RuleSet.rb +0 -109
  46. data/lib/meta/ArrayMeta.rb +0 -34
  47. data/lib/meta/BooleanMeta.rb +0 -26
  48. data/lib/meta/FloatMeta.rb +0 -26
  49. data/lib/meta/IntegerMeta.rb +0 -26
  50. data/lib/meta/StringMeta.rb +0 -26
  51. data/lib/rules/ArrayRule.rb +0 -88
  52. data/lib/rules/BooleanRule.rb +0 -47
  53. data/lib/rules/FloatRule.rb +0 -57
  54. data/lib/rules/IntegerRule.rb +0 -57
  55. data/lib/rules/NullRule.rb +0 -33
  56. data/lib/rules/StringRule.rb +0 -81
data/lib/MetaBuilder.rb DELETED
@@ -1,84 +0,0 @@
1
- ################################################################################
2
- # Create metadata.
3
- #
4
- # @pattern Builder
5
- # @see lib/meta for each meta.
6
- ################################################################################
7
-
8
- require 'Meta'
9
- # Require all meta.
10
- Dir[File.join(__dir__, 'meta', '*.rb')].each { |file| require file }
11
-
12
- class MetaBuilder
13
-
14
- ##
15
- # Create meta.
16
- #
17
- # @param value
18
- ##
19
- def self.create(value)
20
-
21
- meta = nil
22
- data_type = value.class.to_s
23
-
24
- # Create meta type for matching data type.
25
- case data_type
26
- when "Array"
27
- meta = ArrayMeta.new()
28
- when "TrueClass", "FalseClass"
29
- meta = BooleanMeta.new()
30
- when "Float"
31
- meta = FloatMeta.new()
32
- when "Integer"
33
- meta = IntegerMeta.new()
34
- when "String"
35
- meta = StringMeta.new()
36
- end
37
-
38
- unless meta.nil?
39
- meta.load(value)
40
- end
41
-
42
- return meta
43
-
44
- end
45
-
46
- ##
47
- # Create meta for multiple values.
48
- #
49
- # @param values
50
- ##
51
- def self.create_many(values)
52
-
53
- meta = []
54
-
55
- values.each do |value|
56
- meta << self.create(value)
57
- end
58
-
59
- return meta
60
-
61
- end
62
-
63
- ##
64
- # @param data_type [Type]
65
- ##
66
- def self.data_type_to_meta_type(value)
67
-
68
- data_type = value.class
69
-
70
- meta_types = {
71
- Array => :array,
72
- TrueClass => :bool,
73
- FalseClass => :bool,
74
- Float => :float,
75
- Integer => :int,
76
- NilClass => :null,
77
- String => :string
78
- }
79
-
80
- return meta_types[data_type]
81
-
82
- end
83
-
84
- end
data/lib/Reflection.rb DELETED
@@ -1,195 +0,0 @@
1
- ################################################################################
2
- # A snapshot of random data.
3
- #
4
- # @note
5
- # A reflection's random value is within the bounds of aggregated control rule sets
6
- # as well as as the arg type being inputted into the current control reflection.
7
- #
8
- # @nomenclature
9
- # args, inputs/output and meta represent different stages of a value.
10
- #
11
- # @hierachy
12
- # 1. Action
13
- # 2. Reflection <- YOU ARE HERE
14
- # 3. Meta
15
- #
16
- # @status
17
- # - :pass [Symbol] The reflection passes the rules.
18
- # - :fail [Symbol] The reflection fails the rules or produces a system error.
19
- # - :error [Symbol] The control reflection produces a system error.
20
- ################################################################################
21
-
22
- require 'Clone'
23
- require 'MetaBuilder'
24
-
25
- class Reflection
26
-
27
- attr_reader :status
28
-
29
- ##
30
- # Create a Reflection.
31
- #
32
- # @param action [Action] The Action that created this Reflection.
33
- # @param number [Integer] Multiple Reflections can be created per Action.
34
- # @param aggregator [Aggregator] The aggregated RuleSet for this class/method.
35
- ##
36
- def initialize(action, number, aggregator)
37
-
38
- @action = action
39
- @unique_id = action.unique_id + number
40
- @number = number
41
-
42
- # Dependency.
43
- @aggregator = aggregator
44
-
45
- # Caller.
46
- @klass = action.klass
47
- @method = action.method
48
-
49
- # Metadata.
50
- @inputs = nil
51
- @output = nil
52
-
53
- # Clone the action's calling object.
54
- # TODO: Abstract away into Clone class.
55
- @clone = action.caller_object.clone
56
-
57
- # Result.
58
- @status = :pass
59
- @time = Time.now.to_i
60
- @message = nil
61
-
62
- end
63
-
64
- ##
65
- # Reflect on a method.
66
- #
67
- # Creates a shadow action.
68
- # @param *args [Dynamic] The method's arguments.
69
- ##
70
- def reflect(*args)
71
-
72
- # Get aggregated rule sets.
73
- input_rule_sets = @aggregator.get_input_rule_sets(@klass, @method)
74
- output_rule_set = @aggregator.get_output_rule_set(@klass, @method)
75
-
76
- # Fail when no trained rule sets.
77
- if input_rule_sets.nil?
78
- @status = :fail
79
- end
80
-
81
- # When arguments exist.
82
- unless args.size == 0
83
-
84
- # Create random arguments from aggregated rule sets.
85
- unless input_rule_sets.nil?
86
- args = randomize(args, input_rule_sets)
87
- end
88
-
89
- # Create metadata for each argument.
90
- # TODO: Create metadata for other inputs such as instance variables.
91
- @inputs = MetaBuilder.create_many(args)
92
-
93
- end
94
-
95
- # Action method with random arguments.
96
- begin
97
-
98
- # Run reflection.
99
- output = @clone.send(@method, *args)
100
- @output = MetaBuilder.create(output)
101
-
102
- # Validate output against aggregated control rule sets.
103
- unless output_rule_set.nil?
104
- unless @aggregator.test_output(output, output_rule_set)
105
- @status = :fail
106
- end
107
- end
108
-
109
- # When a system error occurs.
110
- rescue StandardError => message
111
-
112
- @status = :fail
113
- @message = message
114
-
115
- end
116
-
117
- end
118
-
119
- ##
120
- # Create random values for each argument from control reflections.
121
- #
122
- # @param args [Dynamic] The arguments to mirror random values for.
123
- # @param input_rule_sets [Array] Aggregated rule sets for each argument.
124
- #
125
- # @return [Dynamic] Random arguments.
126
- ##
127
- def randomize(args, input_rule_sets)
128
-
129
- random_args = []
130
-
131
- args.each_with_index do |arg, arg_num|
132
-
133
- # Get a random rule in the rule set.
134
- rules = input_rule_sets[arg_num].rules
135
- agg_rule = rules[rules.keys.sample]
136
-
137
- # Create a random value that follows that rule.
138
- random_args << agg_rule.random()
139
-
140
- end
141
-
142
- return random_args
143
-
144
- end
145
-
146
- ##
147
- # Get the results of the reflection.
148
- #
149
- # @keys
150
- # - eid [Integer] Execution ID
151
- # - aid [Integer] Action ID
152
- # - rid [Integer] Reflection ID
153
- # - num [Integer] Reflection number
154
- #
155
- # @return [Hash] Reflection metadata.
156
- ##
157
- def serialize()
158
-
159
- # Create execution ID from the ID of the first action in the ActionStack.
160
- execution_id = @action.unique_id
161
- unless @action.base.nil?
162
- execution_id = @action.base.unique_id
163
- end
164
-
165
- # Build reflection.
166
- reflection = {
167
- :eid => execution_id,
168
- :aid => @action.unique_id,
169
- :rid => @unique_id,
170
- :num => @number,
171
- :time => @time,
172
- :class => @klass,
173
- :method => @method,
174
- :status => @status,
175
- :message => @message,
176
- :inputs => nil,
177
- :output => nil,
178
- }
179
-
180
- unless @inputs.nil?
181
- reflection[:inputs] = []
182
- @inputs.each do |meta|
183
- reflection[:inputs] << meta.serialize()
184
- end
185
- end
186
-
187
- unless @output.nil?
188
- reflection[:output] = @output.serialize()
189
- end
190
-
191
- return reflection
192
-
193
- end
194
-
195
- end
data/lib/Reflekt.rb DELETED
@@ -1,243 +0,0 @@
1
- ################################################################################
2
- # Reflective testing.
3
- #
4
- # @author Maedi Prichard
5
- #
6
- # @flow
7
- # 1. Reflekt is prepended to a class and setup.
8
- # 2. When a class insantiates so does Reflekt.
9
- # 3. An Action is created on method call.
10
- # 4. Many Refections are created per Action.
11
- # 5. Each Reflection executes on cloned data.
12
- # 6. Flow is returned to the original method.
13
- #
14
- # @usage
15
- # class ExampleClass
16
- # prepend Reflekt
17
- ################################################################################
18
-
19
- require 'set'
20
- require 'erb'
21
- require 'rowdb'
22
- require 'Accessor'
23
- require 'Action'
24
- require 'ActionStack'
25
- require 'Aggregator'
26
- require 'Config'
27
- require 'Control'
28
- require 'Reflection'
29
- require 'Renderer'
30
- # Require all rules.
31
- Dir[File.join(__dir__, 'rules', '*.rb')].each { |file| require file }
32
-
33
- module Reflekt
34
-
35
- def initialize(*args)
36
-
37
- # TODO: Store counts on @@reflekt and key by instance ID.
38
- @reflekt_counts = {}
39
-
40
- # Get child and parent instance methods.
41
- parent_instance_methods = self.class.superclass.instance_methods(false)
42
- child_instance_methods = self.class.instance_methods(false)
43
- instance_methods = parent_instance_methods + child_instance_methods
44
-
45
- # TODO: Include core methods like "Array.include?".
46
- instance_methods.each do |method|
47
-
48
- @reflekt_counts[method] = 0
49
-
50
- # When method called in flow.
51
- self.define_singleton_method(method) do |*args|
52
-
53
- # When Reflekt enabled and control reflection has executed without error.
54
- if @@reflekt.config.enabled && !@@reflekt.error
55
-
56
- # Get current action.
57
- action = @@reflekt.stack.peek()
58
-
59
- # Don't reflect when reflect limit reached or method skipped.
60
- unless (@reflekt_counts[method] >= @@reflekt.config.reflect_limit) || self.class.reflekt_skipped?(method)
61
-
62
- # When stack empty or past action done reflecting.
63
- if action.nil? || action.has_finished_reflecting?
64
-
65
- # Create action.
66
- action = Action.new(self, method, @@reflekt.config.reflect_amount, @@reflekt.stack)
67
-
68
- @@reflekt.stack.push(action)
69
-
70
- end
71
-
72
- ##
73
- # Reflect the action.
74
- #
75
- # The first method call in the action creates a reflection.
76
- # Then method calls are shadow actions which return to the reflection.
77
- ##
78
- if action.has_empty_reflections? && !action.is_reflecting?
79
- action.is_reflecting = true
80
-
81
- # Create control.
82
- control = Control.new(action, 0, @@reflekt.aggregator)
83
- action.control = control
84
-
85
- # Execute control.
86
- control.reflect(*args)
87
-
88
- # Stop reflecting when control fails to execute.
89
- if control.status == :error
90
- @@reflekt.error = true
91
- # Continue reflecting when control executes succesfully.
92
- else
93
-
94
- # Save control as a reflection.
95
- @@reflekt.db.get("reflections").push(control.serialize())
96
-
97
- # Multiple reflections per action.
98
- action.reflections.each_with_index do |value, index|
99
-
100
- # Create reflection.
101
- reflection = Reflection.new(action, index + 1, @@reflekt.aggregator)
102
- action.reflections[index] = reflection
103
-
104
- # Execute reflection.
105
- reflection.reflect(*args)
106
- @reflekt_counts[method] = @reflekt_counts[method] + 1
107
-
108
- # Save reflection.
109
- @@reflekt.db.get("reflections").push(reflection.serialize())
110
-
111
- end
112
-
113
- # Save control.
114
- @@reflekt.db.get("controls").push(control.serialize())
115
-
116
- # Save results.
117
- @@reflekt.db.write()
118
-
119
- # Render results.
120
- @@reflekt.renderer.render()
121
-
122
- end
123
-
124
- action.is_reflecting = false
125
- end
126
-
127
- end
128
-
129
- # Don't execute skipped methods when reflecting.
130
- unless action.is_reflecting? && self.class.reflekt_skipped?(method)
131
-
132
- # Continue action / shadow action.
133
- super *args
134
-
135
- end
136
-
137
- # When Reflekt disabled or control reflection failed.
138
- else
139
-
140
- # Continue action.
141
- super *args
142
-
143
- end
144
-
145
- end
146
-
147
- end
148
-
149
- # Continue initialization.
150
- super
151
-
152
- end
153
-
154
- ##
155
- # Provide Config instance to block.
156
- ##
157
- def self.configure
158
- yield(@@reflekt.config)
159
- end
160
-
161
- private
162
-
163
- def self.prepended(base)
164
-
165
- # Prepend class methods to the instance's singleton class.
166
- base.singleton_class.prepend(SingletonClassMethods)
167
-
168
- # Setup class.
169
- @@reflekt = Accessor.new()
170
- @@reflekt.setup ||= reflekt_setup_class
171
-
172
- end
173
-
174
- # Setup class.
175
- def self.reflekt_setup_class()
176
-
177
- # Receive configuration.
178
- @@reflekt.config = Config.new()
179
-
180
- # Set configuration.
181
- @@reflekt.path = File.dirname(File.realpath(__FILE__))
182
-
183
- # Get reflections directory path from config or current action path.
184
- if @@reflekt.config.output_path
185
- @@reflekt.output_path = File.join(@@reflekt.config.output_path, @@reflekt.config.output_directory)
186
- else
187
- @@reflekt.output_path = File.join(Dir.pwd, @@reflekt.config.output_directory)
188
- end
189
-
190
- # Create reflections directory.
191
- unless Dir.exist? @@reflekt.output_path
192
- Dir.mkdir(@@reflekt.output_path)
193
- end
194
-
195
- # Create database.
196
- @@reflekt.db = Rowdb.new(@@reflekt.output_path + '/db.js')
197
- @@reflekt.db.defaults({ :reflekt => { :api_version => 1 }})
198
- # @TODO Fix Rowdb.get(path) not returning values at path after Rowdb.push()
199
- db = @@reflekt.db.value()
200
-
201
- # Create shadow stack.
202
- @@reflekt.stack = ActionStack.new()
203
-
204
- # Create aggregated rule sets.
205
- @@reflekt.aggregator = Aggregator.new(@@reflekt.config.meta_map)
206
- @@reflekt.aggregator.train(db[:controls])
207
-
208
- # Create renderer.
209
- @@reflekt.renderer = Renderer.new(@@reflekt.path, @@reflekt.output_path)
210
-
211
- return true
212
-
213
- end
214
-
215
- module SingletonClassMethods
216
-
217
- @@reflekt_skipped_methods = Set.new()
218
-
219
- ##
220
- # Skip a method.
221
- #
222
- # @note
223
- # Class variables cascade to child classes.
224
- # So a reflekt_skip on the parent class will persist to the child class.
225
- #
226
- # @param method [Symbol] The method name.
227
- ##
228
- def reflekt_skip(method)
229
- @@reflekt_skipped_methods.add(method)
230
- end
231
-
232
- def reflekt_skipped?(method)
233
- return true if @@reflekt_skipped_methods.include?(method)
234
- false
235
- end
236
-
237
- #def reflekt_limit(amount)
238
- # @@reflekt.reflect_limit = amount
239
- #end
240
-
241
- end
242
-
243
- end