reflekt 1.0.1 → 1.0.6

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/{Accessor.rb → accessor.rb} +0 -0
  3. data/lib/{Execution.rb → action.rb} +12 -12
  4. data/lib/action_stack.rb +44 -0
  5. data/lib/{Clone.rb → clone.rb} +4 -4
  6. data/lib/{Config.rb → config.rb} +2 -1
  7. data/lib/{Control.rb → control.rb} +23 -12
  8. data/lib/experiment.rb +81 -0
  9. data/lib/meta.rb +71 -0
  10. data/lib/meta/{ArrayMeta.rb → array_meta.rb} +2 -2
  11. data/lib/meta/{BooleanMeta.rb → boolean_meta.rb} +2 -2
  12. data/lib/meta/{FloatMeta.rb → float_meta.rb} +2 -2
  13. data/lib/meta/{IntegerMeta.rb → integer_meta.rb} +2 -2
  14. data/lib/meta/null_meta.rb +34 -0
  15. data/lib/meta/{StringMeta.rb → string_meta.rb} +2 -2
  16. data/lib/{MetaBuilder.rb → meta_builder.rb} +3 -2
  17. data/lib/reflection.rb +148 -0
  18. data/lib/{Reflekt.rb → reflekt.rb} +44 -44
  19. data/lib/{Renderer.rb → renderer.rb} +0 -0
  20. data/lib/{Rule.rb → rule.rb} +1 -1
  21. data/lib/{RuleSet.rb → rule_set.rb} +26 -20
  22. data/lib/{Aggregator.rb → rule_set_aggregator.rb} +44 -22
  23. data/lib/rules/{ArrayRule.rb → array_rule.rb} +1 -1
  24. data/lib/rules/{BooleanRule.rb → boolean_rule.rb} +6 -4
  25. data/lib/rules/{FloatRule.rb → float_rule.rb} +1 -1
  26. data/lib/rules/{IntegerRule.rb → integer_rule.rb} +1 -1
  27. data/lib/rules/null_rule.rb +33 -0
  28. data/lib/rules/{StringRule.rb → string_rule.rb} +1 -1
  29. data/lib/web/bundle.js +2 -2
  30. data/lib/web/package-lock.json +3 -3
  31. data/lib/web/package.json +1 -1
  32. data/lib/web/server.js +5 -5
  33. metadata +30 -27
  34. data/lib/Meta.rb +0 -39
  35. data/lib/Reflection.rb +0 -186
  36. data/lib/ShadowStack.rb +0 -44
@@ -0,0 +1,34 @@
1
+ ################################################################################
2
+ # A reprsentation of a null value.
3
+ #
4
+ # @note
5
+ # A "null" value on serialized "inputs" and "output" also becomes a NullMeta.
6
+ #
7
+ # @hierachy
8
+ # 1. Action
9
+ # 2. Reflection
10
+ # 3. Meta <- YOU ARE HERE
11
+ ################################################################################
12
+
13
+ require_relative '../meta'
14
+
15
+ class NullMeta < Meta
16
+
17
+ def initialize()
18
+ @type = :null
19
+ end
20
+
21
+ ##
22
+ # @param value [NilClass]
23
+ ##
24
+ def load(value)
25
+ # No need to load a value for null meta.
26
+ end
27
+
28
+ def serialize()
29
+ {
30
+ :type => @type,
31
+ }
32
+ end
33
+
34
+ end
@@ -1,4 +1,4 @@
1
- require 'Meta'
1
+ require_relative '../meta'
2
2
 
3
3
  class StringMeta < Meta
4
4
 
@@ -16,7 +16,7 @@ class StringMeta < Meta
16
16
  @length = value.length
17
17
  end
18
18
 
