pione 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. data/.gitignore +0 -1
  2. data/.travis.yml +3 -0
  3. data/History.txt +15 -0
  4. data/Rakefile +4 -0
  5. data/doc/man/pione-action-list.md +23 -0
  6. data/doc/man/pione-action.md +37 -0
  7. data/doc/man/pione-clean.md +56 -0
  8. data/doc/man/pione-compiler.md +39 -0
  9. data/doc/man/pione-update-package-info.md +38 -0
  10. data/example/DeferredChoice/DeferredChoice.pione +6 -4
  11. data/example/DeferredChoice/pione-package.json +15 -0
  12. data/example/FeatureExample/FeatureExample.pione +2 -0
  13. data/example/FeatureExample/pione-package.json +15 -0
  14. data/example/LoopByTouch/LoopByTouch.pione +2 -0
  15. data/example/LoopByTouch/pione-package.json +18 -0
  16. data/example/LucasNumber/LucasNumber.pione +6 -4
  17. data/example/LucasNumber/pione-package.json +15 -0
  18. data/example/MakePair/MakePair.pione +2 -0
  19. data/example/MakePair/pione-package.json +17 -0
  20. data/example/MakePair/scenario/case1/Scenario.pione +1 -0
  21. data/example/MakePair/scenario/case1/pione-scenario.json +47 -0
  22. data/example/MakePair/scenario/case2/Scenario.pione +1 -0
  23. data/example/MakePair/scenario/case2/pione-scenario.json +22 -0
  24. data/example/MakePair/scenario/case3/Scenario.pione +1 -0
  25. data/example/MakePair/scenario/case3/pione-scenario.json +43 -0
  26. data/example/OddSelector/OddSelector.pione +2 -0
  27. data/example/OddSelector/pione-package.json +15 -0
  28. data/example/OddSelector/scenario/Scenario.pione +1 -0
  29. data/example/OddSelector/{data → scenario/input}/1.i +0 -0
  30. data/example/OddSelector/{data → scenario/input}/10.i +0 -0
  31. data/example/OddSelector/{data → scenario/input}/2.i +0 -0
  32. data/example/OddSelector/{data → scenario/input}/3.i +0 -0
  33. data/example/OddSelector/{data → scenario/input}/4.i +0 -0
  34. data/example/OddSelector/{data → scenario/input}/5.i +0 -0
  35. data/example/OddSelector/{data → scenario/input}/6.i +0 -0
  36. data/example/OddSelector/{data → scenario/input}/7.i +0 -0
  37. data/example/OddSelector/{data → scenario/input}/8.i +0 -0
  38. data/example/OddSelector/{data → scenario/input}/9.i +0 -0
  39. data/example/OddSelector/scenario/output/1.res +0 -0
  40. data/example/OddSelector/scenario/output/3.res +0 -0
  41. data/example/OddSelector/scenario/output/5.res +0 -0
  42. data/example/OddSelector/scenario/output/7.res +0 -0
  43. data/example/OddSelector/scenario/output/9.res +0 -0
  44. data/example/OddSelector/scenario/pione-scenario.json +23 -0
  45. data/example/PegasusWMS/Merge/Merge.pione +3 -1
  46. data/example/PegasusWMS/Merge/pione-package.json +15 -0
  47. data/example/PegasusWMS/Pipeline/Pipeline.pione +2 -0
  48. data/example/PegasusWMS/Pipeline/pione-package.json +15 -0
  49. data/example/PegasusWMS/Split/Split.pione +2 -0
  50. data/example/PegasusWMS/Split/pione-package.json +15 -0
  51. data/example/{AbstractRule/AbstractRule.pione → SelectRuleByParam/SelectRuleByParam.pione} +4 -2
  52. data/example/SelectRuleByParam/pione-package.json +17 -0
  53. data/example/SelectRuleByParam/scenario/a/Scenario.pione +2 -0
  54. data/example/{AbstractRule → SelectRuleByParam}/scenario/a/output/message.txt +0 -0
  55. data/example/SelectRuleByParam/scenario/a/pione-scenario.json +10 -0
  56. data/example/SelectRuleByParam/scenario/b/Scenario.pione +2 -0
  57. data/example/{AbstractRule → SelectRuleByParam}/scenario/b/output/message.txt +0 -0
  58. data/example/SelectRuleByParam/scenario/b/pione-scenario.json +10 -0
  59. data/example/SelectRuleByParam/scenario/c/Scenario.pione +2 -0
  60. data/example/{AbstractRule → SelectRuleByParam}/scenario/c/output/message.txt +0 -0
  61. data/example/SelectRuleByParam/scenario/c/pione-scenario.json +10 -0
  62. data/example/Sum/Sum.pione +23 -21
  63. data/example/Sum/pione-package.json +15 -0
  64. data/example/Sum/scenario/Scenario.pione +1 -0
  65. data/example/Sum/{input → scenario/input}/list.txt +0 -0
  66. data/example/Sum/scenario/output/sum.txt +6 -0
  67. data/example/Sum/scenario/pione-scenario.json +10 -0
  68. data/lib/pione/agent/agent-exception.rb +11 -0
  69. data/lib/pione/agent/process-manager.rb +19 -7
  70. data/lib/pione/agent/task-worker.rb +2 -2
  71. data/lib/pione/command/option.rb +0 -1
  72. data/lib/pione/command/pione-action-list.rb +49 -0
  73. data/lib/pione/command/pione-action.rb +83 -0
  74. data/lib/pione/command/pione-client.rb +34 -10
  75. data/lib/pione/command/pione-compiler.rb +19 -1
  76. data/lib/pione/command/pione-package.rb +2 -0
  77. data/lib/pione/command/pione-task-worker.rb +3 -1
  78. data/lib/pione/command/pione-update-package-info.rb +53 -0
  79. data/lib/pione/command.rb +6 -4
  80. data/lib/pione/global/tuple-space-notifier-variable.rb +1 -1
  81. data/lib/pione/lang/environment.rb +47 -16
  82. data/lib/pione/lang/parameters.rb +6 -0
  83. data/lib/pione/literate-action/document.rb +25 -0
  84. data/lib/pione/literate-action/handler.rb +24 -0
  85. data/lib/pione/literate-action/parser.rb +54 -0
  86. data/lib/pione/literate-action.rb +10 -0
  87. data/lib/pione/location/data-location.rb +11 -3
  88. data/lib/pione/location/dropbox-location.rb +2 -0
  89. data/lib/pione/location/local-location.rb +4 -0
  90. data/lib/pione/package/package-exception.rb +17 -1
  91. data/lib/pione/package/package-handler.rb +13 -4
  92. data/lib/pione/package/scenario-handler.rb +9 -3
  93. data/lib/pione/package/scenario-info.rb +4 -3
  94. data/lib/pione/package/scenario-scanner.rb +11 -7
  95. data/lib/pione/rule-engine/basic-handler.rb +1 -1
  96. data/lib/pione/rule-engine/flow-handler.rb +6 -5
  97. data/lib/pione/test-helper/command-helper.rb +44 -1
  98. data/lib/pione/test-helper/internet-connectivity.rb +10 -0
  99. data/lib/pione/test-helper.rb +11 -10
  100. data/lib/pione/util/digest.rb +1 -1
  101. data/lib/pione/util/id.rb +1 -1
  102. data/lib/pione/util/indentation.rb +1 -1
  103. data/lib/pione/util/last-time.rb +20 -0
  104. data/lib/pione/util/misc.rb +7 -1
  105. data/lib/pione/util/pnml-compiler.rb +84 -13
  106. data/lib/pione/util.rb +1 -0
  107. data/lib/pione/version.rb +1 -1
  108. data/lib/pione.rb +17 -15
  109. data/man/pione-action-list.1 +23 -0
  110. data/man/pione-action.1 +45 -0
  111. data/man/pione-compiler.1 +48 -0
  112. data/man/pione-update-package-info.1 +43 -0
  113. data/pione.gemspec +1 -0
  114. data/test/command/spec_pione-action-list.rb +15 -0
  115. data/test/command/spec_pione-action.rb +24 -0
  116. data/test/command/spec_pione-client.rb +189 -0
  117. data/test/command/spec_pione-compiler.rb +28 -1
  118. data/test/command/spec_pione-update-package-info.rb +66 -0
  119. data/test/lang/data/literal-parser.yml +1 -0
  120. data/test/lang/spec_environment.rb +19 -0
  121. data/test/literate-action/data/D1.md +25 -0
  122. data/test/literate-action/data/HelloWorld.md +11 -0
  123. data/test/literate-action/spec_document.rb +20 -0
  124. data/test/literate-action/spec_handler.rb +28 -0
  125. data/test/literate-action/spec_parser.rb +51 -0
  126. data/test/package/spec_scenario-info.rb +2 -2
  127. data/test/package/spec_scenario-scanner.rb +3 -3
  128. data/test/util/data/pnml/Sequence.pnml +135 -135
  129. data/test/util/spec_pnml-compiler.rb +20 -9
  130. metadata +102 -39
  131. data/example/AbstractRule/package.yml +0 -7
  132. data/example/AbstractRule/scenario/a/scenario.yml +0 -4
  133. data/example/AbstractRule/scenario/b/scenario.yml +0 -4
  134. data/example/AbstractRule/scenario/c/scenario.yml +0 -4
  135. data/example/HelloWorld/package.yml +0 -6
  136. data/example/HelloWorld/scenario/scenario.yml +0 -3
  137. data/example/MakePair/package.yml +0 -8
  138. data/example/MakePair/scenario/case1/scenario.yml +0 -42
  139. data/example/MakePair/scenario/case2/scenario.yml +0 -17
  140. data/example/MakePair/scenario/case3/scenario.yml +0 -39
  141. data/example/PegasusWMS/Merge/package.yml +0 -2
  142. data/example/PegasusWMS/Pipeline/package.yml +0 -2
  143. data/example/PegasusWMS/Split/package.yml +0 -2
  144. data/example/SyntaxError/call_rule_error.pione +0 -6
  145. data/example/SyntaxError/feature_line_error.pione +0 -7
  146. data/example/SyntaxError/flow_block_error.pione +0 -5
  147. data/example/SyntaxError/input_line_error.pione +0 -6
  148. data/example/SyntaxError/invalid_rule_name.pione +0 -6
  149. data/example/SyntaxError/output_line_error.pione +0 -6
  150. data/example/SyntaxError/param_line_error.pione +0 -7
  151. data/example/SyntaxError/variable-binding-error.pione +0 -11
