reflekt 0.9.2 → 0.9.8
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 +37 -0
- data/lib/Aggregator.rb +193 -0
- data/lib/Control.rb +18 -8
- data/lib/Execution.rb +39 -7
- data/lib/Meta.rb +27 -0
- data/lib/MetaBuilder.rb +56 -0
- data/lib/Reflection.rb +104 -104
- data/lib/Reflekt.rb +205 -0
- data/lib/Renderer.rb +39 -0
- data/lib/Rule.rb +24 -26
- data/lib/RuleSet.rb +105 -0
- data/lib/ShadowStack.rb +8 -22
- data/lib/meta/IntegerMeta.rb +27 -0
- data/lib/meta/StringMeta.rb +27 -0
- data/lib/rules/IntegerRule.rb +51 -0
- data/lib/rules/StringRule.rb +57 -0
- data/lib/web/README.md +11 -0
- data/lib/web/bundle.js +30 -0
- data/lib/web/gitignore.txt +7 -0
- data/lib/web/index.html +26 -0
- data/lib/web/package-lock.json +1347 -0
- data/lib/web/package.json +26 -0
- data/lib/web/server.js +122 -0
- metadata +21 -8
- data/lib/Ruler.rb +0 -112
- data/lib/reflekt.rb +0 -244
- data/lib/web/script.js +0 -8
- data/lib/web/style.css +0 -151
- data/lib/web/template.html.erb +0 -266
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"name": "reflekt-server",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "Serves the UI and writes to the DB.",
|
5
|
+
"main": "server.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
8
|
+
"start": "nodemon server.js"
|
9
|
+
},
|
10
|
+
"repository": {
|
11
|
+
"type": "git",
|
12
|
+
"url": "git+https://github.com/refIekt/reflekt-ui.git"
|
13
|
+
},
|
14
|
+
"author": "Maedi Prichard",
|
15
|
+
"license": "MPL-2.0",
|
16
|
+
"bugs": {
|
17
|
+
"url": "https://github.com/refIekt/reflekt-ui/issues"
|
18
|
+
},
|
19
|
+
"homepage": "https://reflekt.dev",
|
20
|
+
"dependencies": {
|
21
|
+
"express": "^4.17.1"
|
22
|
+
},
|
23
|
+
"devDependencies": {
|
24
|
+
"nodemon": "^2.0.5"
|
25
|
+
}
|
26
|
+
}
|
data/lib/web/server.js
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
const express = require('express')
|
2
|
+
const path = require('path')
|
3
|
+
const vm = require("vm");
|
4
|
+
const fs = require('fs');
|
5
|
+
|
6
|
+
const app = express();
|
7
|
+
const port = 3001;
|
8
|
+
const db_path = 'db.js';
|
9
|
+
|
10
|
+
// Configure express.
|
11
|
+
app.use(express.json());
|
12
|
+
app.use(express.static('.'));
|
13
|
+
app.use('/dist', express.static('../dist'));
|
14
|
+
|
15
|
+
// Respond with React app.
|
16
|
+
app.get('/', (req, res) => {
|
17
|
+
res.sendFile(path.join(__dirname, 'index.html'))
|
18
|
+
})
|
19
|
+
|
20
|
+
////
|
21
|
+
// READ.
|
22
|
+
////
|
23
|
+
|
24
|
+
var load_db = () => {
|
25
|
+
|
26
|
+
const data = fs.readFileSync(db_path);
|
27
|
+
const script = new vm.Script(data);
|
28
|
+
script.runInThisContext();
|
29
|
+
return JSON.parse(db);
|
30
|
+
|
31
|
+
}
|
32
|
+
|
33
|
+
////
|
34
|
+
// DELETE.
|
35
|
+
////
|
36
|
+
|
37
|
+
// Handle executions delete request.
|
38
|
+
app.post('/executions/delete', (req, res) => {
|
39
|
+
|
40
|
+
// Get reflection ID.
|
41
|
+
var exe_id = req.body.exe_id;
|
42
|
+
var number = req.body.number;
|
43
|
+
console.log(number);
|
44
|
+
|
45
|
+
// Get database.
|
46
|
+
db = load_db();
|
47
|
+
|
48
|
+
for (let [index, reflection] of db.reflections.entries()) {
|
49
|
+
if (reflection.e == exe_id && reflection.n == number) {
|
50
|
+
console.log("DELETED:")
|
51
|
+
console.log(db.reflections[index]);
|
52
|
+
db.reflections.splice(index, 1);
|
53
|
+
}
|
54
|
+
if (reflection.b != null && reflection.b == exe_id && reflection.n == number) {
|
55
|
+
console.log("DELETED:")
|
56
|
+
console.log(db.reflections[index]);
|
57
|
+
db.reflections.splice(index, 1);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
// Save database.
|
62
|
+
try {
|
63
|
+
fs.writeFileSync(db_path, 'var db = ' + JSON.stringify(JSON.stringify(db)) + ';');
|
64
|
+
}
|
65
|
+
catch (err) {
|
66
|
+
console.error(err)
|
67
|
+
}
|
68
|
+
|
69
|
+
res.status(200).send({ message: 'ok' });
|
70
|
+
|
71
|
+
})
|
72
|
+
|
73
|
+
// Handle reflections delete request.
|
74
|
+
app.post('/reflections/delete', (req, res) => {
|
75
|
+
|
76
|
+
// Get reflection ID.
|
77
|
+
ref_id = req.body.ref_id;
|
78
|
+
|
79
|
+
// Get database.
|
80
|
+
db = load_db();
|
81
|
+
|
82
|
+
// Delete reflection.
|
83
|
+
for (let [index, reflection] of db.reflections.entries()) {
|
84
|
+
if (reflection.r == ref_id) {
|
85
|
+
console.log("DELETED:")
|
86
|
+
console.log(db.reflections[index]);
|
87
|
+
db.reflections.splice(index, 1);
|
88
|
+
break;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
// Save database.
|
93
|
+
try {
|
94
|
+
fs.writeFileSync(db_path, 'var db = ' + JSON.stringify(JSON.stringify(db)) + ';');
|
95
|
+
}
|
96
|
+
catch (err) {
|
97
|
+
console.error(err)
|
98
|
+
}
|
99
|
+
|
100
|
+
res.status(200).send({ message: 'ok' });
|
101
|
+
|
102
|
+
})
|
103
|
+
|
104
|
+
////
|
105
|
+
// UPDATE.
|
106
|
+
////
|
107
|
+
|
108
|
+
// Handle reflections keep request.
|
109
|
+
app.post('/reflections/keep', (req, res) => {
|
110
|
+
console.log(req.body);
|
111
|
+
})
|
112
|
+
|
113
|
+
// Listen for requests.
|
114
|
+
app.listen(port, () => {
|
115
|
+
console.log(`Example app listening at http://localhost:${port}`)
|
116
|
+
})
|
117
|
+
|
118
|
+
//fs.readFile('student.json', (err, data) => {
|
119
|
+
// if (err) throw err;
|
120
|
+
// let student = JSON.parse(data);
|
121
|
+
// console.log(student);
|
122
|
+
//});
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reflekt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maedi Prichard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rowdb
|
@@ -25,21 +25,34 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
description: Testing that's completely automated.
|
28
|
-
email: maediprichard@
|
28
|
+
email: maediprichard@gmail.com
|
29
29
|
executables: []
|
30
30
|
extensions: []
|
31
31
|
extra_rdoc_files: []
|
32
32
|
files:
|
33
|
+
- lib/Accessor.rb
|
34
|
+
- lib/Aggregator.rb
|
33
35
|
- lib/Control.rb
|
34
36
|
- lib/Execution.rb
|
37
|
+
- lib/Meta.rb
|
38
|
+
- lib/MetaBuilder.rb
|
35
39
|
- lib/Reflection.rb
|
40
|
+
- lib/Reflekt.rb
|
41
|
+
- lib/Renderer.rb
|
36
42
|
- lib/Rule.rb
|
37
|
-
- lib/
|
43
|
+
- lib/RuleSet.rb
|
38
44
|
- lib/ShadowStack.rb
|
39
|
-
- lib/
|
40
|
-
- lib/
|
41
|
-
- lib/
|
42
|
-
- lib/
|
45
|
+
- lib/meta/IntegerMeta.rb
|
46
|
+
- lib/meta/StringMeta.rb
|
47
|
+
- lib/rules/IntegerRule.rb
|
48
|
+
- lib/rules/StringRule.rb
|
49
|
+
- lib/web/README.md
|
50
|
+
- lib/web/bundle.js
|
51
|
+
- lib/web/gitignore.txt
|
52
|
+
- lib/web/index.html
|
53
|
+
- lib/web/package-lock.json
|
54
|
+
- lib/web/package.json
|
55
|
+
- lib/web/server.js
|
43
56
|
homepage: https://github.com/refIekt/reflekt
|
44
57
|
licenses:
|
45
58
|
- MPL-2.0
|
data/lib/Ruler.rb
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
require 'Rule'
|
2
|
-
|
3
|
-
class Ruler
|
4
|
-
|
5
|
-
INPUT = "i"
|
6
|
-
OUTPUT = "o"
|
7
|
-
TYPE = "T"
|
8
|
-
VALUE = "V"
|
9
|
-
|
10
|
-
def initialize()
|
11
|
-
|
12
|
-
@controls = nil
|
13
|
-
|
14
|
-
# Rules.
|
15
|
-
@inputs = []
|
16
|
-
@output = nil
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
def load(controls)
|
21
|
-
|
22
|
-
@controls = controls
|
23
|
-
@controls.each_with_index do |control, index|
|
24
|
-
|
25
|
-
# Multiple inputs.
|
26
|
-
control[INPUT].each_with_index do |input, index|
|
27
|
-
unless input.nil?
|
28
|
-
|
29
|
-
# Create rule.
|
30
|
-
if @inputs[index].nil?
|
31
|
-
rule = Rule.new()
|
32
|
-
@inputs[index] = rule
|
33
|
-
else
|
34
|
-
rule = @inputs[index]
|
35
|
-
end
|
36
|
-
|
37
|
-
# Add rules to rule.
|
38
|
-
unless input[TYPE].nil? || input[TYPE].empty?
|
39
|
-
rule.add_type(input[TYPE].class)
|
40
|
-
end
|
41
|
-
unless input[VALUE].nil? || input[VALUE].empty?
|
42
|
-
rule.add_value(input[VALUE])
|
43
|
-
end
|
44
|
-
|
45
|
-
index = index + 1
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# Singular output.
|
50
|
-
output = control[OUTPUT]
|
51
|
-
unless control[OUTPUT].nil?
|
52
|
-
|
53
|
-
# Create rule.
|
54
|
-
if @output.nil?
|
55
|
-
rule = Rule.new()
|
56
|
-
@output = rule
|
57
|
-
else
|
58
|
-
rule = @output
|
59
|
-
end
|
60
|
-
|
61
|
-
## Add rules to rule.
|
62
|
-
unless output[TYPE].nil? || output[TYPE].empty?
|
63
|
-
rule.add_type(output[TYPE])
|
64
|
-
end
|
65
|
-
unless output[VALUE].nil? || output[VALUE].empty?
|
66
|
-
rule.add_value(output[VALUE])
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
def train()
|
76
|
-
|
77
|
-
@inputs.each do |rule|
|
78
|
-
# Get min/max.
|
79
|
-
if rule.is_number?
|
80
|
-
numbers = rule.values.select {|num| num.class == Integer }
|
81
|
-
numbers.sort!
|
82
|
-
rule.min = numbers.first
|
83
|
-
rule.max = numbers.last
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
def validate_inputs(klass, method, inputs)
|
91
|
-
result = true
|
92
|
-
inputs.each_with_index do |value, index|
|
93
|
-
rule = @inputs[index]
|
94
|
-
if rule.is_number? && value.class == Integer
|
95
|
-
result = false if value < rule.min
|
96
|
-
result = false if value > rule.max
|
97
|
-
end
|
98
|
-
end
|
99
|
-
return result
|
100
|
-
end
|
101
|
-
|
102
|
-
def validate_output(klass, method, outputs)
|
103
|
-
result = true
|
104
|
-
rule = @output
|
105
|
-
if rule.is_number? && value.class == Integer
|
106
|
-
result = false if value < rule.min
|
107
|
-
result = false if value > rule.max
|
108
|
-
end
|
109
|
-
return result
|
110
|
-
end
|
111
|
-
|
112
|
-
end
|
data/lib/reflekt.rb
DELETED
@@ -1,244 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
require 'erb'
|
3
|
-
require 'rowdb'
|
4
|
-
require 'Control'
|
5
|
-
require 'Execution'
|
6
|
-
require 'Reflection'
|
7
|
-
require 'Ruler'
|
8
|
-
require 'ShadowStack'
|
9
|
-
|
10
|
-
################################################################################
|
11
|
-
# REFLEKT
|
12
|
-
#
|
13
|
-
# An Execution is created each time a method is called.
|
14
|
-
# Multiple Refections are created per Execution.
|
15
|
-
# These Reflections execute on a ShadowStack on cloned objects.
|
16
|
-
# Then flow is returned to the original method and normal execution continues.
|
17
|
-
#
|
18
|
-
# Usage:
|
19
|
-
#
|
20
|
-
# class ExampleClass
|
21
|
-
# prepend Reflekt
|
22
|
-
################################################################################
|
23
|
-
|
24
|
-
module Reflekt
|
25
|
-
|
26
|
-
# The amount of reflections to create per method call.
|
27
|
-
@@reflekt_reflect_amount = 2
|
28
|
-
|
29
|
-
# Limit the amount of reflections that can be created per instance method.
|
30
|
-
# A method called thousands of times doesn't need that many reflections.
|
31
|
-
@@reflection_limit = 10
|
32
|
-
|
33
|
-
def initialize(*args)
|
34
|
-
|
35
|
-
@reflection_counts = {}
|
36
|
-
|
37
|
-
# Get instance methods.
|
38
|
-
# TODO: Include parent methods like "Array.include?".
|
39
|
-
self.class.instance_methods(false).each do |method|
|
40
|
-
|
41
|
-
# Don't process skipped methods.
|
42
|
-
next if self.class.reflekt_skipped?(method)
|
43
|
-
|
44
|
-
@reflection_counts[method] = 0
|
45
|
-
|
46
|
-
# When method called in flow.
|
47
|
-
self.define_singleton_method(method) do |*args|
|
48
|
-
|
49
|
-
# Don't reflect when limit reached.
|
50
|
-
unless @reflection_counts[method] >= @@reflection_limit
|
51
|
-
|
52
|
-
# Get current execution.
|
53
|
-
execution = @@reflekt_stack.peek()
|
54
|
-
|
55
|
-
# When stack empty or past execution done reflecting.
|
56
|
-
if execution.nil? || execution.has_finished_reflecting?
|
57
|
-
|
58
|
-
# Create execution.
|
59
|
-
execution = Execution.new(self, @@reflekt_reflect_amount)
|
60
|
-
@@reflekt_stack.push(execution)
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
# Get ruler.
|
65
|
-
# The method's ruler will not exist the first time the db generated.
|
66
|
-
if @@reflekt_rules.key? execution.caller_class.to_s.to_sym
|
67
|
-
ruler = @@reflekt_rules[execution.caller_class.to_s.to_sym][method.to_s]
|
68
|
-
else
|
69
|
-
ruler = nil
|
70
|
-
end
|
71
|
-
|
72
|
-
# Reflect.
|
73
|
-
# The first method call in the Execution creates a Reflection.
|
74
|
-
# Subsequent method calls are shadow executions on cloned objects.
|
75
|
-
if execution.has_empty_reflections? && !execution.is_reflecting?
|
76
|
-
execution.is_reflecting = true
|
77
|
-
|
78
|
-
class_name = execution.caller_class.to_s
|
79
|
-
method_name = method.to_s
|
80
|
-
|
81
|
-
# Create control.
|
82
|
-
control = Control.new(execution, method, ruler)
|
83
|
-
execution.control = control
|
84
|
-
|
85
|
-
# Execute control.
|
86
|
-
control.reflect(*args)
|
87
|
-
|
88
|
-
# Save control.
|
89
|
-
@@reflekt_db.get("#{class_name}.#{method_name}.controls").push(control.result())
|
90
|
-
|
91
|
-
# Multiple reflections per execution.
|
92
|
-
execution.reflections.each_with_index do |value, index|
|
93
|
-
|
94
|
-
# Create reflection.
|
95
|
-
reflection = Reflection.new(execution, method, ruler)
|
96
|
-
execution.reflections[index] = reflection
|
97
|
-
|
98
|
-
# Execute reflection.
|
99
|
-
reflection.reflect(*args)
|
100
|
-
@reflection_counts[method] = @reflection_counts[method] + 1
|
101
|
-
|
102
|
-
# Save reflection.
|
103
|
-
@@reflekt_db.get("#{class_name}.#{method_name}.reflections").push(reflection.result())
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
# Save results.
|
108
|
-
@@reflekt_db.write()
|
109
|
-
|
110
|
-
# Render results.
|
111
|
-
reflekt_render()
|
112
|
-
|
113
|
-
execution.is_reflecting = false
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
# Continue execution / shadow execution.
|
119
|
-
super *args
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
# Continue initialization.
|
126
|
-
super
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
##
|
131
|
-
# Render results.
|
132
|
-
##
|
133
|
-
def reflekt_render()
|
134
|
-
|
135
|
-
# Get JSON.
|
136
|
-
@@reflekt_json = File.read("#{@@reflekt_output_path}/db.json")
|
137
|
-
|
138
|
-
# Save HTML.
|
139
|
-
template = File.read("#{@@reflekt_path}/web/template.html.erb")
|
140
|
-
rendered = ERB.new(template).result(binding)
|
141
|
-
File.open("#{@@reflekt_output_path}/index.html", 'w+') do |f|
|
142
|
-
f.write rendered
|
143
|
-
end
|
144
|
-
|
145
|
-
# Add JS.
|
146
|
-
javascript = File.read("#{@@reflekt_path}/web/script.js")
|
147
|
-
File.open("#{@@reflekt_output_path}/script.js", 'w+') do |f|
|
148
|
-
f.write javascript
|
149
|
-
end
|
150
|
-
|
151
|
-
# Add CSS.
|
152
|
-
stylesheet = File.read("#{@@reflekt_path}/web/style.css")
|
153
|
-
File.open("#{@@reflekt_output_path}/style.css", 'w+') do |f|
|
154
|
-
f.write stylesheet
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
158
|
-
|
159
|
-
private
|
160
|
-
|
161
|
-
def self.prepended(base)
|
162
|
-
# Prepend class methods to the instance's singleton class.
|
163
|
-
base.singleton_class.prepend(SingletonClassMethods)
|
164
|
-
|
165
|
-
@@reflekt_setup ||= reflekt_setup_class
|
166
|
-
end
|
167
|
-
|
168
|
-
# Setup class.
|
169
|
-
def self.reflekt_setup_class()
|
170
|
-
|
171
|
-
# Receive configuration.
|
172
|
-
$ENV ||= {}
|
173
|
-
$ENV[:reflekt] ||= $ENV[:reflekt] = {}
|
174
|
-
|
175
|
-
# Set configuration.
|
176
|
-
@@reflekt_path = File.dirname(File.realpath(__FILE__))
|
177
|
-
|
178
|
-
# Build reflections directory.
|
179
|
-
if $ENV[:reflekt][:output_path]
|
180
|
-
@@reflekt_output_path = File.join($ENV[:reflekt][:output_path], 'reflections')
|
181
|
-
# Build reflections directory in current execution path.
|
182
|
-
else
|
183
|
-
@@reflekt_output_path = File.join(Dir.pwd, 'reflections')
|
184
|
-
end
|
185
|
-
# Create reflections directory.
|
186
|
-
unless Dir.exist? @@reflekt_output_path
|
187
|
-
Dir.mkdir(@@reflekt_output_path)
|
188
|
-
end
|
189
|
-
|
190
|
-
# Create database.
|
191
|
-
@@reflekt_db = Rowdb.new(@@reflekt_output_path + '/db.json')
|
192
|
-
@@reflekt_db.defaults({ :reflekt => { :api_version => 1 }})
|
193
|
-
|
194
|
-
# Create shadow execution stack.
|
195
|
-
@@reflekt_stack = ShadowStack.new()
|
196
|
-
|
197
|
-
# Define rules.
|
198
|
-
# TODO: Fix Rowdb.get(path) not returning data at path after Rowdb.push()?
|
199
|
-
@@reflekt_rules = {}
|
200
|
-
db = @@reflekt_db.value()
|
201
|
-
db.each do |class_name, class_values|
|
202
|
-
@@reflekt_rules[class_name] = {}
|
203
|
-
class_values.each do |method_name, method_values|
|
204
|
-
next if method_values.nil?
|
205
|
-
next unless method_values.class == Hash
|
206
|
-
if method_values.key? "controls"
|
207
|
-
|
208
|
-
ruler = Ruler.new()
|
209
|
-
ruler.load(method_values['controls'])
|
210
|
-
ruler.train()
|
211
|
-
|
212
|
-
@@reflekt_rules[class_name][method_name] = ruler
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
return true
|
218
|
-
end
|
219
|
-
|
220
|
-
module SingletonClassMethods
|
221
|
-
|
222
|
-
@@reflekt_skipped_methods = Set.new
|
223
|
-
|
224
|
-
##
|
225
|
-
# Skip a method.
|
226
|
-
#
|
227
|
-
# @param method - A symbol representing the method name.
|
228
|
-
##
|
229
|
-
def reflekt_skip(method)
|
230
|
-
@@reflekt_skipped_methods.add(method)
|
231
|
-
end
|
232
|
-
|
233
|
-
def reflekt_skipped?(method)
|
234
|
-
return true if @@reflekt_skipped_methods.include?(method)
|
235
|
-
false
|
236
|
-
end
|
237
|
-
|
238
|
-
def reflekt_limit(amount)
|
239
|
-
@@reflection_limit = amount
|
240
|
-
end
|
241
|
-
|
242
|
-
end
|
243
|
-
|
244
|
-
end
|