19
- def result()
19
+ def serialize()
20
20
  {
21
21
  :type => @type,
22
22
  :length => @length
@@ -5,9 +5,9 @@
5
5
  # @see lib/meta for each meta.
6
6
  ################################################################################
7
7
 
8
- require 'Meta'
8
+ require_relative 'meta'
9
9
  # Require all meta.
10
- Dir[File.join(__dir__, 'meta', '*.rb')].each { |file| require file }
10
+ Dir[File.join(__dir__, 'meta', '*.rb')].each { |file| require_relative file }
11
11
 
12
12
  class MetaBuilder
13
13
 
@@ -73,6 +73,7 @@ class MetaBuilder
73
73
  FalseClass => :bool,
74
74
  Float => :float,
75
75
  Integer => :int,
76
+ NilClass => :null,
76
77
  String => :string
77
78
  }
78
79
 
@@ -0,0 +1,148 @@
1
+ ################################################################################
2
+ # A snapshot of real or random data.
3
+ #
4
+ # @pattern Abstract class
5
+ #
6
+ # @nomenclature
7
+ # args, inputs/output and meta represent different stages of a value.
8
+ #
9
+ # @hierachy
10
+ # 1. Action
11
+ # 2. Reflection <- YOU ARE HERE
12
+ # 3. Meta
13
+ #
14
+ # @status
15
+ # - :pass [Symbol] The reflection passes the rules.
16
+ # - :fail [Symbol] The reflection fails the rules or produces a system error.
17
+ # - :error [Symbol] The control reflection produces a system error.
18
+ ################################################################################
19
+
20
+ require_relative 'clone'
21
+ require_relative 'meta_builder'
22
+
23
+ class Reflection
24
+
25
+ attr_reader :status
26
+
27
+ ##
28
+ # Create a reflection.
29
+ #
30
+ # @param action [Action] The Action that created this Reflection.
31
+ # @param number [Integer] Multiple Reflections can be created per Action.
32
+ # @param aggregator [RuleSetAggregator] The aggregated RuleSet for this class/method.
33
+ ##
34
+ def initialize(action, number, aggregator)
35
+
36
+ @action = action
37
+ @unique_id = action.unique_id + number
38
+ @number = number
39
+
40
+ # Dependency.
41
+ @aggregator = aggregator
42
+
43
+ # Caller.
44
+ @klass = action.klass
45
+ @method = action.method
46
+
47
+ # Metadata.
48
+ @inputs = nil
49
+ @output = nil
50
+
51
+ # Clone the action's calling object.
52
+ # TODO: Abstract away into Clone class.
53
+ @clone = action.caller_object.clone
54
+
55
+ # Result.
56
+ @status = :pass
57
+ @time = Time.now.to_i
58
+ @message = nil
59
+
60
+ end
61
+
62
+ ##
63
+ # Reflect on a method.
64
+ #
65
+ # Create a shadow action.
66
+ # @param *args [Dynamic] The method's arguments.
67
+ ##
68
+ def reflect(*args)
69
+ # Implemented by Control and Experiment.
70
+ end
71
+
72
+ ##
73
+ # Create random values for each argument from control reflections.
74
+ #
75
+ # @param args [Dynamic] The arguments to mirror random values for.
76
+ # @param input_rule_sets [Array] Aggregated rule sets for each argument.
77
+ #
78
+ # @return [Dynamic] Random arguments.
79
+ ##
80
+ def randomize(args, input_rule_sets)
81
+
82
+ random_args = []
83
+
84
+ args.each_with_index do |arg, arg_num|
85
+
86
+ # Get a random rule in the rule set.
87
+ rules = input_rule_sets[arg_num].rules
88
+ agg_rule = rules[rules.keys.sample]
89
+
90
+ # Create a random value that follows that rule.
91
+ random_args << agg_rule.random()
92
+
93
+ end
94
+
95
+ return random_args
96
+
97
+ end
98
+
99
+ ##
100
+ # Get the results of the reflection.
101
+ #
102
+ # @keys
103
+ # - eid [Integer] Execution ID
104
+ # - aid [Integer] Action ID
105
+ # - rid [Integer] Reflection ID
106
+ # - num [Integer] Reflection number
107
+ #
108
+ # @return [Hash] Reflection metadata.
109
+ ##
110
+ def serialize()
111
+
112
+ # Create execution ID from the ID of the first action in the ActionStack.
113
+ execution_id = @action.unique_id
114
+ unless @action.base.nil?
115
+ execution_id = @action.base.unique_id
116
+ end
117
+
118
+ # Build reflection.
119
+ reflection = {
120
+ :eid => execution_id,
121
+ :aid => @action.unique_id,
122
+ :rid => @unique_id,
123
+ :num => @number,
124
+ :time => @time,
125
+ :class => @klass,
126
+ :method => @method,
127
+ :status => @status,
128
+ :message => @message,
129
+ :inputs => nil,
130
+ :output => nil,
131
+ }
132
+
133
+ unless @inputs.nil?
134
+ reflection[:inputs] = []
135
+ @inputs.each do |meta|
136
+ reflection[:inputs] << meta.serialize()
137
+ end
138
+ end
139
+
140
+ unless @output.nil?
141
+ reflection[:output] = @output.serialize()
142
+ end
143
+
144
+ return reflection
145
+
146
+ end
147
+
148
+ end
@@ -6,8 +6,8 @@
6
6
  # @flow