data/lib/pione/command.rb CHANGED
@@ -17,10 +17,12 @@ require 'pione/command/pione-tuple-space-viewer'
17
17
  require 'pione/command/pione-relay'
18
18
  require 'pione/command/pione-relay-client-db'
19
19
  require 'pione/command/pione-relay-account-db'
20
- require 'pione/command/pione-clean'
20
+ require 'pione/command/pione-clean' # pione clean
21
21
  require 'pione/command/pione-syntax-checker'
22
- require 'pione/command/pione-log'
23
- require 'pione/command/pione-val'
22
+ require 'pione/command/pione-log' # pione log
23
+ require 'pione/command/pione-val' # pione-val
24
24
  require 'pione/command/pione-package'
25
25
  require 'pione/command/pione-compiler'
26
-
26
+ require 'pione/command/pione-update-package-info' # pione update-package-info
27
+ require 'pione/command/pione-action' # pione action
28
+ require 'pione/command/pione-action-list' # pione action:list
@@ -51,7 +51,7 @@ module Pione
51
51
  item.desc = "presence notification addresses"
52
52
  item.init = ["255.255.255.255:56000"]
53
53
  item.define_updater do |vals|
54
- vals.map {|val| URI.parse("broadcast://%s" % val)}
54
+ vals.map {|val| val.is_a?(String) ? URI.parse("broadcast://%s" % val) : val}
55
55
  end
