reflekt 0.9.6 → 1.0.1

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.
@@ -1,24 +1,65 @@
1
+ ################################################################################
2
+ # A shadow execution.
3
+ #
4
+ # @hierachy
5
+ # 1. Execution <- YOU ARE HERE
6
+ # 2. Reflection
7
+ # 3. Meta
8
+ ################################################################################
9
+
1
10
  class Execution
2
11
 
3
- attr_accessor :object
12
+ attr_accessor :unique_id
13
+ attr_accessor :caller_object
4
14
  attr_accessor :caller_id
5
15
  attr_accessor :caller_class
16
+ attr_accessor :klass
17
+ attr_accessor :method
18
+ attr_accessor :base
6
19
  attr_accessor :parent
7
20
  attr_accessor :child
8
21
  attr_accessor :control
9
22
  attr_accessor :reflections
10
23
  attr_accessor :is_reflecting
24
+ attr_accessor :is_base
11
25
 
12
- def initialize(object, reflection_count)
26
+ ##
27
+ # Create Execution.
28
+ #
29
+ # @param object [Object] The calling object.
30
+ # @param method [Symbol] The calling method.
31
+ # @param reflect_amount [Integer] The number of reflections to create per execution.
32
+ # @param stack [ShadowStack] The shadow execution call stack.
33
+ ##
34
+ def initialize(caller_object, method, reflect_amount, stack)
13
35
 
14
- @object = object
15
- @caller_id = object.object_id
16
- @caller_class = object.class
36
+ @time = Time.now.to_i
37
+ @unique_id = @time + rand(1..99999)
38
+ @base = nil
17
39
  @parent = nil
18
40
  @child = nil
19
41
 
20
- @control = []
21
- @reflections = Array.new(reflection_count)
42
+ # Dependency.
43
+ @stack = stack
44
+
45
+ # Caller.
46
+ @caller_object = caller_object
47
+ @caller_id = caller_object.object_id
48
+ @caller_class = caller_object.class
49
+ @klass = @caller_class.to_s.to_sym
50
+ @method = method
51
+
52
+ # Reflections.
53
+ @control = nil
54
+ @reflections = Array.new(reflect_amount)
55
+
56
+ # State.
57
+ if @stack.peek() == nil
58
+ @is_base = true
59
+ else
60
+ @is_base = false
61
+ @base = @stack.base()
62
+ end
22
63
  @is_reflecting = false
23
64
 
24
65
  end
@@ -0,0 +1,39 @@
1
+ ################################################################################
2
+ # Metadata for input and output.
3
+ #
4
+ # @pattern Abstract class
5
+ # @see lib/meta for each meta.
6
+ #
7
+ # @hierachy
8
+ # 1. Execution
9
+ # 2. Reflection
10
+ # 3. Meta <- YOU ARE HERE
11
+ ################################################################################
12
+
13
+ class Meta
14
+
15
+ ##
16
+ # Each meta defines its type.
17
+ ##
18
+ def initialize()
19
+ @type = nil
20
+ end
21
+
22
+ ##
23
+ # Each meta loads values.
24
+ #
25
+ # @param value [Dynamic]
26
+ ##
27
+ def load(value)
28
+ end
29
+
30
+ ##
31
+ # Each meta provides metadata.
32
+ #
33
+ # @return [Hash]
34
+ ##
35
+ def result()
36
+ {}
37
+ end
38
+
39
+ end
@@ -0,0 +1,83 @@
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
+ String => :string
77
+ }
78
+
79
+ return meta_types[data_type]
80
+
81
+ end
82
+
83
+ end
@@ -1,167 +1,185 @@
1
+ ################################################################################
2
+ # A snapshot of simulated data.
3
+ #
4
+ # @nomenclature
5
+ # args, inputs/output and meta represent different stages of a value.
6
+ #
7
+ # @hierachy
8
+ # 1. Execution
9
+ # 2. Reflection <- YOU ARE HERE
10
+ # 3. Meta
11
+ ################################################################################
12
+
13
+ require 'Clone'
14
+ require 'MetaBuilder'
15
+
1
16
  class Reflection
2
17
 