7
7
  # 1. Reflekt is prepended to a class and setup.
8
8
  # 2. When a class insantiates so does Reflekt.
9
- # 3. An Execution is created on method call.
10
- # 4. Many Refections are created per Execution.
9
+ # 3. An Action is created on method call.
10
+ # 4. Many Refections are created per Action.
11
11
  # 5. Each Reflection executes on cloned data.
12
12
  # 6. Flow is returned to the original method.
13
13
  #
@@ -19,16 +19,16 @@
19
19
  require 'set'
20
20
  require 'erb'
21
21
  require 'rowdb'
22
- require 'Accessor'
23
- require 'Aggregator'
24
- require 'Config'
25
- require 'Control'
26
- require 'Execution'
27
- require 'Reflection'
28
- require 'Renderer'
29
- require 'ShadowStack'
22
+ require_relative 'accessor'
23
+ require_relative 'action'
24
+ require_relative 'action_stack'
25
+ require_relative 'config'
26
+ require_relative 'control'
27
+ require_relative 'experiment'
28
+ require_relative 'renderer'
29
+ require_relative 'rule_set_aggregator'
30
30
  # Require all rules.
31
- Dir[File.join(__dir__, 'rules', '*.rb')].each { |file| require file }
31
+ Dir[File.join(__dir__, 'rules', '*.rb')].each { |file| require_relative file }
32
32
 
33
33
  module Reflekt
34
34
 
@@ -53,34 +53,34 @@ module Reflekt
53
53
  # When Reflekt enabled and control reflection has executed without error.
54
54
  if @@reflekt.config.enabled && !@@reflekt.error
55
55
 
56
- # Get current execution.
57
- execution = @@reflekt.stack.peek()
56
+ # Get current action.
57
+ action = @@reflekt.stack.peek()
58
58
 
59
59
  # Don't reflect when reflect limit reached or method skipped.
60
60
  unless (@reflekt_counts[method] >= @@reflekt.config.reflect_limit) || self.class.reflekt_skipped?(method)
61
61
 
62
- # When stack empty or past execution done reflecting.
63
- if execution.nil? || execution.has_finished_reflecting?
62
+ # When stack empty or past action done reflecting.
63
+ if action.nil? || action.has_finished_reflecting?
64
64
 
65
- # Create execution.
66
- execution = Execution.new(self, method, @@reflekt.config.reflect_amount, @@reflekt.stack)
65
+ # Create action.
66
+ action = Action.new(self, method, @@reflekt.config.reflect_amount, @@reflekt.stack)
67
67
 