56
56
  end
57
57
 
@@ -9,7 +9,7 @@ module Pione
9
9
 
10
10
  # Return true if the name with the package id is bound.
11
11
  def bound?(package_id, name)
12
- @table[package_id][name] || (@parent ? @parent.bound?(package_id, name) : false)
12
+ (@table.has_key?(package_id) and @table[package_id][name]) || (@parent ? @parent.bound?(package_id, name) : false)
13
13
  end
14
14
 
15
15
  # Find value of the reference recursively. We will raise
@@ -55,12 +55,10 @@ module Pione
55
55
  # get value from parent table
56
56
  return @parent.get_value(env, ref) if @parent
57
57
  else
58
- # or find by parent package id
59
- if parent_ids = env.find_parent_ids(ref.package_id)
60
- parent_ids.each do |parent_id|
61
- if val = get_value(env, ref.set(package_id: parent_id))
62
- return val
63
- end
58
+ # otherwise, find by parent package id
59
+ env.find_ancestor_ids(ref.package_id).each do |ancestor_id|
60
+ if val = get_value(env, ref.set(package_id: ancestor_id))
61
+ return val
64
62
  end
65
63
  end
66
64
  end
@@ -94,6 +92,22 @@ module Pione
94
92
  end
95
93
  end
96
94
 
