tla-trace-filter 0.0.3 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +108 -0
- data/VERSION +1 -1
- data/lib/cli/cli.rb +124 -70
- data/lib/render/render.rb +85 -53
- data/mustache/api-call-after-state-post.mustache +9 -0
- data/mustache/api-call-after-state-pre.mustache +9 -0
- data/mustache/api-call-before-state-post.mustache +9 -0
- data/mustache/api-call-before-state-pre.mustache +9 -0
- data/mustache/api-call-call-post.mustache +9 -0
- data/mustache/api-call-call-pre.mustache +9 -0
- data/mustache/{api-call-output.mustache → api-call-default-afterState.mustache} +3 -3
- data/mustache/{api-call-default.mustache → api-call-default-api_input.mustache} +0 -0
- data/mustache/{api-call-return.mustache → api-call-default-api_return.mustache} +0 -0
- data/mustache/{api-call-input.mustache → api-call-default-beforeState.mustache} +3 -3
- data/mustache/api-call-header.mustache +4 -0
- data/mustache/api-call-init.mustache +41 -24
- data/mustache/api-call-link.mustache +5 -1
- data/mustache/api-call-main.mustache +28 -48
- data/mustache/api-call-post.mustache +13 -0
- data/mustache/api-call-pre.mustache +9 -0
- data/mustache/api-call-ret-post.mustache +9 -0
- data/mustache/api-call-ret-pre.mustache +9 -0
- data/mustache/api-call-step-post.mustache +9 -0
- data/mustache/api-call-step-pre.mustache +10 -0
- data/mustache/api-call.mustache +2 -2
- data/spec/cli/cli_spec.rb +26 -1
- data/spec/render/render_spec.rb +26 -3
- data/tla-trace-filter.gemspec +3 -3
- metadata +25 -12
- data/README.org +0 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c26773e9c1c8523333a24665eb9f648f021b17a0
|
4
|
+
data.tar.gz: d5a1a47884bb9bb5b07eede01df7e567037b7e57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c47bd7b02c21164670b48fee9f5ede938c80e25673bb17864e1a25bd31b75296c54c6b7d72aaf667c0d079ac51b23879bafc3011ad8f8f1b06d70f80bc670855
|
7
|
+
data.tar.gz: 40ef12b948cf1b57fccd9a700bec5561a2ae33813c03a633d7f867c15718292c1214b18032e9ebdcff05fc5cbe9d1ffbe1f37083bd50d22f806efbcdf66b7ddd
|
data/README.md
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# `tla-sbuilder-trace` - Post process trace output from model checking sbuilder formal models
|
2
|
+
|
3
|
+
Command line filter for
|
4
|
+
processing
|
5
|
+
[TLA+ Tools](http://research.microsoft.com/en-us/um/people/lamport/tla/tools.html) trace
|
6
|
+
output resulting from model
|
7
|
+
checking
|
8
|
+
[TLA+ language](http://research.microsoft.com/en-us/um/people/lamport/tla/book.html) specification
|
9
|
+
code generated
|
10
|
+
using [sbuilder](https://github.com/jarjuk/tla-sbuilder) -tool.
|
11
|
+
|
12
|
+
The tool implements two commands
|
13
|
+
|
14
|
+
* `add-links` : for adding links pointing 1) to *TLA+ language*
|
15
|
+
specification code and 2) to source code translated by sbuilder tool
|
16
|
+
|
17
|
+
* `api-calls` : for interpreting transitions in trace output as
|
18
|
+
interface calls on sbuilder source code translated by *sbuilder* tool
|
19
|
+
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
|
24
|
+
To install `tla-trace-filter` GEM create a `Gemfile` -file with the
|
25
|
+
content
|
26
|
+
|
27
|
+
```
|
28
|
+
source "https://rubygems.org"
|
29
|
+
gem 'tla-trace-filter'
|
30
|
+
```
|
31
|
+
|
32
|
+
and run
|
33
|
+
|
34
|
+
bundle install
|
35
|
+
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
### tla-trace-filter.rb add-links
|
40
|
+
|
41
|
+
To add links to model checker trace output in file `gen/tlc.out`
|
42
|
+
resulting from model checking *TLA+ language* specification code in
|
43
|
+
file `gen/setup1/tla/model.tla`, and using YAML file
|
44
|
+
`gen/setup1/tla/interfaces.yaml` to map transition names back to
|
45
|
+
source code modules in directory `solidity` run:
|
46
|
+
|
47
|
+
bundle exec tla-trace-filter.rb add-links setup1
|
48
|
+
|
49
|
+
|
50
|
+
To embed links to trace output run:
|
51
|
+
|
52
|
+
bundle exec tla-trace-filter.rb add-links setup1 --embed
|
53
|
+
|
54
|
+
|
55
|
+
### tla-trace-filter.rb api-calls
|
56
|
+
|
57
|
+
To create API calls run:
|
58
|
+
|
59
|
+
bundle exec tla-trace-filter.rb api-calls setup1
|
60
|
+
|
61
|
+
|
62
|
+
### Getting help
|
63
|
+
|
64
|
+
Location of the files and directories can be changes using command
|
65
|
+
line options. To get a list of available command and their options
|
66
|
+
run:
|
67
|
+
|
68
|
+
bundle exec tla-trace-filter.rb help
|
69
|
+
|
70
|
+
## Documentation
|
71
|
+
|
72
|
+
See [Cucumber](https://cucumber.io/) tests in GEM directory `features`.
|
73
|
+
|
74
|
+
For a demonstration of `api-call-init` -extension point refer to
|
75
|
+
a
|
76
|
+
[blog entry](https://jarjuk.wordpress.com/2017/12/06/sbuilder-wallet-3/).
|
77
|
+
|
78
|
+
|
79
|
+
## <a id="API-CALL_INIT">`api-call-init`-extension point</a>
|
80
|
+
|
81
|
+
`tla-trace-filter.rb` -tool
|
82
|
+
uses [mustache](https://mustache.github.io/) templates to produce
|
83
|
+
output. Default templates used are located in GEM directory
|
84
|
+
`mustache`. Command line option `--mustache` can override the
|
85
|
+
location, where templates are searched for.
|
86
|
+
|
87
|
+
To show templates, used by the tool, issue the command
|
88
|
+
|
89
|
+
ls $(bundle show tla-trace-filter)/mustache
|
90
|
+
|
91
|
+
To get instructions, how to use `api-call-init` -extension point,
|
92
|
+
issue the command:
|
93
|
+
|
94
|
+
cat $(bundle show tla-trace-filter)/mustache/api-call-init.mustache
|
95
|
+
|
96
|
+
|
97
|
+
## <a id="MUSTACHE-LAMBDAS">Mustache output lambdas</a>
|
98
|
+
|
99
|
+
Following lambda function are available in mustache template
|
100
|
+
|
101
|
+
* `{{#YAML_DUMP}}key{{/YAML_DUMP}}` : dump context `key` as YAML,
|
102
|
+
e.g. to dump `beforeState`, `api_input`, `api_return` or
|
103
|
+
`afterState` for `tla-trace-filter.rb api-calls` -command
|
104
|
+
|
105
|
+
|
106
|
+
## License
|
107
|
+
|
108
|
+
MIT
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/lib/cli/cli.rb
CHANGED
@@ -2,6 +2,8 @@ require_relative "../tla-trace-filter.rb"
|
|
2
2
|
|
3
3
|
require 'thor'
|
4
4
|
require 'yaml'
|
5
|
+
require 'socket' # gethostname
|
6
|
+
require 'digest' # sha1
|
5
7
|
|
6
8
|
module TlaTraceFilter
|
7
9
|
class Cli < Thor
|
@@ -12,13 +14,16 @@ module TlaTraceFilter
|
|
12
14
|
API_CALL_TEMPLATE = "api-call" # root template for command 'api-call'
|
13
15
|
ADD_LINKS_TEMPLATE = "add-links" # root template for command 'add-links'
|
14
16
|
|
17
|
+
API_CALL_PRE = "api-call-pre" # render before anything other templates
|
18
|
+
API_CALL_POST = "api-call-post" # render last
|
19
|
+
|
15
20
|
|
16
21
|
|
17
22
|
VERSION_BANNER = <<~EOS
|
18
23
|
#{File.basename $0}: #{File.readlines( File.join File.dirname( __FILE__ ), "../../VERSION" ).first.gsub( /\n/, "" )}
|
19
24
|
EOS
|
20
25
|
|
21
|
-
MUSTACHE_DEFAULT = "mustache/"
|
26
|
+
MUSTACHE_DEFAULT = [ "mustache/" ]
|
22
27
|
MUSTACHE_OPTION= <<-EOS
|
23
28
|
Output is processed using mustache templates in directory
|
24
29
|
#{File.dirname __FILE__}/../../mustache. Mustache templates can be
|
@@ -48,6 +53,9 @@ module TlaTraceFilter
|
|
48
53
|
def rendering
|
49
54
|
@rendering ||= TlaTraceFilter::Render.new( options )
|
50
55
|
end
|
56
|
+
|
57
|
+
# @# @!attribute [Digest:SHA1] sha1
|
58
|
+
attr_accessor :sha1
|
51
59
|
|
52
60
|
end
|
53
61
|
|
@@ -106,10 +114,11 @@ module TlaTraceFilter
|
|
106
114
|
add_shared_option :tla_dir, :type=>:string, :desc=>"Override default specification code dir gen/SETUP/tla"
|
107
115
|
add_shared_option :src_dir, :default=>"./solidity", :type=>:string, :desc=>"Source code root directory"
|
108
116
|
add_shared_option :filter_src, :aliases => "-f", :type => :boolean, :default => false
|
109
|
-
add_shared_option :mustache, :aliases => "-m", :type => :
|
117
|
+
add_shared_option :mustache, :aliases => "-m", :type => :array, :desc => "Add a directory (ends with /-char) or GEM to search for mustache template", :default=> MUSTACHE_DEFAULT
|
110
118
|
add_shared_option :solc_line, :type => :boolean, :default=>false, :desc => "TRUE interpretes sourceLines as characters starting from source start"
|
111
119
|
add_shared_option :debug_mustache, :type => :boolean, :default=>false, :desc => "Raise exception if referencing non-existing property"
|
112
120
|
add_shared_option :embed, :type => :boolean, :default=>false, :desc => "TRUE adds link to trace output"
|
121
|
+
add_shared_option :sha1, :type => :boolean, :default=>true, :desc => "Make :sha1 available for template #{API_CALL_POST}"
|
113
122
|
|
114
123
|
# @!endgroup
|
115
124
|
|
@@ -185,11 +194,10 @@ module TlaTraceFilter
|
|
185
194
|
API calls are resolved using 'interface.yaml' YAML file found in
|
186
195
|
specification code directory (option :tla-dir).
|
187
196
|
|
188
|
-
Use command
|
189
197
|
|
190
|
-
|
191
|
-
|
192
|
-
|
198
|
+
Extension points:
|
199
|
+
- cat $(bundle show tla-trace-filter)/mustache/api-call-init.mustache:
|
200
|
+
dynamic distpatch based on context[:interface][:interface_operation]
|
193
201
|
|
194
202
|
|
195
203
|
#{MUSTACHE_OPTION}
|
@@ -202,18 +210,25 @@ module TlaTraceFilter
|
|
202
210
|
shared_options :state_dump
|
203
211
|
shared_options :filter_src
|
204
212
|
shared_options :solc_line
|
213
|
+
shared_options :sha1
|
205
214
|
|
206
215
|
def api_calls( setup, file=nil)
|
207
216
|
|
208
217
|
# unfreeze 'options' && set defaults (:tla_dir)
|
209
218
|
setOptions( setup )
|
210
219
|
|
220
|
+
# init sha1 calculation
|
221
|
+
sha1Init
|
222
|
+
|
211
223
|
# Load fixed named template - allow used to define mapping
|
212
224
|
apiInitTemplate = "{{>#{API_CALL_INIT} }}"
|
213
225
|
@logger.info "#{__method__}, apiInitTemplate=#{apiInitTemplate}"
|
214
226
|
rendered = rendering.render(apiInitTemplate, options)
|
215
227
|
@logger.info "#{__method__}, output from init '#{rendered}'"
|
216
|
-
|
228
|
+
# outputRendered(rendered)
|
229
|
+
|
230
|
+
# preamble partial
|
231
|
+
outputRendered( rendering.render( "{{>#{API_CALL_PRE}}}", preAndPostHash(options ) ) )
|
217
232
|
|
218
233
|
# Default FILE vs. given on cmd line
|
219
234
|
file = traceFile( setup, file )
|
@@ -222,54 +237,71 @@ module TlaTraceFilter
|
|
222
237
|
@logger.info "#{__method__}, template=#{template}"
|
223
238
|
|
224
239
|
# queue length of 1
|
225
|
-
|
226
|
-
|
240
|
+
interfaceBeforeState = nil
|
241
|
+
interfaceEnterState = nil
|
242
|
+
interfaceEndState = nil
|
227
243
|
|
228
244
|
# read 'file' yielding String/Hash and parsedLines producing Hash
|
229
245
|
processInput( file ) do |data, parsedLines|
|
230
246
|
|
231
247
|
if data.is_a?(String)
|
232
|
-
# api - call do not
|
248
|
+
# api - call do not output trace lines
|
233
249
|
elsif data.is_a?(Hash)
|
234
250
|
|
235
251
|
# reason to output api-call
|
236
252
|
if data[:interface_started]
|
237
253
|
|
238
|
-
if
|
239
|
-
#
|
240
|
-
|
254
|
+
if interfaceBeforeState.nil?
|
255
|
+
# first time processing state 0
|
256
|
+
interfaceBeforeState = data
|
257
|
+
@logger.debug "loop: init interfaceBeforeState: #{interfaceBeforeState}" if @logger.debug?
|
258
|
+
elsif interfaceEnterState.nil?
|
259
|
+
# state 0 has been processed - is this the first interface
|
260
|
+
interfaceEnterState = data
|
241
261
|
else
|
242
262
|
|
243
|
-
#
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
#
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
263
|
+
# New iterface has started to execute. Now we can render
|
264
|
+
# apiStep for previous interface call using state collected in
|
265
|
+
#
|
266
|
+
# * beforeState: takens from 'interfaceBeforeState': it s either the first
|
267
|
+
# 'data' parsed OR 'data' parsed , which was reached
|
268
|
+
# after executing previous interface call.
|
269
|
+
|
270
|
+
# * afterState: taken from preceding 'data' in 'interfaceEndState'
|
271
|
+
apiOutput = canonizeData( interfaceBeforeState, interfaceEnterState, interfaceEndState )
|
272
|
+
@logger.debug "loop: apiOutput #{apiOutput}" if @logger.debug?
|
273
|
+
rendered = rendering.render(template, apiOutput)
|
274
|
+
outputRendered( rendered )
|
275
|
+
|
276
|
+
# init 'interfaceBeforeState' as 'interfaceEndState'
|
277
|
+
# from the previous step (which was just rendered)
|
278
|
+
interfaceBeforeState = interfaceEndState
|
279
|
+
# init 'interfaceEnterState' to current 'data' parsed from inputfile
|
280
|
+
interfaceEnterState = data
|
281
|
+
@logger.debug "loop: set interfaceBeforeState #{interfaceBeforeState}" if @logger.debug?
|
253
282
|
end
|
254
283
|
|
255
284
|
end # interface_started
|
256
285
|
|
257
|
-
#
|
258
|
-
|
286
|
+
# advance 'interfaceEndState' with current 'data'
|
287
|
+
interfaceEndState = data
|
259
288
|
|
260
289
|
end # elsif Hash?
|
261
290
|
end # block
|
262
291
|
|
263
|
-
|
292
|
+
# flush interfaceBeforeState
|
293
|
+
if !interfaceBeforeState.nil?
|
264
294
|
# render parsed data && output if any ouput
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
rendered
|
269
|
-
puts rendered if rendered.length > 0
|
295
|
+
apiOutput = canonizeData( interfaceBeforeState, interfaceEnterState || interfaceEndState, interfaceEndState )
|
296
|
+
@logger.debug "loop:exit: apiOutput (quit) #{apiOutput}" if @logger.debug?
|
297
|
+
rendered = rendering.render(template, apiOutput)
|
298
|
+
outputRendered( rendered )
|
270
299
|
|
271
300
|
end #
|
272
|
-
|
301
|
+
|
302
|
+
# postamble (including setting sha1) - but not calculating it
|
303
|
+
rendered = rendering.render("{{>#{API_CALL_POST}}}", preAndPostHash(options ) )
|
304
|
+
puts rendered if rendered.length > 0
|
273
305
|
|
274
306
|
end
|
275
307
|
|
@@ -278,10 +310,68 @@ module TlaTraceFilter
|
|
278
310
|
|
279
311
|
|
280
312
|
# ------------------------------------------------------------------
|
281
|
-
# @!group No
|
313
|
+
# @!group No commansd
|
282
314
|
|
283
315
|
no_commands do
|
284
316
|
|
317
|
+
# INitialize sha1 opbject
|
318
|
+
def sha1Init
|
319
|
+
self.sha1 = Digest::SHA1.new if options[:sha1]
|
320
|
+
end
|
321
|
+
|
322
|
+
def sha1Update( data )
|
323
|
+
sha1.update( data ) if options[:sha1]
|
324
|
+
# @logger.debug "#{__method__}: lines=#{@lines}, sha1.hexdigest=#{sha1.hexdigest}, data=#{data}" if @logger.debug?
|
325
|
+
end
|
326
|
+
|
327
|
+
|
328
|
+
# Output 'rendered' line && calculate sha1
|
329
|
+
def outputRendered rendered
|
330
|
+
if rendered.length > 0
|
331
|
+
sha1Update( rendered )
|
332
|
+
puts rendered
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# @return [Hash] data hash passed to pre/post templates.
|
337
|
+
def preAndPostHash( options)
|
338
|
+
{
|
339
|
+
:options => options,
|
340
|
+
:META => getMeta(),
|
341
|
+
:sha1 => sha1,
|
342
|
+
}
|
343
|
+
end
|
344
|
+
|
345
|
+
def getMeta
|
346
|
+
{
|
347
|
+
:timestamp => Time.new.strftime( "%Y-%m-%d %H:%M:%S" ),
|
348
|
+
:hostname => Socket.gethostname,
|
349
|
+
:user => ENV["USER"],
|
350
|
+
}
|
351
|
+
end
|
352
|
+
|
353
|
+
# @return [Hash] with properties from
|
354
|
+
# 'interfaceBeforeState','interfaceEnterState' and
|
355
|
+
# 'interfaceEndState'
|
356
|
+
def canonizeData( interfaceBeforeState, interfaceEnterState, interfaceEndState )
|
357
|
+
ret = {
|
358
|
+
options: interfaceBeforeState[:options], # cmd line options
|
359
|
+
interface_started: true,
|
360
|
+
beforeState: interfaceBeforeState[:parsed][:state_space],
|
361
|
+
parsed: interfaceEnterState[:parsed],
|
362
|
+
now: interfaceEndState[:parsed][:state_space][:now],
|
363
|
+
interface: interfaceEndState[:interface],
|
364
|
+
interface_operation: interfaceEndState[:interface_operation],
|
365
|
+
afterState: interfaceEndState[:parsed][:state_space],
|
366
|
+
}
|
367
|
+
|
368
|
+
# q[:beforeState] = q[:parsed][:state_space]
|
369
|
+
# q[:now] = lastData[:parsed][:state_space][:now]
|
370
|
+
# q[:interface] = lastData[:interface]
|
371
|
+
# q[:afterState] = lastData[:parsed][:state_space]
|
372
|
+
# q
|
373
|
+
end
|
374
|
+
|
285
375
|
# @param parsed [Hash] parsed model checking state
|
286
376
|
#
|
287
377
|
# @param interfaceDefintion [type] interface for currently
|
@@ -433,43 +523,6 @@ module TlaTraceFilter
|
|
433
523
|
interfaceHash
|
434
524
|
end
|
435
525
|
|
436
|
-
# # @param interface_operation [String] interface geth(mine)
|
437
|
-
# # executing tla transition parsed in state space
|
438
|
-
# #
|
439
|
-
# # @param state_space [Hash] state space state parsed
|
440
|
-
# #
|
441
|
-
# # @return [Boolean] true if
|
442
|
-
# # state_space[:pc][interface_operation] ends_with
|
443
|
-
# # '_start', edge case return 'false' if
|
444
|
-
# # 'interface_operation' not found in 'state_space'
|
445
|
-
# #
|
446
|
-
|
447
|
-
# def interfaceStarted?(interface_operation, state_space)
|
448
|
-
# @logger.debug "#{__method__}: interface_operation, state_space=#{state_space.to_yaml}" if @logger.debug?
|
449
|
-
# @logger.info "#{__method__}: look '#{interface_operation}' in #{state_space[:pc]}"
|
450
|
-
# return false if interface_operation.nil? || interface_operation.length == 0
|
451
|
-
# return false if state_space[:pc][interface_operation].nil?
|
452
|
-
# # state_space[:pc][interface_operation].end_with? "_start"
|
453
|
-
# isStart?( state_space[:pc][interface_operation] )
|
454
|
-
# end
|
455
|
-
|
456
|
-
# # @param interface_operation [String] interface geth(mine)
|
457
|
-
# # executing tla transition parsed in state space
|
458
|
-
# #
|
459
|
-
# # @param state_space [Hash] state space state parsed
|
460
|
-
# #
|
461
|
-
# # @return [Boolean] true if
|
462
|
-
# # state_space[:pc][interface_operation] does NOT ends
|
463
|
-
# # '_start' && 'interface_operation' found in 'state_space'
|
464
|
-
# #
|
465
|
-
|
466
|
-
# def interfaceExecuting?(interface_operation, state_space)
|
467
|
-
# # not valid interface_operation
|
468
|
-
# return false if interface_operation.nil? || interface_operation.length == 0
|
469
|
-
# return false if state_space[:pc][interface_operation].nil?
|
470
|
-
# # toggle isStart?
|
471
|
-
# return !isStart?( state_space[:pc][interface_operation] )
|
472
|
-
# end
|
473
526
|
|
474
527
|
# @param interface_operation [String] interface geth(mine)
|
475
528
|
# executing tla transition parsed in state space
|
@@ -510,6 +563,7 @@ module TlaTraceFilter
|
|
510
563
|
|
511
564
|
# unfreeze 'options' && set defaults (:tla_dir)
|
512
565
|
def setOptions( setup )
|
566
|
+
@logger.info "#{__method__}, options=#{options.to_yaml}"
|
513
567
|
# unfreeze options
|
514
568
|
new_options = options.dup
|
515
569
|
self.options = new_options
|
data/lib/render/render.rb
CHANGED
@@ -15,11 +15,11 @@ module TlaTraceFilter
|
|
15
15
|
# ------------------------------------------------------------------
|
16
16
|
# @!group Constants
|
17
17
|
|
18
|
-
# Default templates for
|
19
|
-
|
20
|
-
API_CALL_DEFAULT_PARTIAL
|
21
|
-
API_RETURN_DEFAULT_PARTIAL
|
22
|
-
|
18
|
+
# Default templates for beforeState, call, and afterState
|
19
|
+
API_BEFORE_STATE_DEFAULT_PARTIAL = "api-call-default-beforeState"
|
20
|
+
API_CALL_DEFAULT_PARTIAL = "api-call-default-api_input"
|
21
|
+
API_RETURN_DEFAULT_PARTIAL = "api-call-default-api_return"
|
22
|
+
API_AFTER_STATE_DEFAULT_PARTIAL = "api-call-default-afterState"
|
23
23
|
|
24
24
|
# Keys mapping to the output templates
|
25
25
|
API_DEFAULT_KEY = "default"
|
@@ -46,13 +46,13 @@ module TlaTraceFilter
|
|
46
46
|
# (with default) to partial name
|
47
47
|
attr_accessor :returnPartials
|
48
48
|
|
49
|
-
# @# @!attribute [Hash]
|
49
|
+
# @# @!attribute [Hash] beforeStatePartials hash mapping interface-names
|
50
50
|
# (with default) to partial name
|
51
|
-
attr_accessor :
|
51
|
+
attr_accessor :beforeStatePartials
|
52
52
|
|
53
|
-
# @# @!attribute [Hash]
|
53
|
+
# @# @!attribute [Hash] afterStatePartials hash mapping interface-names
|
54
54
|
# (with default) to partial name
|
55
|
-
attr_accessor :
|
55
|
+
attr_accessor :afterStatePartials
|
56
56
|
|
57
57
|
# @!endgroup
|
58
58
|
|
@@ -79,18 +79,18 @@ module TlaTraceFilter
|
|
79
79
|
# default search only GEM templates
|
80
80
|
self.templatePaths = [ File.join( File.dirname(__FILE__), "../../mustache/") ]
|
81
81
|
# user defined template search path prepended
|
82
|
-
self.templatePaths =
|
82
|
+
self.templatePaths = options[:mustache] + templatePaths if options[:mustache]
|
83
83
|
end
|
84
84
|
|
85
85
|
def initPartials
|
86
86
|
self.partials = {}
|
87
87
|
API_CALL_INIT( "" )
|
88
88
|
API_RETURN_INIT( "" )
|
89
|
-
|
90
|
-
|
89
|
+
API_BEFORE_STATE_INIT( "" )
|
90
|
+
API_AFTER_STATE_INIT( "" )
|
91
91
|
# self.callPartials = {}
|
92
|
-
# self.
|
93
|
-
# self.
|
92
|
+
# self.beforeStatePartials = {}
|
93
|
+
# self.afterStatePartials = {}
|
94
94
|
end
|
95
95
|
|
96
96
|
# @!endgroup
|
@@ -154,15 +154,15 @@ module TlaTraceFilter
|
|
154
154
|
|
155
155
|
# Initiliaze template calls. If no data given results calling to
|
156
156
|
# default templates
|
157
|
-
def
|
157
|
+
def API_BEFORE_STATE_INIT( data)
|
158
158
|
@logger.info "#{__method__}: data=#{data}"
|
159
159
|
begin
|
160
|
-
self.
|
160
|
+
self.beforeStatePartials = data.nil? || data == "" ? {} : YAML.load( data )
|
161
161
|
rescue Exception => e
|
162
162
|
msg = <<-EOS
|
163
163
|
#{e}
|
164
164
|
|
165
|
-
Error parsing YAML data in
|
165
|
+
Error parsing YAML data in API_BEFORE_STATE_INIT:
|
166
166
|
|
167
167
|
#{data}
|
168
168
|
EOS
|
@@ -170,20 +170,20 @@ module TlaTraceFilter
|
|
170
170
|
raise Exception.new, msg, e.backtrace
|
171
171
|
end
|
172
172
|
|
173
|
-
@logger.debug "#{__method__}:
|
173
|
+
@logger.debug "#{__method__}: beforeStatePartials=#{beforeStatePartials}" if @logger.debug?
|
174
174
|
|
175
175
|
# ensure that 'default' and 'empty' partials are defined
|
176
|
-
self.
|
177
|
-
self.
|
176
|
+
self.beforeStatePartials[API_DEFAULT_KEY] = API_BEFORE_STATE_DEFAULT_PARTIAL if beforeStatePartials[API_DEFAULT_KEY].nil?
|
177
|
+
self.beforeStatePartials[API_EMPTY_KEY] = API_AFTER_STATE_DEFAULT_PARTIAL if beforeStatePartials[API_EMPTY_KEY].nil?
|
178
178
|
|
179
179
|
end
|
180
180
|
|
181
181
|
# Lambda to initiliaze template calls. If no data given results
|
182
182
|
# calling to default templates
|
183
|
-
def
|
183
|
+
def API_AFTER_STATE_INIT( data)
|
184
184
|
@logger.info "#{__method__}: data=#{data}"
|
185
185
|
begin
|
186
|
-
self.
|
186
|
+
self.afterStatePartials = data.nil? || data == "" ? {} : YAML.load( data )
|
187
187
|
rescue Exception => e
|
188
188
|
msg = <<-EOS
|
189
189
|
#{e}
|
@@ -196,11 +196,11 @@ module TlaTraceFilter
|
|
196
196
|
raise Exception.new, msg, e.backtrace
|
197
197
|
end
|
198
198
|
|
199
|
-
@logger.debug "#{__method__}:
|
199
|
+
@logger.debug "#{__method__}: afterStatePartials=#{afterStatePartials}" if @logger.debug?
|
200
200
|
|
201
201
|
# ensure that 'default' and 'empty' partials are defined
|
202
|
-
self.
|
203
|
-
self.
|
202
|
+
self.afterStatePartials[API_DEFAULT_KEY] = API_AFTER_STATE_DEFAULT_PARTIAL if afterStatePartials[API_DEFAULT_KEY].nil?
|
203
|
+
self.afterStatePartials[API_EMPTY_KEY] = API_AFTER_STATE_DEFAULT_PARTIAL if afterStatePartials[API_EMPTY_KEY].nil?
|
204
204
|
|
205
205
|
end
|
206
206
|
|
@@ -236,25 +236,25 @@ module TlaTraceFilter
|
|
236
236
|
end
|
237
237
|
|
238
238
|
def getInputStatePartialName( interfaceOperation )
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
raise "Missing could not resolve '#{interfaceOperation}' in
|
244
|
-
|
245
|
-
@logger.info "#{__method__}: API-call to interfaceOperation '#{interfaceOperation}' render with '#{
|
246
|
-
|
239
|
+
beforeStatePartialName = nil
|
240
|
+
beforeStatePartialName = beforeStatePartials[API_EMPTY_KEY] if interfaceOperation.nil?
|
241
|
+
beforeStatePartialName = beforeStatePartials[interfaceOperation] if beforeStatePartialName.nil?
|
242
|
+
beforeStatePartialName = beforeStatePartials[API_DEFAULT_KEY] if beforeStatePartialName.nil?
|
243
|
+
raise "Missing could not resolve '#{interfaceOperation}' in beforeStatePartials #{beforeStatePartials}" if beforeStatePartialName.nil?
|
244
|
+
|
245
|
+
@logger.info "#{__method__}: API-call to interfaceOperation '#{interfaceOperation}' render with '#{beforeStatePartialName}'"
|
246
|
+
beforeStatePartialName
|
247
247
|
end
|
248
248
|
|
249
249
|
def getOutputStatePartialName( interfaceOperation )
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
raise "Missing could not resolve '#{interfaceOperation}' in
|
255
|
-
|
256
|
-
@logger.info "#{__method__}: API-call to interfaceOperation '#{interfaceOperation}' render with '#{
|
257
|
-
|
250
|
+
afterStatePartialName = nil
|
251
|
+
afterStatePartialName = afterStatePartials[API_EMPTY_KEY] if interfaceOperation.nil?
|
252
|
+
afterStatePartialName = afterStatePartials[interfaceOperation] if afterStatePartialName.nil?
|
253
|
+
afterStatePartialName = afterStatePartials[API_DEFAULT_KEY] if afterStatePartialName.nil?
|
254
|
+
raise "Missing could not resolve '#{interfaceOperation}' in afterStatePartials #{afterStatePartials}" if afterStatePartialName.nil?
|
255
|
+
|
256
|
+
@logger.info "#{__method__}: API-call to interfaceOperation '#{interfaceOperation}' render with '#{afterStatePartialName}'"
|
257
|
+
afterStatePartialName
|
258
258
|
end
|
259
259
|
|
260
260
|
# @!endgroup
|
@@ -297,18 +297,18 @@ module TlaTraceFilter
|
|
297
297
|
lineCount
|
298
298
|
end
|
299
299
|
|
300
|
-
# Lamba called for '
|
301
|
-
# [:interface][:interface_operation]
|
302
|
-
def
|
300
|
+
# Lamba called for 'API_BEFORE_STATE' to dispatch dynamically rendering of
|
301
|
+
# [:interface][:interface_operation] beforeState.
|
302
|
+
def API_BEFORE_STATE
|
303
303
|
@logger.info "#{__method__}: [:interface][:interface_operation]=#{context[:interface][:interface_operation]}, now=#{context[:now]}"
|
304
304
|
callPartialName = getInputStatePartialName( context[:interface][:interface_operation] )
|
305
305
|
template = partial( callPartialName )
|
306
306
|
render( template, context )
|
307
307
|
end
|
308
308
|
|
309
|
-
# Lamba called for '
|
310
|
-
# [:interface][:interface_operation]
|
311
|
-
def
|
309
|
+
# Lamba called for 'API_AFTER_STATE' to dispatch dynamically rendering of
|
310
|
+
# [:interface][:interface_operation] afterState.
|
311
|
+
def API_AFTER_STATE
|
312
312
|
@logger.info "#{__method__}: [:interface][:interface_operation]=#{context[:interface][:interface_operation]} now=#{context[:now]}"
|
313
313
|
callPartialName = getOutputStatePartialName( context[:interface][:interface_operation] )
|
314
314
|
template = partial( callPartialName )
|
@@ -316,6 +316,7 @@ module TlaTraceFilter
|
|
316
316
|
end
|
317
317
|
|
318
318
|
def API_RETURN
|
319
|
+
@logger.info "#{__method__}: [:interface][:interface_operation]=#{context[:interface][:interface_operation]} now=#{context[:now]}"
|
319
320
|
|
320
321
|
interfaceOperation = context[:interface][:interface_operation]
|
321
322
|
responseKey = context[:interface][:response_key]
|
@@ -325,8 +326,10 @@ module TlaTraceFilter
|
|
325
326
|
template = partial( callPartialName )
|
326
327
|
|
327
328
|
# context access likke i_Bank_saveAccount_
|
328
|
-
# raise "keys=#{context[:
|
329
|
-
|
329
|
+
# raise "keys=#{context[:afterState][:responses].to_yaml}"
|
330
|
+
@logger.debug "#{__method__}: context[:afterState]=#{context[:afterState].to_yaml}" if @logger.debug?
|
331
|
+
|
332
|
+
context[:api_return] = context[:afterState][:responses].nil? ? nil : context[:afterState][:responses][responseKey]
|
330
333
|
|
331
334
|
render( template, context )
|
332
335
|
|
@@ -370,10 +373,10 @@ module TlaTraceFilter
|
|
370
373
|
context[:parsed][:state_space][:step_input]
|
371
374
|
else
|
372
375
|
|
373
|
-
|
376
|
+
inputvariable = "#{context[:interface][:interface_name]}_input"
|
374
377
|
|
375
378
|
# find name of procedure input varibable
|
376
|
-
api = context[:parsed][:state_space].keys.find { |k| k.to_s.end_with?(
|
379
|
+
api = context[:parsed][:state_space].keys.find { |k| k.to_s.end_with?( inputvariable) } unless inputvariable.nil?
|
377
380
|
|
378
381
|
# access procedure input data
|
379
382
|
api = context[:parsed][:state_space][api] unless api.nil?
|
@@ -381,7 +384,15 @@ module TlaTraceFilter
|
|
381
384
|
# access procedure input for currently running interface opertaion
|
382
385
|
api = api[context[:interface][:interface_operation]] unless api.nil?
|
383
386
|
|
384
|
-
|
387
|
+
if api.nil?
|
388
|
+
msg = %Q{
|
389
|
+
No input found in context[:parsed][:state_space][:step_input] - maybe set 'SetStepInput = TRUE'
|
390
|
+
|
391
|
+
Tried to locate input variable ending with #{inputvariable} in context[:parsed][:state_space]
|
392
|
+
}
|
393
|
+
|
394
|
+
api = { :error => msg }
|
395
|
+
end
|
385
396
|
|
386
397
|
api
|
387
398
|
end
|
@@ -391,6 +402,26 @@ module TlaTraceFilter
|
|
391
402
|
end
|
392
403
|
|
393
404
|
|
405
|
+
# @!endgroup
|
406
|
+
|
407
|
+
# # ------------------------------------------------------------------
|
408
|
+
# @!group DUmp
|
409
|
+
|
410
|
+
# dump 'contextKey' in in YAML, where 'contextKey' is path of hash
|
411
|
+
# keys repareated by '.'
|
412
|
+
def DUMP_YAML( contextKey )
|
413
|
+
# enable splitting key - just be sure
|
414
|
+
contextKey = contextKey.to_s unless contextKey.is_a? String
|
415
|
+
keys = contextKey.split(".")
|
416
|
+
c = context
|
417
|
+
keys.each do |key|
|
418
|
+
break if c.nil?
|
419
|
+
c = c[key.to_sym]
|
420
|
+
end
|
421
|
+
c.to_yaml
|
422
|
+
end
|
423
|
+
|
424
|
+
|
394
425
|
# @!endgroup
|
395
426
|
|
396
427
|
|
@@ -494,7 +525,8 @@ module TlaTraceFilter
|
|
494
525
|
# otherwiset (= also NOT even if installed locally in gems)
|
495
526
|
def gem_location( gemName )
|
496
527
|
gemSpec = Gem.loaded_specs[gemName]
|
497
|
-
raise "Unknown gemName #{gemName}" if gemSpec.nil?
|
528
|
+
raise "Unknown gemName #{gemName} - known Gems #{Gem.loaded_specs.keys.join(",")} " if gemSpec.nil?
|
529
|
+
@logger.info "#{__method__}: gemName#{gemName} resolves to gemSpec.gem_dir#{gemSpec.gem_dir}"
|
498
530
|
gemSpec.gem_dir
|
499
531
|
end
|
500
532
|
|