68
- @@reflekt.stack.push(execution)
68
+ @@reflekt.stack.push(action)
69
69
 
70
70
  end
71
71
 
72
72
  ##
73
- # Reflect the execution.
73
+ # Reflect the action.
74
74
  #
75
- # The first method call in the execution creates a reflection.
76
- # Then method calls are shadow executions which return to the reflection.
75
+ # The first method call in the action creates a reflection.
76
+ # Then method calls are shadow actions which return to the reflection.
77
77
  ##
78
- if execution.has_empty_reflections? && !execution.is_reflecting?
79
- execution.is_reflecting = true
78
+ if action.has_empty_experiments? && !action.is_reflecting?
79
+ action.is_reflecting = true
80
80
 
81
81
  # Create control.
82
- control = Control.new(execution, 0, @@reflekt.aggregator)
83
- execution.control = control
82
+ control = Control.new(action, 0, @@reflekt.aggregator)
83
+ action.control = control
84
84
 
85
85
  # Execute control.
86
86
  control.reflect(*args)
@@ -91,27 +91,27 @@ module Reflekt
91
91
  # Continue reflecting when control executes succesfully.
92
92
  else
93
93
 
94
- # Save control as reflection.
95
- @@reflekt.db.get("reflections").push(control.result())
94
+ # Save control as a reflection.
95
+ @@reflekt.db.get("reflections").push(control.serialize())
96
96
 
97
- # Multiple reflections per execution.
98
- execution.reflections.each_with_index do |value, index|
97
+ # Multiple experiments per action.
98
+ action.experiments.each_with_index do |value, index|
99
99
 
100
- # Create reflection.
101
- reflection = Reflection.new(execution, index + 1, @@reflekt.aggregator)
102
- execution.reflections[index] = reflection
100
+ # Create experiment.
101
+ experiment = Experiment.new(action, index + 1, @@reflekt.aggregator)
102
+ action.experiments[index] = experiment
103
103
 
104
- # Execute reflection.
105
- reflection.reflect(*args)
104
+ # Execute experiment.
105
+ experiment.reflect(*args)
106
106
  @reflekt_counts[method] = @reflekt_counts[method] + 1
107
107
 
108
- # Save reflection.
109
- @@reflekt.db.get("reflections").push(reflection.result())
108
+ # Save experiment.
109
+ @@reflekt.db.get("reflections").push(experiment.serialize())
110
110
 
111
111
  end
112
112
 
113
113
  # Save control.
114
- @@reflekt.db.get("controls").push(control.result())
114
+ @@reflekt.db.get("controls").push(control.serialize())
115
115
 
116
116
  # Save results.
117
117
  @@reflekt.db.write()
@@ -121,15 +121,15 @@ module Reflekt
121
121
 
122
122
  end
123
123
 
124
- execution.is_reflecting = false
124
+ action.is_reflecting = false
125
125
  end
126
126
 
127
127
  end
128
128
 
129
129
  # Don't execute skipped methods when reflecting.
130
- unless execution.is_reflecting? && self.class.reflekt_skipped?(method)
130
+ unless action.is_reflecting? && self.class.reflekt_skipped?(method)
131
131
 
132
- # Continue execution / shadow execution.
132
+ # Continue action / shadow action.
133
133
  super *args
134
134
 
135
135
  end
@@ -137,7 +137,7 @@ module Reflekt
137
137
  # When Reflekt disabled or control reflection failed.
138
138
  else
139
139
 
140
- # Continue execution.
140
+ # Continue action.
141
141
  super *args
142
142
 
143
143
  end
@@ -180,7 +180,7 @@ module Reflekt
180
180
  # Set configuration.
181
181
  @@reflekt.path = File.dirname(File.realpath(__FILE__))
182
182
 
183
- # Get reflections directory path from config or current execution path.
183
+ # Get reflections directory path from config or current action path.
184
184
  if @@reflekt.config.output_path