95
+ # Return all names that related to the package ID and ancestors.
96
+ #
97
+ # @return [Array<String>]
98
+ # all names in the table
99
+ def select_names_by(env, package_id)
100
+ names = @parent ? @parent.select_names_by(package_id) : []
101
+ target_ids = [package_id, *env.find_ancestor_ids(package_id)]
102
+ target_ids.each_with_object(names) do |target_id, names|
103
+ @table[target_id].keys.each do |name|
104
+ if not(names.include?(name))
105
+ names << name
106
+ end
107
+ end
108
+ end
109
+ end
110
+
97
111
  def inspect
98
112
  if @parent
99
113
  "#%s(%s,%s)" % [self.class.name.split("::").last, @table, @parent.inspect]
@@ -256,10 +270,20 @@ module Pione
256
270
  package_id_table[package_name]
257
271
  end
258
272
 
259
- def find_parent_ids(package_id)
273
+ # Find ancestor's IDs of the package ID. The way of ancestors search is depth-first.
274
+ def find_ancestor_ids(package_id)
275
+ ancestor_ids = []
260
276
  if package = package_get(PackageExpr.new(package_id: package_id))
261
- package.parent_ids
277
+ ancestor_ids += package.parent_ids
278
+ package.parent_ids.each do |parent_id|
279
+ find_ancestor_ids(parent_id).each do |ancestor_id|
280
+ if not(ancestor_ids.include?(ancestor_id))
281
+ ancestor_ids << ancestor_id
282
+ end
283
+ end
284
+ end
262
285
  end
286
+ return ancestor_ids
263
287
  end
264
288
 
265
289
  # Create a new environment which tables are overlayed current tables.
@@ -274,11 +298,17 @@ module Pione
274
298
  )
275
299
  end
276
300
 
277
- def merge(param_set)
301
+ # Merge the parameter set as variables into this environment. Rebinding
302
+ # variables raise error, but it is ignored when force flag is true.
303
+ #
304
+ # @param param_set [Lang::ParameterSet]
305
+ # parameter set to be merged
306
+ # @option option
307
+ def merge_param_set(param_set, option={})
278
308
  param_set.keys.each do |key|
279
309
  var = Variable.new(name: key, package_id: current_package_id)
280
310
  val = param_set[key]
281
- variable_set(var, val)
311
+ option[:force] ? variable_set!(var, val) : variable_set(var, val)
282
312
  end
283
313
  return self
284
314
  end
@@ -305,16 +335,17 @@ module Pione
305
335
  set(current_package_id: package_id, current_definition: definition)
306
336
  end
307
337
 
308
- def make_root_rule(param_set)
309
- # set $ROOT_PRARAM_SET
310
- variable_set(Variable.new("ROOT_PARAM_SET"), param_set)
338
+ def make_root_rule(main_param_set)
339
+ # put variable of parameter set for main rule
340
+ variable_set(Variable.new("MAIN_PARAM_SET"), ParameterSetSequence.of(main_param_set))
341
+
311
342
  # make root rule
312
- Package::Document.parse(<<-PIONE, current_package_id, nil, nil, "*system*").eval(self)
343
+ Package::Document.parse(<<-PIONE, current_package_id, nil, nil, "*System*").eval(self)
313
344
  Rule Root
314
345
  input '*'.all or null
315
346
  output '*'.all
316
347
  Flow
317
- rule Main.param($ROOT_PARAM_SET)
348
+ rule Main.param($MAIN_PARAM_SET)
318
349
  End
319
350
  PIONE
320
351
  rule_get(RuleExpr.new("Root"))
@@ -17,7 +17,13 @@ module Pione
17
17
  set(table: table.merge(other.table))
18
18
  end
19
19
 
20
+ # Return a parameter set that match the names.
20
21
  def filter(names)
22
+ set(table: table.select{|key, _| names.include?(key)})
23
+ end
24
+
25
+ # Return a parameter set excluding the names.
26
+ def delete_all(names)
21
27
  set(table: table.reject{|key, _| names.include?(key)})
22
28
  end
23
29
 
