tla-trace-filter 0.0.3
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 +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}}}
|