185
185
  @@reflekt.output_path = File.join(@@reflekt.config.output_path, @@reflekt.config.output_directory)
186
186
  else
@@ -199,10 +199,10 @@ module Reflekt
199
199
  db = @@reflekt.db.value()
200
200
 
201
201
  # Create shadow stack.
202
- @@reflekt.stack = ShadowStack.new()
202
+ @@reflekt.stack = ActionStack.new()
203
203
 
204
204
  # Create aggregated rule sets.
205
- @@reflekt.aggregator = Aggregator.new(@@reflekt.config.meta_map)
205
+ @@reflekt.aggregator = RuleSetAggregator.new(@@reflekt.config.meta_map)
206
206
  @@reflekt.aggregator.train(db[:controls])
207
207
 
208
208
  # Create renderer.
File without changes
@@ -4,7 +4,7 @@
4
4
  # @pattern Abstract class
5
5
  #
6
6
  # @hierachy
7
- # 1. Aggregator
7
+ # 1. RuleSetAggregator
8
8
  # 2. RuleSet
9
9
  # 3. Rule <- YOU ARE HERE
10
10
  #
@@ -6,13 +6,14 @@
6
6
  # - Builder
7
7
  #
8
8
  # @hierachy
9
- # 1. Aggregator
9
+ # 1. RuleSetAggregator
10
10
  # 2. RuleSet <- YOU ARE HERE
11
11
  # 3. Rule
12
12
  ################################################################################
13
13
 
14
14
  require 'set'
15
- require 'MetaBuilder'
15
+ require_relative 'meta_builder'
16
+ require_relative 'meta/null_meta.rb'
16
17
 
17
18
  class RuleSet
18
19
 
@@ -37,40 +38,44 @@ class RuleSet
37
38
  ##
38
39
  # Train rule set on metadata.
39
40
  #
40
- # @param meta [Meta] The metadata to train on.
41
+ # @param meta [Hash] The metadata to train on.
41
42
  ##
42
43
  def train(meta)
43
44
 
44
- unless meta.nil? || meta[:type].nil?
45
+ # Track supported meta types.
46
+ meta_type = meta[:type]
47
+ @meta_types << meta_type
45
48
 
46
- meta_type = meta[:type]
47
- @meta_types << meta_type
49
+ # Get rule types for this meta type.
50
+ if @meta_map.key? meta_type
51
+ @meta_map[meta_type].each do |rule_type|
48
52
 
49
- # Get rule types for this meta type.
50
- if @meta_map.key? meta_type
51
- @meta_map[meta_type].each do |rule_type|
52
-
53
- # Ensure rule exists.
54
- if @rules[rule_type].nil?
55
- @rules[rule_type] = rule_type.new()
56
- end
53
+ # Ensure rule exists.
54
+ if @rules[rule_type].nil?
55
+ @rules[rule_type] = rule_type.new()
56
+ end
57
57
 
58
- # Train rule.
59
- @rules[rule_type].train(meta)
58
+ # Train rule.
59
+ @rules[rule_type].train(meta)
60
60
 
61
- end
62
61
  end
63
-
64
62
  end
65
63
 
66
64
  end
67
65
 
66
+ ##
67
+ # @param value [Dynamic]
68
+ ##
68
69
  def test(value)
69
- result = true
70
70
 
71
- # Only test data type on rule of matching meta type.
71
+ result = true
72
72
  meta_type = MetaBuilder.data_type_to_meta_type(value)
73
73
 
74
+ # Fail if value's meta type not testable by rule set.
75
+ unless @meta_types.include? meta_type
76
+ return false
77
+ end
78
+
74
79
  @rules.each do |klass, rule|
75
80
  if (rule.type == meta_type)
76
81
  unless rule.test(value)
@@ -80,6 +85,7 @@ class RuleSet
80
85
  end
81
86
 
82
87
  return result
88
+
83
89
  end
84
90
 
85
91
  ##