tla-trace-filter 0.0.3 → 0.0.6
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/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
|
|