tla-trace-filter 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.org +66 -0
- data/VERSION +1 -0
- data/bin/tla-trace-filter.rb +5 -0
- data/lib/cli/cli.rb +563 -0
- data/lib/filter/filter.rb +134 -0
- data/lib/parser/grammar.treetop +132 -0
- data/lib/parser/node_extensions.rb +267 -0
- data/lib/parser/parser.rb +85 -0
- data/lib/render/render.rb +510 -0
- data/lib/tla-trace-filter.rb +6 -0
- data/lib/util/logger.rb +82 -0
- data/mustache/add-links-interface.mustache +33 -0
- data/mustache/add-links-state-dump.mustache +28 -0
- data/mustache/add-links-transition.mustache +14 -0
- data/mustache/add-links.mustache +43 -0
- data/mustache/api-call-default.mustache +14 -0
- data/mustache/api-call-init.mustache +70 -0
- data/mustache/api-call-input.mustache +20 -0
- data/mustache/api-call-link.mustache +2 -0
- data/mustache/api-call-main.mustache +86 -0
- data/mustache/api-call-output.mustache +18 -0
- data/mustache/api-call-return.mustache +13 -0
- data/mustache/api-call.mustache +34 -0
- data/spec/cli/cli_spec.rb +73 -0
- data/spec/filter/filter_spec.rb +53 -0
- data/spec/fixtures/interfaces.yaml +22 -0
- data/spec/fixtures/model.tla +1195 -0
- data/spec/fixtures/trace.txt +102 -0
- data/spec/parser/node_extensions_spec.rb +9 -0
- data/spec/parser/parser_spec.rb +392 -0
- data/spec/render/render_spec.rb +177 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/test_spec.rb +8 -0
- data/tla-trace-filter.gemspec +45 -0
- metadata +171 -0
data/lib/util/logger.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
module TlaTraceFilter
|
2
|
+
module Util
|
3
|
+
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# see http://hawkins.io/2013/08/using-the-ruby-logger/
|
7
|
+
|
8
|
+
module MyLogger
|
9
|
+
|
10
|
+
# no logging done
|
11
|
+
|
12
|
+
class NullLoger < Logger
|
13
|
+
def initialize(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add(*args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def debug?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@@logfile = nil # absolute path to log file
|
25
|
+
LOGFILE="tla-trace-filter.log"
|
26
|
+
|
27
|
+
def logfile( options )
|
28
|
+
return @@logfile if @@logfile
|
29
|
+
@@logfile = options[:logfile] || File.join( Dir.getwd, LOGFILE )
|
30
|
+
@@logfile
|
31
|
+
end
|
32
|
+
|
33
|
+
def getLogger( progname=nil, options={} )
|
34
|
+
|
35
|
+
|
36
|
+
progname = self.class.name.split('::').last if progname.nil?
|
37
|
+
level = get_level( options )
|
38
|
+
|
39
|
+
if level.nil?
|
40
|
+
|
41
|
+
return NullLoger.new
|
42
|
+
|
43
|
+
else
|
44
|
+
|
45
|
+
logger = Logger.new( logfile(options) )
|
46
|
+
logger.level=level
|
47
|
+
logger.progname = progname
|
48
|
+
return logger
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end # getLogger
|
53
|
+
|
54
|
+
|
55
|
+
# ------------------------------------------------------------------
|
56
|
+
private
|
57
|
+
|
58
|
+
def get_level( options )
|
59
|
+
|
60
|
+
level_name = options && options[:log] ? options[:log] : ENV['LOG_LEVEL']
|
61
|
+
|
62
|
+
level = case level_name
|
63
|
+
when 'warn', 'WARN'
|
64
|
+
Logger::WARN
|
65
|
+
when 'info', 'INFO'
|
66
|
+
Logger::INFO
|
67
|
+
when 'debug', 'DEBUG'
|
68
|
+
Logger::DEBUG
|
69
|
+
when 'error', 'ERROR'
|
70
|
+
Logger::ERROR
|
71
|
+
else
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
return level
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
{{!
|
2
|
+
|
3
|
+
Output link to interface source module
|
4
|
+
(If it can be found in 'interface.source.sourceModule')
|
5
|
+
|
6
|
+
}}{{!
|
7
|
+
|
8
|
+
Output hyperlink to source.sourceModule/source.sourceLine if possible
|
9
|
+
|
10
|
+
}}{{#interface.source.sourceModule}}
|
11
|
+
Interface operation '{{interface.interface_operation}}' for step '{{{parsed.state_space.step }}}' transition label '{{pc}}' defined in source file:
|
12
|
+
{{options.src_dir}}/{{interface.source.sourceModule}}:{{!
|
13
|
+
|
14
|
+
command line 'options.solc_line' tweaks intepretation of 'sourceLine'
|
15
|
+
--> true : to count characters starting from start of file
|
16
|
+
--> false: use interface.source.sourceLine
|
17
|
+
|
18
|
+
}}{{^options.solc_line}}{{interface.source.sourceLine}}{{/options.solc_line}}{{#options.solc_line}}{{SOLC_LINE}}{{/options.solc_line}}{{!
|
19
|
+
|
20
|
+
continue with source column
|
21
|
+
|
22
|
+
}}:{{interface.source.sourceColumn}}: {{{parsed.line}}}
|
23
|
+
{{/interface.source.sourceModule}}{{!
|
24
|
+
|
25
|
+
else no hyperlink
|
26
|
+
|
27
|
+
}}{{^interface.source.sourceModule}}
|
28
|
+
could not resolve source file for '{{interface.interface_operation}}'
|
29
|
+
{{/interface.source.sourceModule}}{{!
|
30
|
+
Local Variables:
|
31
|
+
require-final-newline: nil
|
32
|
+
End:
|
33
|
+
}}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
{{!
|
2
|
+
|
3
|
+
State dump
|
4
|
+
|
5
|
+
}}{{#options.state_dump}}
|
6
|
+
State dump: interface_started={{interface_started}}, interface_executing={{interface_executing}}
|
7
|
+
|
8
|
+
Executing in:
|
9
|
+
- interfaceOperation: {{interface_operation}}
|
10
|
+
- pc/label: {{pc}}
|
11
|
+
|
12
|
+
|
13
|
+
{{{parsed.state_space}}}
|
14
|
+
|
15
|
+
{{/options.state_dump}}{{!
|
16
|
+
|
17
|
+
else
|
18
|
+
|
19
|
+
}}
|
20
|
+
{{^options.state_dump}}{{!
|
21
|
+
|
22
|
+
No state dump requested
|
23
|
+
|
24
|
+
}}{{/options.state_dump}}{{!
|
25
|
+
Local Variables:
|
26
|
+
require-final-newline: nil
|
27
|
+
End:
|
28
|
+
}}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
{{!
|
2
|
+
Template to output hyperlink to tla specification code module 'model.tla'
|
3
|
+
found in directory 'options.tla_dir'
|
4
|
+
|
5
|
+
- references options and parsed
|
6
|
+
-
|
7
|
+
|
8
|
+
}}
|
9
|
+
|
10
|
+
{{options.tla_dir}}/model.tla:{{parsed.actionLine}}: transition for {{{parsed.line}}}{{!
|
11
|
+
Local Variables:
|
12
|
+
require-final-newline: nil
|
13
|
+
End:
|
14
|
+
}}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
{{!
|
2
|
+
|
3
|
+
Root Mustache template
|
4
|
+
|
5
|
+
Can access to following data:
|
6
|
+
|
7
|
+
:options: options passed from command line
|
8
|
+
|
9
|
+
:interface_started : boolean set to true when 'X_start'
|
10
|
+
transition seen
|
11
|
+
|
12
|
+
:interface_executing : boolean set to true not 'X_start' &&
|
13
|
+
valid interface executing
|
14
|
+
|
15
|
+
:interface_operation: string of interface operations executing, ?? if not known
|
16
|
+
|
17
|
+
:pc : transition label identifying pc, ?? if not known
|
18
|
+
|
19
|
+
:interface : interface definition for transition step interface with
|
20
|
+
properties :source.sourceModule and :source.sourceLine
|
21
|
+
pointing to solidity source of the interface transition
|
22
|
+
|
23
|
+
:parsed: data parsed from TLC trace file with properties:
|
24
|
+
- :line= string which triggers state space dump to parse state space
|
25
|
+
- :actionLine= line number (parser from ':line')
|
26
|
+
- :state_space = state variables as parsed from the dump, particularly
|
27
|
+
variable :step, which is used as a key to 'interfaces.yaml'
|
28
|
+
to create :source reference
|
29
|
+
|
30
|
+
|
31
|
+
}}{{>add-links-transition}}{{!
|
32
|
+
|
33
|
+
1)
|
34
|
+
|
35
|
+
}}{{>add-links-interface}}{{!
|
36
|
+
|
37
|
+
2)
|
38
|
+
|
39
|
+
}}{{>add-links-state-dump}}{{!
|
40
|
+
Local Variables:
|
41
|
+
require-final-newline: nil
|
42
|
+
End:
|
43
|
+
}}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
{{!
|
2
|
+
Default template called from API_CALL
|
3
|
+
|
4
|
+
It receives all same information as templates
|
5
|
+
'api-calls.mustache' and 'add-links.mustache' plus additional
|
6
|
+
data in property ':api_input'.
|
7
|
+
|
8
|
+
Api input is hash parsed from tlc trace output for currently
|
9
|
+
running interface (as present in context property :interface)
|
10
|
+
|
11
|
+
|
12
|
+
}}
|
13
|
+
|
14
|
+
CALL:{{now}} {{interface.interface_operation}}( {{{api_input}}} )
|
@@ -0,0 +1,70 @@
|
|
1
|
+
{{!
|
2
|
+
|
3
|
+
api-call-init.mustache: define rendering for 'api-call' command
|
4
|
+
|
5
|
+
Override this template to use other than default rendering.
|
6
|
+
|
7
|
+
This template is called once for a 'tla-trace-filter.rb api-call'.
|
8
|
+
It initialize four mappings:
|
9
|
+
|
10
|
+
- API_INPUT_INIT : render state before API call
|
11
|
+
- API_CALL_INIT : render API interface and API input parameters
|
12
|
+
- API_RETURN_INIT : render API interface and API return parameters
|
13
|
+
- API_OUTPUT_INIT : render state after API call
|
14
|
+
|
15
|
+
These mappings wrap mustache lambda sections, which contain a YAML
|
16
|
+
formatted hash mapping interface operation to a name of mustache
|
17
|
+
partial template. Two special keys are used: 1) 'default'
|
18
|
+
(=template to use if no other found), and 2) 'empty' (=template to
|
19
|
+
use if 'interface.interface_operation' is nil).
|
20
|
+
|
21
|
+
Example:
|
22
|
+
|
23
|
+
Demo(): solidity-constructor
|
24
|
+
Demo(execute): solidity-message
|
25
|
+
empty: api-call-empty
|
26
|
+
default: api-call-input
|
27
|
+
|
28
|
+
Which reads:
|
29
|
+
- inteface operation "Demo()" uses mustache partial 'solidity-constructor.mustache'
|
30
|
+
- interface Demo(execute) use partial 'solidity-message.mustache
|
31
|
+
- undedefined interface operation (initial state) use partial 'api-call-empty.mustache'
|
32
|
+
- all other interface operations use template 'api-call-input.mustache'
|
33
|
+
|
34
|
+
Search parth of these template files is configured using command line option --mustache
|
35
|
+
|
36
|
+
}}{{!
|
37
|
+
|
38
|
+
Configure templates to render state before API call
|
39
|
+
|
40
|
+
}}{{#API_INPUT_STATE_INIT}}
|
41
|
+
default: api-call-input
|
42
|
+
empty: api-call-input
|
43
|
+
{{/API_INPUT_STATE_INIT}}{{!
|
44
|
+
|
45
|
+
Configure templates to render API CALL
|
46
|
+
|
47
|
+
}}{{#API_CALL_INIT}}
|
48
|
+
default: api-call-default
|
49
|
+
{{/API_CALL_INIT}}{{!
|
50
|
+
|
51
|
+
Configure templates to render API_RETURN
|
52
|
+
|
53
|
+
}}{{#API_RETURN_INIT}}
|
54
|
+
default: api-call-return
|
55
|
+
empty: api-call-return
|
56
|
+
{{/API_RETURN_INIT}}{{!
|
57
|
+
|
58
|
+
Configure templates to render state after API call
|
59
|
+
|
60
|
+
}}{{#API_OUTPUT_STATE_INIT}}
|
61
|
+
default: api-call-output
|
62
|
+
empty: api-call-output
|
63
|
+
{{/API_OUTPUT_STATE_INIT}}{{!
|
64
|
+
|
65
|
+
Do not output new-line
|
66
|
+
|
67
|
+
Local Variables:
|
68
|
+
require-final-newline: nil
|
69
|
+
End:
|
70
|
+
}}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
{{!
|
2
|
+
|
3
|
+
api-call-input.mustache: output state before API call
|
4
|
+
|
5
|
+
Default implementation:
|
6
|
+
- output text INPUT-BLOCKCHAIN:
|
7
|
+
- YAML dump 'parsed.state_space.eth_accounts'
|
8
|
+
- YAML dump 'parsed.state_space.eth_storageRoot'
|
9
|
+
|
10
|
+
}}
|
11
|
+
|
12
|
+
# <INPUT-BLOCKCHAIN now="{{inputState.now}}">
|
13
|
+
eth_accounts: {{{inputState.eth_accounts.to_yaml}}}
|
14
|
+
eth_storageRoot: {{{inputState.eth_storageRoot.pretty_generate}}}
|
15
|
+
# </INPUT-BLOCKCHAIN>
|
16
|
+
{{!
|
17
|
+
Local Variables:
|
18
|
+
require-final-newline: nil
|
19
|
+
End:
|
20
|
+
}}
|
@@ -0,0 +1,2 @@
|
|
1
|
+
{{options.src_dir}}/{{interface.source.sourceModule}}:{{^options.solc_line}}{{interface.source.sourceLine}}{{/options.solc_line}}{{#options.solc_line}}{{SOLC_LINE}}{{/options.solc_line}}:1: {{interface.interface_operation}} at tick {{now}}
|
2
|
+
{{options.tla_dir}}/model.tla:{{parsed.actionLine}}: {{{parsed.line}}}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
{{!
|
2
|
+
|
3
|
+
api-call-main.mustache: template calling API_INPUT, API_CALL, API_OUTPUT templates
|
4
|
+
|
5
|
+
Output API call for interface.interface_operation
|
6
|
+
|
7
|
+
}}{{!
|
8
|
+
|
9
|
+
IF #interface.source.sourceModule - interface known
|
10
|
+
|
11
|
+
}}{{#interface.source.sourceModule}}{{!
|
12
|
+
|
13
|
+
- start interface
|
14
|
+
|
15
|
+
}}{{#interface_started}}
|
16
|
+
------------------------------------------------------------------
|
17
|
+
{{interface.interface_operation}}: at tick '{{parsed.state_space.now}}' for step '{{{parsed.state_space.step }}}'{{!
|
18
|
+
|
19
|
+
- input state: dispatched dynamically trough API_INPUT_STATE, which maps
|
20
|
+
[:interface][:interface_operation] to partial name set in 'api-call-init'
|
21
|
+
using API_INPUT_STATE_INIT
|
22
|
+
|
23
|
+
}}{{{API_INPUT_STATE}}}{{!
|
24
|
+
|
25
|
+
- API call: dispatched dynamically trough API_CALL, which maps
|
26
|
+
[:interface][:interface_operation] to partial name set in 'api-call-init'
|
27
|
+
using API_CALL_INIT
|
28
|
+
|
29
|
+
}}{{{API_CALL}}}{{!
|
30
|
+
|
31
|
+
- API_RETURN: dispatched dynamically trough API_RETURN, which maps
|
32
|
+
[:interface][:interface_operation] to partial name set in 'api-call-init'
|
33
|
+
using API_RETURN_INIT
|
34
|
+
|
35
|
+
}}{{{API_RETURN}}}{{!
|
36
|
+
|
37
|
+
- output state: dispatched dynamically trough API_OUTPUT_STATE, which maps
|
38
|
+
[:interface][:interface_operation] to partial name set in 'api-call-init'
|
39
|
+
|
40
|
+
}}{{{API_OUTPUT_STATE}}}{{!
|
41
|
+
|
42
|
+
- link to source line
|
43
|
+
}}{{>api-call-link}}{{!
|
44
|
+
|
45
|
+
END IF - interface.source.sourceModule
|
46
|
+
|
47
|
+
}}{{/interface_started}}{{#interface_executing}}{{/interface_executing}}{{/interface.source.sourceModule}}{{!
|
48
|
+
|
49
|
+
ELSE ^interface.source.sourceModule : when no source module identified
|
50
|
+
- interface started
|
51
|
+
|
52
|
+
}}{{^interface.source.sourceModule}}{{#interface_started}}
|
53
|
+
------------------------------------------------------------------
|
54
|
+
{{interface.interface_operation}}: at tick '{{parsed.state_space.now}}' for step '{{{parsed.state_space.step }}}'{{!
|
55
|
+
|
56
|
+
- input state
|
57
|
+
|
58
|
+
}}{{{API_INPUT_STATE}}}{{!
|
59
|
+
|
60
|
+
- API call
|
61
|
+
|
62
|
+
}}{{{API_CALL}}}{{!
|
63
|
+
|
64
|
+
- API return
|
65
|
+
|
66
|
+
}}{{{API_RETURN}}}{{!
|
67
|
+
|
68
|
+
- output state + some extra lines to separate different api-calls
|
69
|
+
|
70
|
+
}}{{{API_OUTPUT_STATE}}}{{!
|
71
|
+
|
72
|
+
- link to source file
|
73
|
+
|
74
|
+
}}{{>api-call-link}}{{!
|
75
|
+
|
76
|
+
- end interface_started
|
77
|
+
|
78
|
+
}}{{/interface_started}}{{!
|
79
|
+
|
80
|
+
END : ^interface.source.sourceModule
|
81
|
+
|
82
|
+
}}{{/interface.source.sourceModule}}{{!
|
83
|
+
Local Variables:
|
84
|
+
require-final-newline: nil
|
85
|
+
End:
|
86
|
+
}}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
{{!
|
2
|
+
|
3
|
+
api-call-output.mustache: output state state after API call
|
4
|
+
|
5
|
+
Default implementation: output eth_account, eth_storageRoot in YAML format
|
6
|
+
|
7
|
+
|
8
|
+
}}
|
9
|
+
|
10
|
+
# <OUTPUT-BLOCKCHAIN now="{{inputState.now}}">
|
11
|
+
eth_accounts: {{{outputState.eth_accounts.to_yaml}}}
|
12
|
+
eth_storageRoot: {{{outputState.eth_storageRoot.to_yaml}}}
|
13
|
+
# </OUTPUT-BLOCKCHAIN>
|
14
|
+
{{!
|
15
|
+
Local Variables:
|
16
|
+
require-final-newline: nil
|
17
|
+
End:
|
18
|
+
}}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
{{!
|
2
|
+
Default template called from API_RETURN
|
3
|
+
|
4
|
+
It receives all same information as templates
|
5
|
+
'api-calls.mustache' and 'add-links.mustache' plus additional
|
6
|
+
data in property ':api_return'.
|
7
|
+
|
8
|
+
Api input is hash parsed from tlc trace output for currently
|
9
|
+
running interface (as present in context property :interface)
|
10
|
+
|
11
|
+
|
12
|
+
}}
|
13
|
+
RETURN:{{now}} {{interface.interface_operation}}=>{{{api_return}}}
|