reflekt 0.9.6 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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