3
- # Keys.
4
- TIME = "t"
5
- INPUT = "i"
6
- OUTPUT = "o"
7
- TYPE = "T"
8
- COUNT = "C"
9
- VALUE = "V"
10
- STATUS = "s"
11
- MESSAGE = "m"
12
- # Values.
13
- PASS = "p"
14
- FAIL = "f"
15
-
16
- attr_accessor :clone
18
+ attr_reader :status
17
19
 
18
20
  ##
19
21
  # Create a Reflection.
20
22
  #
21
- # @param Execution execution - The Execution that created this Reflection.
22
- # @param Symbol klass - The class of the method being called.
23
- # @param Symbol method - The method that is being called.
24
- # @param Ruler ruler - The RuleSets for this class/method.
23
+ # @status
24
+ # - :pass The reflection passes the rules.
25
+ # - :fail The reflection fails the rules or produces a system error.
26
+ # - :error The control reflection produces a system error.
27
+ #
28
+ # @param execution [Execution] The Execution that created this Reflection.
29
+ # @param number [Integer] Multiple Reflections can be created per Execution.
30
+ # @param aggregator [Aggregator] The aggregated RuleSet for this class/method.
25
31
  ##
26
- def initialize(execution, klass, method, ruler)
32
+ def initialize(execution, number, aggregator)
27
33
 
28
34
  @execution = execution
29
- @klass = klass
30
- @method = method
31
- @ruler = ruler
35
+ @unique_id = execution.unique_id + number
36
+ @number = number
37
+
38
+ # Dependency.
39
+ @aggregator = aggregator
32
40
 
33
- # Arguments.
34
- @inputs = []
41
+ # Caller.
42
+ @klass = execution.klass
43
+ @method = execution.method
44
+
45
+ # Metadata.
46
+ @inputs = nil
35
47
  @output = nil
36
48
 
37
- # Clone the execution's object.
38
- @clone = execution.object.clone
39
- @clone_id = nil
49
+ # Clone the execution's calling object.
50
+ # TODO: Abstract away into Clone class.
51
+ @clone = execution.caller_object.clone
40
52
 
41
53
  # Result.
42
- @status = PASS
54
+ @status = :pass
43
55
  @time = Time.now.to_i
56
+ @message = nil
44
57
 
45
58
  end
46
59
 
47
60
  ##
48
61
  # Reflect on a method.
49
62
  #
50
- # Creates a shadow execution stack.
51
- #
52
- # @param *args - The method's arguments.
53
- #
54
- # @return - A reflection hash.
63
+ # Creates a shadow execution.
64
+ # @param *args [Dynamic] The method's arguments.
55
65
  ##
56
66
  def reflect(*args)
57
67
 
58
- # Get RuleSets.
59
- input_rule_sets = @ruler.get_input_rule_sets(@klass, @method)
60
- output_rule_set = @ruler.get_output_rule_set(@klass, @method)
61
-
62
- # Create deviated arguments.
63
- args.each do |arg|
64
- case arg
65
- when Integer
66
- @inputs << rand(999)
67
- else
68
- @inputs << arg
69
- end
70
- end
68
+ # Get aggregated rule sets.
69
+ input_rule_sets = @aggregator.get_input_rule_sets(@klass, @method)
70
+ output_rule_set = @aggregator.get_output_rule_set(@klass, @method)
71
71
 
72
- # Action method with new arguments.
73
- begin
72
+ # When arguments exist.
73
+ unless args.size == 0
74
74
 
75
- # Validate input with controls.
75
+ # When aggregated rule sets exist.
76
76
  unless input_rule_sets.nil?
77
- unless @ruler.validate_inputs(@inputs, input_rule_sets)
78
- @status = FAIL
77
+
78
+ # Randomize arguments from rule sets.
79
+ args = randomize(args, input_rule_sets)
80
+
81
+ # Validate arguments against aggregated rule sets.
82
+ unless @aggregator.test_inputs(args, input_rule_sets)
83
+ @status = :fail
79
84
  end
85
+
80
86
  end
81
87
 
88
+ # Create metadata for each argument.
89
+ # TODO: Create metadata for other inputs such as properties on the instance.
90
+ @inputs = MetaBuilder.create_many(args)
91
+
92
+ end
93
+
94
+ # Action method with new/old arguments.
95
+ begin
96
+
82
97
  # Run reflection.