@@ -0,0 +1,25 @@
1
+ module Pione
2
+ module LiterateAction
3
+ class Document
4
+ def self.load(location)
5
+ new(location.read)
6
+ end
7
+
8
+ def initialize(src)
9
+ @action = Parser.parse(src)
10
+ end
11
+
12
+ # Return action names in the document.
13
+ def action_names
14
+ @action.keys
15
+ end
16
+
17
+ # Find target action fromt the name.
18
+ def find(name)
19
+ if action = @action[name]
20
+ Handler.new(action)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ module Pione
2
+ module LiterateAction
3
+ class Handler
4
+ def initialize(action)
5
+ @lang = action[:lang]
6
+ @content = action[:content]
7
+ end
8
+
9
+ # Convert the action to a string.
10
+ def textize(domain_info)
11
+ @content.to_s
12
+ end
13
+
14
+ # Execute the action.
15
+ def execute(domain_info, dir=Location[Global.pwd])
16
+ text = textize(domain_info)
17
+ location = Location[Temppath.create]
18
+ location.write(("#!/usr/bin/env %s\n" % @lang) + text)
19
+ location.path.chmod(0700)
20
+ `cd #{dir.path}; #{location.path}`
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,54 @@
1
+ module Pione
2
+ module LiterateAction
3
+ class Parser
4
+ # Parse the source string and return the result.
5
+ def self.parse(src)
6
+ new(src).parse
7
+ end
8
+
9
+ def initialize(src)
10
+ @src = src
11
+ end
12
+
13
+ # Parse the source string.
14
+ def parse
15
+ @parsed = Kramdown::Parser::GFM.parse(@src)
16
+ current_name = nil
17
+ root = @parsed.first
18
+ root.children.each_with_object(Hash.new) do |elt, action|
19
+ if name = find_rule_name(elt)
20
+ current_name = name
21
+ next
22
+ end
23
+
24
+ if current_name
25
+ lang, content = find_action(elt)
26
+ if content
27
+ action[current_name] ||= {content: ""}
28
+ action[current_name][:lang] = lang
29
+ action[current_name][:content] << content
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ # Find a rule name from the element.
38
+ def find_rule_name(elt)
39
+ if elt.type == :header and elt.options[:level] == 2
40
+ elt.options[:raw_text]
41
+ end
42
+ end
43
+
44
+ # Find an action from the element.
45
+ def find_action(elt)
46
+ if elt.type == :codeblock
47
+ if elt.attr["class"] and elt.attr["class"].start_with?("language-")
48
+ return [elt.attr["class"].sub("language-", ""), elt.value]
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,10 @@
1
+ module Pione
2
+ module LiterateAction
3
+
4
+ end
5
+ end
6
+
7
+ require 'pione/literate-action/parser' # literate action parser
8
+ require 'pione/literate-action/document' # literate action document
9
+ require 'pione/literate-action/handler' # action handler
10
+
@@ -191,15 +191,23 @@ module Pione
191
191
  raise NotImplementedError
192
192
  end
193
193
 
194
- # Return last modification time of the location.
194
+ # Return ctime of the location.
195
195
  #
196
196
  # @return [Time]
197
- # last modification time
197
+ # ctime
198
+ def ctime
199
+ raise NotImplementedError
200
+ end
201
+
202
+ # Return mtime of the location.
203
+ #
204
+ # @return [Time]
205
+ # mtime
198
206
  def mtime
199
207
  raise NotImplementedError
200
208
  end
201
209
 
202
- # Set last modification time of the location.
210
+ # Set mtime of the location.
203
211
  #
204
212
  # @return [void]
205
213
  def mtime=(time)
@@ -90,6 +90,8 @@ module Pione
90
90
  @client.file_delete(@path)
91
91
  end
92
92
 
93
+ # dropbox have "modified" time only, therefore ctime is not implemented
94
+
93
95
  def mtime
94
96
  metadata = @client.metadata(@path)
95
97
  Time.parse(metadata["modified"])
@@ -60,6 +60,10 @@ module Pione
60
60
  @path.mkpath unless exist?
61
61
  end
62
62
 
63
+ def ctime
64
+ @path.exist? ? @path.ctime : (raise NotFound.new(self))
65
+ end
66
+
63
67
  def mtime
64
68
  @path.exist? ? @path.mtime : (raise NotFound.new(self))
65
69
  end
@@ -31,7 +31,23 @@ module Pione
31
31
  class InvalidPackage < PackageError; end
32
32
 
33
33
  # InvalidScenario raises when the package is something bad.
34
- class InvalidScenario < PackageError; end
34
+ class InvalidScenario < PackageError
35
+ def initialize(location, reason)
36
+ @location = location
37
+ @reason = reason
38
+ end
39
+
40
+ def message
41
+ "%<path>s is an invalid scenario document: %<reason>s" % args
42
+ end
43
+
44
+ def args
45
+ {
46
+ :path => @location.path,
47
+ :reason => @reason
48
+ }
49
+ end
50
+ end
35
51
 
36
52
  class DatabaseError < PackageError; end
37
53
  end
@@ -4,13 +4,22 @@ module Pione
4
4
  class PackageHandler
5
5
  class << self
6
6
  # Update package info file and scenario info files.
7
- def write_info_files(location)
7
+ def write_info_files(location, option={})
8
+ # scan the package directory
8
9
  package_info = PackageScanner.new(location).scan
