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.
- checksums.yaml +4 -4
- data/lib/{Accessor.rb → accessor.rb} +0 -0
- data/lib/{Execution.rb → action.rb} +12 -12
- data/lib/action_stack.rb +44 -0
- data/lib/{Clone.rb → clone.rb} +4 -4
- data/lib/{Config.rb → config.rb} +2 -1
- data/lib/{Control.rb → control.rb} +23 -12
- data/lib/experiment.rb +81 -0
- data/lib/meta.rb +71 -0
- data/lib/meta/{ArrayMeta.rb → array_meta.rb} +2 -2
- data/lib/meta/{BooleanMeta.rb → boolean_meta.rb} +2 -2
- data/lib/meta/{FloatMeta.rb → float_meta.rb} +2 -2
- data/lib/meta/{IntegerMeta.rb → integer_meta.rb} +2 -2
- data/lib/meta/null_meta.rb +34 -0
- data/lib/meta/{StringMeta.rb → string_meta.rb} +2 -2
- data/lib/{MetaBuilder.rb → meta_builder.rb} +3 -2
- data/lib/reflection.rb +148 -0
- data/lib/{Reflekt.rb → reflekt.rb} +44 -44
- data/lib/{Renderer.rb → renderer.rb} +0 -0
- data/lib/{Rule.rb → rule.rb} +1 -1
- data/lib/{RuleSet.rb → rule_set.rb} +26 -20
- data/lib/{Aggregator.rb → rule_set_aggregator.rb} +44 -22
- data/lib/rules/{ArrayRule.rb → array_rule.rb} +1 -1
- data/lib/rules/{BooleanRule.rb → boolean_rule.rb} +6 -4
- data/lib/rules/{FloatRule.rb → float_rule.rb} +1 -1
- data/lib/rules/{IntegerRule.rb → integer_rule.rb} +1 -1
- data/lib/rules/null_rule.rb +33 -0
- data/lib/rules/{StringRule.rb → string_rule.rb} +1 -1
- data/lib/web/bundle.js +2 -2
- data/lib/web/package-lock.json +3 -3
- data/lib/web/package.json +1 -1
- data/lib/web/server.js +5 -5
- metadata +30 -27
- data/lib/Meta.rb +0 -39
- data/lib/Reflection.rb +0 -186
- 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
|
@@ -5,9 +5,9 @@
|
|
5
5
|
# @see lib/meta for each meta.
|
6
6
|
################################################################################
|
7
7
|
|
8
|
-
|
8
|
+
require_relative 'meta'
|
9
9
|
# Require all meta.
|
10
|
-
Dir[File.join(__dir__, 'meta', '*.rb')].each { |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
|
|
data/lib/reflection.rb
ADDED
@@ -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
|
10
|
-
# 4. Many Refections are created per
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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|
|
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
|
57
|
-
|
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
|
63
|
-
if
|
62
|
+
# When stack empty or past action done reflecting.
|
63
|
+
if action.nil? || action.has_finished_reflecting?
|
64
64
|
|
65
|
-
# Create
|
66
|
-
|
65
|
+
# Create action.
|
66
|
+
action = Action.new(self, method, @@reflekt.config.reflect_amount, @@reflekt.stack)
|
67
67
|
|
68
|
-
@@reflekt.stack.push(
|
68
|
+
@@reflekt.stack.push(action)
|
69
69
|
|
70
70
|
end
|
71
71
|
|
72
72
|
##
|
73
|
-
# Reflect the
|
73
|
+
# Reflect the action.
|
74
74
|
#
|
75
|
-
# The first method call in the
|
76
|
-
# Then method calls are shadow
|
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
|
79
|
-
|
78
|
+
if action.has_empty_experiments? && !action.is_reflecting?
|
79
|
+
action.is_reflecting = true
|
80
80
|
|
81
81
|
# Create control.
|
82
|
-
control = Control.new(
|
83
|
-
|
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.
|
94
|
+
# Save control as a reflection.
|
95
|
+
@@reflekt.db.get("reflections").push(control.serialize())
|
96
96
|
|
97
|
-
# Multiple
|
98
|
-
|
97
|
+
# Multiple experiments per action.
|
98
|
+
action.experiments.each_with_index do |value, index|
|
99
99
|
|
100
|
-
# Create
|
101
|
-
|
102
|
-
|
100
|
+
# Create experiment.
|
101
|
+
experiment = Experiment.new(action, index + 1, @@reflekt.aggregator)
|
102
|
+
action.experiments[index] = experiment
|
103
103
|
|
104
|
-
# Execute
|
105
|
-
|
104
|
+
# Execute experiment.
|
105
|
+
experiment.reflect(*args)
|
106
106
|
@reflekt_counts[method] = @reflekt_counts[method] + 1
|
107
107
|
|
108
|
-
# Save
|
109
|
-
@@reflekt.db.get("reflections").push(
|
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.
|
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
|
-
|
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
|
130
|
+
unless action.is_reflecting? && self.class.reflekt_skipped?(method)
|
131
131
|
|
132
|
-
# Continue
|
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
|
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
|
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 =
|
202
|
+
@@reflekt.stack = ActionStack.new()
|
203
203
|
|
204
204
|
# Create aggregated rule sets.
|
205
|
-
@@reflekt.aggregator =
|
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
|
data/lib/{Rule.rb → rule.rb}
RENAMED
@@ -6,13 +6,14 @@
|
|
6
6
|
# - Builder
|
7
7
|
#
|
8
8
|
# @hierachy
|
9
|
-
# 1.
|
9
|
+
# 1. RuleSetAggregator
|
10
10
|
# 2. RuleSet <- YOU ARE HERE
|
11
11
|
# 3. Rule
|
12
12
|
################################################################################
|
13
13
|
|
14
14
|
require 'set'
|
15
|
-
|
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 [
|
41
|
+
# @param meta [Hash] The metadata to train on.
|
41
42
|
##
|
42
43
|
def train(meta)
|
43
44
|
|
44
|
-
|
45
|
+
# Track supported meta types.
|
46
|
+
meta_type = meta[:type]
|
47
|
+
@meta_types << meta_type
|
45
48
|
|
46
|
-
|
47
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
59
|
-
|
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
|
-
|
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
|
##
|