83
- @output = @clone.send(@method, *@inputs)
98
+ output = @clone.send(@method, *args)
99
+ @output = MetaBuilder.create(output)
84
100
 
85
- # Validate output with controls.
101
+ # Validate output with aggregated control rule sets.
86
102
  unless output_rule_set.nil?
87
- unless @ruler.validate_output(@output, output_rule_set)
88
- @status = FAIL
103
+ unless @aggregator.test_output(output, output_rule_set)
104
+ @status = :fail
89
105
  end
90
106
  end
91
107
 
92
- # When fail.
108
+ # When a system error occurs.
93
109
  rescue StandardError => message
94
- @status = FAIL
110
+
111
+ @status = :fail
95
112
  @message = message
113
+
96
114
  end
97
115
 
98
116
  end
99
117
 
100
- def result()
101
- # Build reflection.
102
- reflection = {
103
- TIME => @time,
104
- STATUS => @status,
105
- INPUT => normalize_input(@inputs),
106
- OUTPUT => normalize_output(@output),
107
- MESSAGE => @message
108
- }
109
- end
110
-
111
118
  ##
112
- # Normalize inputs.
119
+ # Create random values for each argument from control reflections.
120
+ #
121
+ # @param args [Dynamic] The arguments to create random values for.
122
+ # @param input_rule_sets [Array] Aggregated rule sets for each argument.
113
123
  #
114
- # @param args - The actual inputs.
115
- # @return - A generic inputs representation.
124
+ # @return [Dynamic] Random arguments.
116
125
  ##
117
- def normalize_input(args)
118
- inputs = []
119
- args.each do |arg|
120
- input = {
121
- TYPE => arg.class.to_s,
122
- VALUE => normalize_value(arg)
123
- }
124
- if (arg.class == Array)
125
- input[COUNT] = arg.count
126
- end
127
- inputs << input
126
+ def randomize(args, input_rule_sets)
127
+
128
+ random_args = []
129
+
130
+ args.each_with_index do |arg, arg_num|
131
+
132
+ rule_type = Aggregator.value_to_rule_type(arg)
133
+ agg_rule = input_rule_sets[arg_num].rules[rule_type]
134
+
135
+ random_args << agg_rule.random()
136
+
128
137
  end
129
- inputs
138
+
139
+ return random_args
140
+
130
141
  end
131
142
 
132
143
  ##
133
- # Normalize output.
144
+ # Get the results of the reflection.
134
145
  #
135
- # @param input - The actual output.
136
- # @return - A generic output representation.
146
+ # @return [Hash] Reflection metadata.
137
147
  ##
138
- def normalize_output(input)
139
-
140
- output = {
141
- TYPE => input.class.to_s,
142
- VALUE => normalize_value(input)
143
- }
148
+ def result()
144
149
 
145
- if (input.class == Array || input.class == Hash)
146
- output[COUNT] = input.count
147
- elsif (input.class == TrueClass || input.class == FalseClass)
148
- output[TYPE] = :Boolean
150
+ # The ID of the first execution in the ShadowStack.
151
+ base_id = nil
152
+ unless @execution.base == nil
153
+ base_id = @execution.base.unique_id
149
154
  end
150
155
 
151
- return output
152
-
153
- end
154
-
155
- def normalize_value(value)
156
+ # Build reflection.
157
+ reflection = {
158
+ :base_id => base_id,
159
+ :exe_id => @execution.unique_id,
160
+ :ref_id => @unique_id,
161
+ :ref_num => @number,
162
+ :time => @time,
163
+ :class => @klass,
164
+ :method => @method,
165
+ :status => @status,
166
+ :message => @message,
167
+ :inputs => nil,
168
+ :output => nil,
169
+ }
156
170
 
157
- unless value.nil?
158
- value = value.to_s.gsub(/\r?\n/, " ").to_s
159
- if value.length >= 30
160
- value = value[0, value.rindex(/\s/,30)].rstrip() + '...'
171
+ unless @inputs.nil?
172
+ reflection[:inputs] = []
173
+ @inputs.each do |meta|
174
+ reflection[:inputs] << meta.result()
161
175
  end
162
176
  end
163
177
 
164
- return value
178
+ unless @output.nil?
179
+ reflection[:output] = @output.result()
180
+ end
181
+
182
+ return reflection
165
183
 
166
184
  end
167
185