9
- (location + "pione-package.json").write(JSON.pretty_generate(package_info))
10
- Log::SystemLog.info("write %s" % (location + "pione-package.json").address)
10
+ last_time = Util::LastTime.get(package_info.filepaths.map{|path| location + path})
11
+
12
+ # update the package info file
13
+ info_location = location + "pione-package.json"
14
+ if option[:force] or not(info_location.exist?) or last_time > info_location.mtime
15
+ info_location.write(JSON.pretty_generate(package_info))
16
+ Log::SystemLog.info("update the package info file: %s" % info_location.address)
17
+ end
18
+
19
+ # write scenario info files
11
20
  package_info.scenarios.each do |scenario|
12
21
  scenario_info = ScenarioScanner.new(location + scenario).scan
13
- ScenarioHandler.new(location + scenario, scenario_info).write_info_file
22
+ ScenarioHandler.new(location + scenario, scenario_info).write_info_file(option)
14
23
  end
15
24
  end
16
25
  end
@@ -17,9 +17,15 @@ module Pione
17
17
  end
18
18
 
19
19
  # Write an information file for the scenario.
20
- def write_info_file
21
- (@location + "pione-scenario.json").write(JSON.pretty_generate(@info))
22
- Log::SystemLog.info("write %s" % (@location + "pione-scenario.json").address)
20
+ def write_info_file(option={})
21
+ last_time = Util::LastTime.get(@info.filepaths.map{|path| @location + path})
22
+
23
+ # update the scenario info file
24
+ location = @location + "pione-scenario.json"
25
+ if option[:force] or not(location.exist?) or last_time > location.mtime
26
+ location.write(JSON.pretty_generate(@info))
27
+ Log::SystemLog.info("update the scenario info file: %s" % location.address)
28
+ end
23
29
  end
24
30
 
25
31
  # Return input location of the scenario. If the scenario doesn't have
@@ -2,7 +2,7 @@ module Pione
2
2
  module Package
3
3
  class ScenarioInfo < StructX
4
4
  member :name
5
- member :param_set
5
+ member :textual_param_sets
6
6
  member :inputs, default: lambda {Array.new}
7
7
  member :outputs, default: lambda {Array.new}
8
8
 
@@ -10,12 +10,13 @@ module Pione
10
10
  # location of the file.
11
11
  def self.read(src)
12
12
  data = JSON.load(src.is_a?(Location::DataLocation) ? src.read : src)
13
- new(name: data["ScenarioName"], param_set: data["ParamSet"], inputs: data["Inputs"], outputs: data["Outputs"])
13
+ new(name: data["ScenarioName"], textual_param_sets: data["ParamSet"], inputs: data["Inputs"], outputs: data["Outputs"])
14
14
  end
15
15
 
16
16
  # Return file paths of the scenario.
17
17
  def filepaths
18
18
  list = []
19
+ list << "Scenario.pione"
19
20
  list += inputs
20
21
  list += outputs
21
22
  return list
@@ -24,7 +25,7 @@ module Pione
24
25
  def to_json(*args)
25
26
  data = Hash.new
26
27
  data["ScenarioName"] = name
27
- data["ParamSet"] = param_set
28
+ data["ParamSet"] = textual_param_sets
28
29
  data["Inputs"] = inputs
29
30
  data["Outputs"] = outputs
30
31
  data.to_json(*args)
@@ -29,20 +29,20 @@ module Pione
29
29
  name, param_set = scan_annotations
30
30
  inputs = scan_data_dir("input")
31
31
  outputs = scan_data_dir("output")
32
- ScenarioInfo.new(name: name, param_set: param_set, inputs: inputs, outputs: outputs)
32
+ ScenarioInfo.new(name: name, textual_param_sets: param_set, inputs: inputs, outputs: outputs)
33
33
  end
34
- rescue Parslet::ParseFailed => e
35
- raise InvalidScenario.new("invalid scenario document because of parser failed: %s" % e.message)
36
34
  end
37
35
 
38
36
  # Scan annotations from scenario file and return scenario name and
39
37
  # parameter set.
40
38
  def scan_annotations
39
+ location = @location + "Scenario.pione"
40
+
41
41
  # setup fake language environment
42
42
  env = Lang::Environment.new.setup_new_package("ScenarioScanner")
43
43
 
44
44
  # parse the scenario document
45
- Document.load(env, @location + "Scenario.pione", nil, nil, nil, @location + "Scenario.pione")
45
+ Document.load(env, location, nil, nil, nil, @location + "Scenario.pione")
46
46
 
47
47
  # get name and parameter set from fake package's annotations
48
48
  annotations = env.package_get(Lang::PackageExpr.new(package_id: env.current_package_id)).annotations
@@ -50,6 +50,8 @@ module Pione
50
50
  param_set = find_param_set(annotations)
51
51
 
52
52
  return name, param_set
53
+ rescue Parslet::ParseFailed => e
54
+ raise InvalidScenario.new(location, "Parser failed: " + e.message)
53
55
  end
54
56
 
55
57
  # Scan data files.
@@ -67,15 +69,16 @@ module Pione
67
69
 
68
70
  # Find "ScenarioName" annotaion.
69
71
  def find_name(annotations)
72
+ location = @location + "Scenario.pione"
70
73
  names = annotations.select {|annotation| annotation.annotation_type == "ScenarioName"}
71
74
  case names.size
72
75
  when 0
73
- raise InvalidScenario.new("No scenario name in %s" % (@location + "Scenario.pione"))
76
+ raise InvalidScenario.new(location, "No scenario name exists.")
74
77
  when 1
75
78
  names.first.value
76
79
  else
77
80
  name_list = names.map {|name| name.value}.join(", ")
78
- raise InvalidScenario.new("Multiple scenario names found: %s" % name_list)
81
+ raise InvalidScenario.new(location, "Duplicated scenario name found." % name_list)
79
82
  end
80
83
  end
81
84
 
@@ -88,7 +91,8 @@ module Pione
88
91
  when 1
89
92
  param_sets.first.value
90
93
  else
91
- raise InvalidScenario.new("Multiple parameter set found in %s" % @location.address)
94
+ location = @location + "Scenario.pione"
95
+ raise InvalidScenario.new(location, "Duplicated parameter set found.")
92
96
  end
93
97
  end
94
98
  end
@@ -132,7 +132,7 @@ module Pione
132
132
  # set current package id
133
133
  _env.set(current_package_id: package_id)
134
134
  # merge parameter set
135
- _env.merge(param_set)
135
+ _env.merge_param_set(param_set)
136
136
 
137
137
  ### system environment
138
138
  # ENV.each do |key, value|
@@ -129,7 +129,7 @@ module Pione
129
129
  # Make a task tuple from the application.
130
130
  def make_tuple(caller_id)
131
131
  features = rule_condition.features.inject(Lang::FeatureSequence.new) do |f, expr|
132
- f + f.eval(env)
132
+ f + expr.eval(env)
133
133
  end
134
134
  TupleSpace::TaskTuple.new(
135
135
  digest,
@@ -229,7 +229,7 @@ module Pione
229
229
  pieces.each do |param_set|
230
230
  ### merge default parameter values ####
231
231
  # setup task's environment by parameter set
232
- _env = plain_env.layer.merge(param_set)
232
+ _env = plain_env.layer.merge_param_set(param_set)
233
233
  _env.set(current_package_id: rule.package_id || env.current_package_id)
234
234
 
235
235
  # get task's condition
@@ -239,9 +239,9 @@ module Pione
239
239
  _param_set = param_set.merge_default_values(rule_condition)
240
240
 
241
241
  # handle parameter distribution
242
- _param_set.expand do |expanded_param_set|
242
+ _param_set.eval(_env).expand do |expanded_param_set|
243
243
  # rebuild environment by expanded param set
244
- _env = plain_env.layer.merge(expanded_param_set)
244
+ _env = plain_env.layer.merge_param_set(expanded_param_set)
245
245
  _env.set(current_package_id: rule.package_id || env.current_package_id)
246
246
 
247
247
  # get task's condition
@@ -437,7 +437,8 @@ module Pione
437
437
  # Wait until tasks completed.
438
438
  def wait_task_completion(tasks)
439
439
  tasks.each do |task|
440
- # wait to finish the work
440
+ # wait to finish the distributed task, note that finished tuple is in
441
+ # the task domain
441
442
  finished = read(TupleSpace::FinishedTuple.new(domain: task.domain_id))
442
443
 
443
444
  ### task completion processing ###
@@ -54,7 +54,7 @@ module Pione
54
54
  private
55
55
 
56
56
  # Run the command execution action.
57
- def execute(options, &b)
57
+ def execute(*options, &b)
58
58
  # initialize exit status
59
59
  Global.exit_status = true
60
60
 
@@ -88,5 +88,48 @@ module Pione
88
88
  end
89
89
  end
90
90
  end
91
+
92
+ class PioneClientRunner < StructX
93
+ member :title
94
+ member :template, default: "%s"
95
+ member :args
96
+ member :base, default: lambda {Pione::Location[Temppath.mkdir]}
97
+ member :default_arguments
98
+ member :context
99
+
100
+ def self.test(context, &b)
101
+ # with client mode
102
+ new(context: context).tap do |runner|
103
+ runner.default_arguments = ["-o", runner.base.path.to_s]
104
+ b.call(runner)
105
+ end
106
+
107
+ # with stand alone mode
108
+ new(context: context, template: "%s with stand alone mode").tap do |runner|
109
+ runner.default_arguments = ["-o", runner.base.path.to_s, "--stand-alone"]
110
+ b.call(runner)
111
+ end
112
+ end
113
+
114
+ def run(&b)
115
+ _args = args
116
+ _base = base
117
+ context.it(template % title) do
118
+ TestHelper::Command.succeed do
119
+ Pione::Command::PioneClient.run(_args)
120
+ end
121
+ b.call(_base)
122
+ end
123
+ end
124
+
125
+ def timeout(sec)
126
+ _args = args + ["--timeout", sec.to_s]
127
+ context.it(template % title) do
128
+ TestHelper::Command.fail do
129
+ Pione::Command::PioneClient.run(_args)
130
+ end
131
+ end
132
+ end
133
+ end
91
134
  end
92
135
  end
@@ -0,0 +1,10 @@
1
+ module Pione
2
+ module TestHelper
3
+ module InternetConnectivity
4
+ def self.ok?
5
+ `ping -c 3 -W 1 8.8.8.8 >> /dev/null`
6
+ $? == 0
7
+ end
8
+ end
9
+ end
10
+ end
@@ -28,16 +28,17 @@ module Pione
28
28
  end
29
29
 
30
30
  # load test helpers
31
- require "pione/test-helper/extension" # extensions for test
32
- require "pione/test-helper/webserver" # fake HTTP server
33
- require "pione/test-helper/location-helper" # location test helper
34
- require "pione/test-helper/command-helper" # command test helper
35
- require "pione/test-helper/parser-helper" # parser test utility
36
- require "pione/test-helper/transformer-helper" # transformer test utility
37
- require "pione/test-helper/lang-helper" # language test method
38
- require "pione/test-helper/package-helper" # pakcage test
39
- require "pione/test-helper/tuple-helper" # tuple test
40
- require "pione/test-helper/tuple-space-helper" # tuple space
31
+ require "pione/test-helper/extension" # extensions for test
32
+ require "pione/test-helper/webserver" # fake HTTP server
33
+ require "pione/test-helper/location-helper" # location test helper
34
+ require "pione/test-helper/command-helper" # command test helper
35
+ require "pione/test-helper/parser-helper" # parser test utility
36
+ require "pione/test-helper/transformer-helper" # transformer test utility
37
+ require "pione/test-helper/lang-helper" # language test method
38
+ require "pione/test-helper/package-helper" # pakcage test
39
+ require "pione/test-helper/tuple-helper" # tuple test
40
+ require "pione/test-helper/tuple-space-helper" # tuple space
41
+ require "pione/test-helper/internet-connectivity" # check internet connection
41
42
 
42
43
  # extend bacon's context
43
44
  class Bacon::Context
@@ -10,7 +10,7 @@ module Pione
10
10
  else
11
11
  _inputs = "%s,..." % inputs.flatten[0..2].map{|i| i.name}.join(",")
12
12
  end
13
- _param_set = param_set.filter(["I", "INPUT", "O", "OUTPUT", "*"])
13
+ _param_set = param_set.delete_all(["I", "INPUT", "O", "OUTPUT", "*"])
14
14
  _param_set = _param_set.map{|k,v| "%s:%s" % [k, v.textize]}.join(",")
15
15
  "&%s:%s([%s],{%s})" % [package_id, rule_name, _inputs, _param_set]
16
16
  end
data/lib/pione/util/id.rb CHANGED
@@ -5,7 +5,7 @@ module Pione
5
5
  # Make a task id by input data names and parameters.
6
6
  def generate(inputs, params)
7
7
  # NOTE: auto variables are ignored
8
- param_set = params.filter(["I", "INPUT", "O", "OUTPUT", "*"])
8
+ param_set = params.delete_all(["I", "INPUT", "O", "OUTPUT", "*"])
9
9
  inputs = inputs.map {|t| t.is_a?(TupleSpace::DataTuple) ? t.name : t}
10
10
  Digest::MD5.hexdigest("%s::%s" % [inputs.join(":"), param_set.textize])
11
11
  end