roby 0.7.2 → 0.7.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.
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ === 0.7.3
2
+
3
+ * fix needed update to run on latest activesupport
4
+ This is probably the last release of 0.7. The 'next' branch will become 0.8 as
5
+ soon as it is tested enough
6
+
1
7
  === 0.7.2
2
8
 
3
9
  * fixed a memory leak regarding the event propagation histories. Until now,
data/Manifest.txt CHANGED
@@ -229,6 +229,7 @@ test/test_bgl.rb
229
229
  test/test_control.rb
230
230
  test/test_event.rb
231
231
  test/test_exceptions.rb
232
+ test/test_gui.rb
232
233
  test/test_interface.rb
233
234
  test/test_log.rb
234
235
  test/test_log_server.rb
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  $LOAD_PATH.unshift File.expand_path('lib', File.dirname(__FILE__))
2
2
  require 'enumerator'
3
- require 'hoe'
4
3
  require 'roby/config'
5
4
 
6
5
  begin
@@ -11,11 +10,16 @@ begin
11
10
 
12
11
  p.summary = 'A plan-based control framework for autonomous systems'
13
12
  p.url = p.paragraphs_of('README.txt', 1).join("\n\n")
14
- p.description = p.paragraphs_of('README.txt', 2..18).join("\n\n")
13
+ p.description = p.paragraphs_of('README.txt', 3..5).join("\n\n")
14
+ p.description +=
15
+ "\n\nSee the README.txt file at http://roby.rubyforge.org for more
16
+ informations, including links to tutorials and demonstration videos"
15
17
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
16
18
  p.post_install_message = p.paragraphs_of('README.txt', 2).join("\n\n")
17
19
 
18
- p.extra_deps << ['facets', '>= 2.0'] << 'activesupport' << ['utilrb', '>= 1.3.1']
20
+ p.extra_deps << ['facets', '>= 2.0'] << 'activesupport' << ['utilrb', '>= 1.3.1'] <<
21
+ ['rake', '>= 0.8.3']
22
+ p.extra_dev_deps << 'flexmock'
19
23
  if p.respond_to? :need_rdoc=
20
24
  p.need_rdoc = false
21
25
  end
@@ -42,8 +46,8 @@ begin
42
46
  tasks.delete_if { |n, _| n =~ /dist:(re|clobber_|)docs/ }
43
47
  end
44
48
  end
45
- rescue LoadError
46
- puts "cannot load the Hoe gem, distribution is disabled"
49
+ rescue
50
+ puts "cannot setup Hoe, distribution is disabled"
47
51
  end
48
52
 
49
53
  def build_extension(name, soname = name)
@@ -104,9 +108,14 @@ end
104
108
  UIFILES = %w{relations.ui relations_view.ui data_displays.ui replay_controls.ui basic_display.ui chronicle_view.ui}
105
109
  desc 'generate all Qt UI files using rbuic4'
106
110
  task :uic do
111
+ rbuic = 'rbuic4'
112
+ if File.exists?('/usr/lib/kde4/bin/rbuic4')
113
+ rbuic = '/usr/lib/kde4/bin/rbuic4'
114
+ end
115
+
107
116
  UIFILES.each do |file|
108
117
  file = 'lib/roby/log/gui/' + file
109
- if !system('rbuic4', '-o', file.gsub(/\.ui$/, '_ui.rb'), file)
118
+ if !system(rbuic, '-o', file.gsub(/\.ui$/, '_ui.rb'), file)
110
119
  STDERR.puts "Failed to generate #{file}"
111
120
  end
112
121
  end
@@ -6,6 +6,7 @@ app.robot robot_name, (ARGV.shift || robot_name)
6
6
  app.setup
7
7
  begin
8
8
  app.run do
9
+ Robot.info "loaded Roby #{Roby::VERSION}"
9
10
  # Load the controller
10
11
  include Roby
11
12
  Roby.execute do
@@ -4,6 +4,8 @@ require 'roby/distributed'
4
4
  require 'roby/distributed/protocol'
5
5
  require 'optparse'
6
6
 
7
+ require 'pp'
8
+
7
9
  remote_url = nil
8
10
  opt = OptionParser.new do |opt|
9
11
  opt.on('--host URL', String, "sets the host to connect to") do |url|
@@ -33,7 +35,18 @@ end
33
35
  DRb.start_service
34
36
 
35
37
  require 'irb'
36
- IRB.setup(nil)
38
+ IRB.setup(remote_url)
39
+ IRB.conf[:INSPECT_MODE] = false
40
+ IRB.conf[:IRB_NAME] = remote_url
41
+ IRB.conf[:PROMPT_MODE] = :ROBY
42
+ IRB.conf[:AUTO_INDENT] = true
43
+ IRB.conf[:PROMPT][:ROBY] = {
44
+ :PROMPT_I => "%N > ",
45
+ :PROMPT_N => "%N > ",
46
+ :PROMPT_S => "%N %l ",
47
+ :PROMPT_C => "%N * ",
48
+ :RETURN => "=> %s\n"
49
+ }
37
50
 
38
51
  control = Roby::RemoteInterface.new(DRbObject.new_with_uri("druby://#{remote_url}"))
39
52
 
data/lib/roby/config.rb CHANGED
@@ -8,7 +8,7 @@ try it on 1.9, checkout the 1.9 branch of the development repository on github
8
8
  end
9
9
 
10
10
  module Roby
11
- VERSION = '0.7.2'
11
+ VERSION = '0.7.3'
12
12
  ROBY_LIB_DIR = File.expand_path( File.join(File.dirname(__FILE__), '..') )
13
13
  ROBY_ROOT_DIR = File.expand_path( File.join(ROBY_LIB_DIR, '..') )
14
14
  end
data/lib/roby/event.rb CHANGED
@@ -171,6 +171,7 @@ module Roby
171
171
  end
172
172
  super() if defined? super
173
173
  @executable = true
174
+
174
175
  end
175
176
 
176
177
  def default_command(context)
@@ -183,12 +184,39 @@ module Roby
183
184
  # True if this event is controlable
184
185
  def controlable?; !!@command end
185
186
 
187
+ # Checks that the event can be called. Raises various exception
188
+ # when it is not the case.
189
+ def check_call_validity
190
+ if !self_owned?
191
+ raise OwnershipError, "not owner"
192
+ elsif !controlable?
193
+ raise EventNotControlable.new(self), "#call called on a non-controlable event"
194
+ elsif !executable?
195
+ raise EventNotExecutable.new(self), "#call called on #{self} which is non-executable event"
196
+ elsif !Roby.inside_control?
197
+ raise ThreadMismatch, "#call called while not in control thread"
198
+ end
199
+ end
200
+
201
+ # Checks that the event can be emitted. Raises various exception
202
+ # when it is not the case.
203
+ def check_emission_validity
204
+ if !executable?
205
+ raise EventNotExecutable.new(self), "#emit called on #{self} which is not executable"
206
+ elsif !self_owned?
207
+ raise OwnershipError, "cannot emit an event we don't own. #{self} is owned by #{owners}"
208
+ elsif !Roby.inside_control?
209
+ raise ThreadMismatch, "#emit called while not in control thread"
210
+ end
211
+ end
212
+
186
213
  # Returns true if the command has been called and false otherwise
187
214
  # The command won't be called if #postpone() is called within the
188
215
  # #calling hook
189
216
  #
190
217
  # This is used by propagation code, and should never be called directly
191
218
  def call_without_propagation(context) # :nodoc:
219
+ check_call_validity
192
220
  if !controlable?
193
221
  raise EventNotControlable.new(self), "#call called on a non-controlable event"
194
222
  end
@@ -222,15 +250,7 @@ module Roby
222
250
  # non-controlable and respond to the :call message. Controlability must
223
251
  # be checked using #controlable?
224
252
  def call(*context)
225
- if !self_owned?
226
- raise OwnershipError, "not owner"
227
- elsif !controlable?
228
- raise EventNotControlable.new(self), "#call called on a non-controlable event"
229
- elsif !executable?
230
- raise EventNotExecutable.new(self), "#call called on #{self} which is non-executable event"
231
- elsif !Roby.inside_control?
232
- raise ThreadMismatch, "#call called while not in control thread"
233
- end
253
+ check_call_validity
234
254
 
235
255
  context.compact!
236
256
  if Propagation.gathering?
@@ -426,7 +446,7 @@ module Roby
426
446
  begin
427
447
  h.call(event)
428
448
  rescue Exception => e
429
- Propagation.add_error( EventHandlerError.new(e, event) )
449
+ Propagation.add_error( EventHandlerError.new(e, event) )
430
450
  end
431
451
  end
432
452
  end
@@ -460,6 +480,7 @@ module Roby
460
480
  #
461
481
  # This is used by event propagation. Do not call directly: use #call instead
462
482
  def emit_without_propagation(context) # :nodoc:
483
+ check_emission_validity
463
484
  if !executable?
464
485
  raise EventNotExecutable.new(self), "#emit called on #{self} which is not executable"
465
486
  end
@@ -482,13 +503,7 @@ module Roby
482
503
 
483
504
  # Emit the event with +context+ as the event context
484
505
  def emit(*context)
485
- if !executable?
486
- raise EventNotExecutable.new(self), "#emit called on #{self} which is not executable"
487
- elsif !self_owned?
488
- raise OwnershipError, "cannot emit an event we don't own. #{self} is owned by #{owners}"
489
- elsif !Roby.inside_control?
490
- raise ThreadMismatch, "#emit called while not in control thread"
491
- end
506
+ check_emission_validity
492
507
 
493
508
  context.compact!
494
509
  if Propagation.gathering?
data/lib/roby/log/file.rb CHANGED
@@ -43,8 +43,17 @@ module Roby::Log
43
43
  super(@event_io)
44
44
 
45
45
  @index_data = Array.new
46
- update_index
47
- rewind
46
+ begin
47
+ rewind
48
+ rescue ArgumentError, EOFError
49
+ rebuild_index
50
+ rewind
51
+ end
52
+
53
+ if !valid_index?
54
+ rebuild_index
55
+ rewind
56
+ end
48
57
  end
49
58
 
50
59
  # Reads as much index data as possible
@@ -65,6 +74,28 @@ module Roby::Log
65
74
  return if index_data.empty?
66
75
  end
67
76
 
77
+ def valid_index?
78
+ 100.times do |i|
79
+ break if i * 10 >= index_data.size
80
+ index = index_data[i * 10]
81
+
82
+ event_io.seek(index[:pos])
83
+ cycle = begin
84
+ Marshal.load(event_io)
85
+ rescue EOFError
86
+ return false
87
+ rescue ArgumentError
88
+ return false
89
+ end
90
+
91
+ if cycle[-4] != :cycle_end ||
92
+ cycle[-1].first != index
93
+ return false
94
+ end
95
+ end
96
+ true
97
+ end
98
+
68
99
  def rewind
69
100
  @event_io.rewind
70
101
  Marshal.load(@event_io)
@@ -18,7 +18,7 @@ module Ui
18
18
  CATEGORIES = ['Task structure']
19
19
 
20
20
  def event_root_index; createIndex(TASK_ROOT_INDEX, 0, -1) end
21
- def task_root_index; createIndex(EVENT_ROOT_INDEX, 0, -1) end
21
+ def task_root_index; createIndex(EVENT_ROOT_INDEX, 0, -1) end
22
22
 
23
23
  attr_reader :relations
24
24
  attr_reader :display
@@ -31,10 +31,30 @@ module Ui
31
31
  @relations = []
32
32
 
33
33
  relations[TASK_ROOT_INDEX] = Roby::TaskStructure.enum_for(:each_relation).to_a
34
+
35
+ RelationConfigModel.detect_qtruby_behaviour(createIndex(0, 0, 0))
34
36
  end
35
37
 
38
+ QTRUBY_INDEX_USING_POINTERS = 1
39
+ QTRUBY_INDEX_USING_OBJECTIDS = 2
40
+ def self.detect_qtruby_behaviour(idx)
41
+ if idx.internalPointer == 0
42
+ @@qtruby_behaviour = QTRUBY_INDEX_USING_POINTERS
43
+ elsif idx.internalId == 1
44
+ @@qtruby_behaviour = QTRUBY_INDEX_USING_OBJECTIDS
45
+ end
46
+ end
47
+
48
+ def self.category_from_index(idx)
49
+ if @@qtruby_behaviour == QTRUBY_INDEX_USING_POINTERS
50
+ idx.internalPointer
51
+ else
52
+ idx.internalId >> 1
53
+ end
54
+ end
55
+
36
56
  def index(row, column, parent)
37
- if parent.valid? && parent.internalPointer == -1
57
+ if parent.valid? && RelationConfigModel.category_from_index(parent) == -1
38
58
  createIndex(row, column, parent.row)
39
59
  elsif row < relations.size
40
60
  createIndex(row, column, -1)
@@ -42,13 +62,14 @@ module Ui
42
62
  Qt::ModelIndex.new
43
63
  end
44
64
  end
65
+
45
66
  def parent(index)
46
- category = index.internalPointer
67
+ category = RelationConfigModel.category_from_index(index)
47
68
  if !index.valid? || category == -1 then Qt::ModelIndex.new
48
69
  else createIndex(category, 0, -1) end
49
70
  end
50
71
  def columnCount(parent); 2 end
51
- def hasChildren(parent); !parent.valid? || parent.internalPointer == -1 end
72
+ def hasChildren(parent); !parent.valid? || RelationConfigModel.category_from_index(parent) == -1 end
52
73
  def rowCount(parent)
53
74
  if !parent.valid? then relations.size
54
75
  else relations[parent.row].size end
@@ -62,7 +83,7 @@ module Ui
62
83
  def data(index, role)
63
84
  return Qt::Variant.new unless index.valid?
64
85
 
65
- category = index.internalPointer
86
+ category = RelationConfigModel.category_from_index(index)
66
87
  value = if category == -1
67
88
  if index.column == COL_NAME && role == Qt::DisplayRole
68
89
  CATEGORIES[index.row]
@@ -86,7 +107,7 @@ module Ui
86
107
  end
87
108
  end
88
109
  def setData(index, value, role)
89
- category = index.internalPointer
110
+ category = RelationConfigModel.category_from_index(index)
90
111
  relation = relations[category][index.row]
91
112
  if role == Qt::CheckStateRole
92
113
  case value.to_i
@@ -104,7 +125,7 @@ module Ui
104
125
  emit dataChanged(index, index)
105
126
  end
106
127
  def flags(index)
107
- if !index.valid? || index.internalPointer == -1 then Qt::ItemIsEnabled
128
+ if !index.valid? || RelationConfigModel.category_from_index(index) == -1 then Qt::ItemIsEnabled
108
129
  else
109
130
  flags = Qt::ItemIsSelectable | Qt::ItemIsTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable
110
131
  if index.column == 1
@@ -124,7 +145,7 @@ module Ui
124
145
  nil
125
146
  end
126
147
  def paint(painter, option, index)
127
- if index.column == 1 && index.internalPointer >= 0
148
+ if index.column == 1 && RelationConfigModel.category_from_index(index) >= 0
128
149
  color = index.model.data(index, Qt::DisplayRole).to_string
129
150
  rect = option.rect
130
151
  rect.adjust(1, 1, -1, -1)
@@ -2,6 +2,7 @@ require 'Qt4'
2
2
  require 'roby/app'
3
3
  require 'optparse'
4
4
 
5
+ require 'roby/log/event_stream'
5
6
  require 'roby/log/gui/replay_controls'
6
7
  require 'roby/log/gui/data_displays'
7
8
 
@@ -135,9 +136,14 @@ class Replay < Qt::MainWindow
135
136
  @first_sample = @time = min
136
137
  @last_sample = max
137
138
 
138
- ui_controls.progress.minimum = min.to_i
139
- ui_controls.progress.maximum = max.to_i
140
- ui_controls.update_bookmarks_menu
139
+ if min
140
+ ui_controls.progress.minimum = min.to_i
141
+ ui_controls.progress.maximum = max.to_i
142
+ ui_controls.update_bookmarks_menu
143
+ else
144
+ ui_controls.progress.minimum = 0
145
+ ui_controls.progress.maximum = 1
146
+ end
141
147
  else
142
148
  play_until time, integrate
143
149
  end
@@ -146,8 +152,13 @@ class Replay < Qt::MainWindow
146
152
  end
147
153
 
148
154
  def update_time_display
149
- ui_controls.time_lcd.display(((self.time - first_sample) * 1000.0).round / 1000.0)
150
- ui_controls.progress.value = self.time.to_i
155
+ if first_sample
156
+ ui_controls.time_lcd.display(((self.time - first_sample) * 1000.0).round / 1000.0)
157
+ ui_controls.progress.value = self.time.to_i
158
+ else
159
+ ui_controls.time_lcd.display(0)
160
+ ui_controls.progress.value = 0
161
+ end
151
162
  end
152
163
 
153
164
  attr_reader :time
@@ -182,9 +182,12 @@ class Ui::ReplayControls
182
182
  retry
183
183
  end
184
184
 
185
- unless replay.first_sample
185
+ if !replay.first_sample
186
186
  replay.seek(nil)
187
187
  end
188
+ if !replay.first_sample # no samples at all !
189
+ return
190
+ end
188
191
 
189
192
  user_time = if !op
190
193
  replay.first_sample + (user_time - Time.at(0))
data/lib/roby/support.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/string/inflections'
1
+ require 'active_support/inflector'
2
2
  class String # :nodoc: all
3
3
  include ActiveSupport::CoreExtensions::String::Inflections
4
4
  end
data/lib/roby/task.rb CHANGED
@@ -248,6 +248,41 @@ module Roby
248
248
  super(obj)
249
249
  end
250
250
  end
251
+
252
+ # Checks that the event can be called. Raises various exception
253
+ # when it is not the case.
254
+ def check_call_validity
255
+ super
256
+ rescue EventNotExecutable => e
257
+ refine_exception(e)
258
+ end
259
+
260
+ # Checks that the event can be emitted. Raises various exception
261
+ # when it is not the case.
262
+ def check_emission_validity
263
+ super
264
+ rescue EventNotExecutable => e
265
+ refine_exception(e)
266
+ end
267
+
268
+
269
+ def refine_exception (e)
270
+ if task.partially_instanciated?
271
+ raise EventNotExecutable.new(self), "#{name}! called on #{task} which is partially instanciated\n" +
272
+ "The following arguments were not set: \n" +
273
+ task.list_unset_arguments.map {|n| "\t#{n}"}.join("\n")+"\n"
274
+ #
275
+ elsif !plan
276
+ raise EventNotExecutable.new(self), "#{name}! called on #{task} but the task is in no plan"
277
+ elsif !plan.executable?
278
+ raise EventNotExecutable.new(self), "#{name}! called on #{task} but the plan is not executable"
279
+ elsif task.abstract?
280
+ raise EventNotExecutable.new(self), "#{name}! called on #{task} but the task is abstract"
281
+ else
282
+ raise EventNotExecutable.new(self), "#{name}! called on #{task} which is not executable: #{e.message}"
283
+ end
284
+ end
285
+
251
286
  end
252
287
 
253
288
  class TaskArguments < Hash
@@ -473,10 +508,23 @@ module Roby
473
508
  @model = self.class
474
509
 
475
510
  yield(self) if block_given?
476
-
477
511
  initialize_events
478
512
  end
479
513
 
514
+
515
+ # Lists all arguments, that are set to be needed via the :argument
516
+ # syntax but are not set.
517
+ # This is needed for debugging purposes.
518
+ def list_unset_arguments
519
+ ret = Array.new
520
+ model.arguments.each { |name|
521
+ if !arguments.has_key?(name) then
522
+ ret << name
523
+ end }
524
+ ret
525
+ end
526
+
527
+
480
528
  # Helper methods which creates all the necessary TaskEventGenerator
481
529
  # objects and stores them in the #bound_events map
482
530
  def initialize_events # :nodoc:
@@ -672,7 +720,7 @@ module Roby
672
720
  def executable?; !abstract? && !partially_instanciated? && super end
673
721
  # Returns true if this task's stop event is controlable
674
722
  def interruptible?; event(:stop).controlable? end
675
- # Set the executable flag. executable cannot be set to +false+ is the
723
+ # Set the executable flag. executable cannot be set to +false+ if the
676
724
  # task is running, and cannot be set to true on a finished task.
677
725
  def executable=(flag)
678
726
  return if flag == @executable
@@ -1119,22 +1167,8 @@ module Roby
1119
1167
 
1120
1168
  # define an instance method which calls the event command
1121
1169
  define_method("#{ev_s}!") do |*context|
1122
- begin
1123
1170
  generator = event(ev)
1124
1171
  generator.call(*context)
1125
- rescue EventNotExecutable => e
1126
- if partially_instanciated?
1127
- raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} which is partially instanciated"
1128
- elsif !plan
1129
- raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} but the task is in no plan"
1130
- elsif !plan.executable?
1131
- raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} but the plan is not executable"
1132
- elsif abstract?
1133
- raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} but the task is abstract"
1134
- else
1135
- raise EventNotExecutable.new(generator), "#{ev_s}! called on #{generator.task} which is not executable: #{e.message}"
1136
- end
1137
- end
1138
1172
  end
1139
1173
  end
1140
1174
 
@@ -1611,6 +1645,7 @@ module Roby
1611
1645
  unless defined? TaskStructure
1612
1646
  TaskStructure = RelationSpace(Task)
1613
1647
  end
1648
+
1614
1649
  end
1615
1650
 
1616
1651
  require 'roby/task-operations'
data/test/suite_core.rb CHANGED
@@ -22,3 +22,5 @@ require 'test_control'
22
22
  require 'test_interface'
23
23
  require 'test_log'
24
24
 
25
+ require 'test_gui'
26
+
data/test/test_gui.rb ADDED
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift File.expand_path('..', File.dirname(__FILE__))
2
+ require 'roby/test/common'
3
+ require 'roby/test/tasks/simple_task'
4
+ require 'roby/test/tasks/empty_task'
5
+
6
+ require 'roby/log/gui/relations'
7
+
8
+ class TC_Task < Test::Unit::TestCase
9
+ include Roby::Test
10
+
11
+ def test_index_handling
12
+ model = Ui::RelationConfigModel.new(nil)
13
+ [-1, 0, 222].each do |id|
14
+ idx = model.createIndex(0, 0, id)
15
+ assert_equal(id, Ui::RelationConfigModel.category_from_index(idx))
16
+ end
17
+ end
18
+ end
19
+
20
+
data/test/test_task.rb CHANGED
@@ -560,6 +560,17 @@ class TC_Task < Test::Unit::TestCase
560
560
  assert_equal(task.event(:failed).last, task.terminal_event)
561
561
  end
562
562
 
563
+ def assert_exception_message(klass, msg)
564
+ yield
565
+ flunk 'no exception raised'
566
+ rescue klass => e
567
+ unless msg === e.message
568
+ flunk "exception message '#{e.message}' does not match the expected pattern"
569
+ end
570
+ rescue Exception => e
571
+ flunk "expected an exception of class #{klass} but got #{e.full_message}"
572
+ end
573
+
563
574
  def test_executable
564
575
  model = Class.new(SimpleTask) do
565
576
  event(:inter, :command => true)
@@ -570,6 +581,8 @@ class TC_Task < Test::Unit::TestCase
570
581
  assert_raises(EventNotExecutable) { task.start! }
571
582
  assert_raises(EventNotExecutable) { task.event(:start).call }
572
583
 
584
+
585
+
573
586
  plan.discover(task)
574
587
  assert(task.executable?)
575
588
  assert_nothing_raised { task.event(:start).call(nil) }
@@ -593,6 +606,83 @@ class TC_Task < Test::Unit::TestCase
593
606
  task.executable = nil
594
607
  assert(task.executable?)
595
608
  end
609
+
610
+ class ParameterizedTask < Roby::Task
611
+ arguments :arg
612
+ end
613
+
614
+ class AbstractTask < Roby::Task
615
+ abstract
616
+ end
617
+
618
+ class NotExecutablePlan < Roby::Plan
619
+ def executable?
620
+ false
621
+ end
622
+ end
623
+
624
+ def exception_propagator(task, relation)
625
+ first_task = SimpleTask.new
626
+ second_task = task
627
+ first_task.send(relation, :start, second_task, :start)
628
+ first_task.start!
629
+ end
630
+
631
+ def check_direct_start(substring, check_signaling)
632
+ error = yield
633
+ assert_exception_message(EventNotExecutable, substring) { error.start! }
634
+ error = yield
635
+ assert_exception_message(EventNotExecutable, substring) {error.event(:start).call(nil)}
636
+ error = yield
637
+ assert_exception_message(EventNotExecutable, substring) {error.event(:start).emit(nil)}
638
+
639
+ if check_signaling then
640
+ error = yield
641
+ assert_exception_message(EventNotExecutable, substring) do
642
+ exception_propagator(error, :on)
643
+ end
644
+ error = yield
645
+ assert_exception_message(EventNotExecutable, substring) do
646
+ exception_propagator(error, :forward)
647
+ end
648
+ end
649
+ end
650
+
651
+ def test_exception_refinement
652
+ # test for partially instanciation
653
+ check_direct_start(/partially instanciated/,true) do
654
+ plan.discover(task = ParameterizedTask.new)
655
+ task
656
+ end
657
+
658
+ #test for a task that is in no plan
659
+ check_direct_start(/no plan/,false) do
660
+ SimpleTask.new
661
+ end
662
+
663
+ #test for an abstract task
664
+ check_direct_start(/abstract/,true) do
665
+ plan.discover(task = AbstractTask.new)
666
+ task
667
+ end
668
+
669
+ #test for a not executable plan
670
+ erroneous_plan = NotExecutablePlan.new
671
+ check_direct_start(/plan is not executable/,false) do
672
+ erroneous_plan.discover(task = SimpleTask.new)
673
+ task
674
+ end
675
+ erroneous_plan.garbage_collect
676
+
677
+ #test for a not executable task
678
+ check_direct_start(/is not executable/,true) do
679
+ plan.discover(task = SimpleTask.new)
680
+ task.executable = false
681
+ task
682
+ end
683
+ end
684
+
685
+
596
686
 
597
687
  def test_task_success_failure
598
688
  FlexMock.use do |mock|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Joyeux
@@ -9,11 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-06-14 00:00:00 +02:00
12
+ date: 2009-03-01 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: facets
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -23,6 +24,7 @@ dependencies:
23
24
  version:
24
25
  - !ruby/object:Gem::Dependency
25
26
  name: activesupport
27
+ type: :runtime
26
28
  version_requirement:
27
29
  version_requirements: !ruby/object:Gem::Requirement
28
30
  requirements:
@@ -32,6 +34,7 @@ dependencies:
32
34
  version:
33
35
  - !ruby/object:Gem::Dependency
34
36
  name: utilrb
37
+ type: :runtime
35
38
  version_requirement:
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
@@ -39,14 +42,35 @@ dependencies:
39
42
  - !ruby/object:Gem::Version
40
43
  version: 1.3.1
41
44
  version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: rake
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.8.3
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: flexmock
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
42
65
  - !ruby/object:Gem::Dependency
43
66
  name: hoe
67
+ type: :development
44
68
  version_requirement:
45
69
  version_requirements: !ruby/object:Gem::Requirement
46
70
  requirements:
47
71
  - - ">="
48
72
  - !ruby/object:Gem::Version
49
- version: 1.5.3
73
+ version: 1.9.0
50
74
  version:
51
75
  description: A plan-based control framework for autonomous systems
52
76
  email:
@@ -230,6 +254,7 @@ extra_rdoc_files:
230
254
  - test/test_control.rb
231
255
  - test/test_event.rb
232
256
  - test/test_exceptions.rb
257
+ - test/test_gui.rb
233
258
  - test/test_interface.rb
234
259
  - test/test_log.rb
235
260
  - test/test_log_server.rb
@@ -476,6 +501,7 @@ files:
476
501
  - test/test_control.rb
477
502
  - test/test_event.rb
478
503
  - test/test_exceptions.rb
504
+ - test/test_gui.rb
479
505
  - test/test_interface.rb
480
506
  - test/test_log.rb
481
507
  - test/test_log_server.rb
@@ -528,43 +554,44 @@ required_rubygems_version: !ruby/object:Gem::Requirement
528
554
  requirements: []
529
555
 
530
556
  rubyforge_project: roby
531
- rubygems_version: 1.1.1
557
+ rubygems_version: 1.2.0
532
558
  signing_key:
533
559
  specification_version: 2
534
560
  summary: A plan-based control framework for autonomous systems
535
561
  test_files:
536
- - test/relations/test_hierarchy.rb
537
- - test/relations/test_planned_by.rb
538
- - test/relations/test_executed_by.rb
562
+ - test/distributed/test_communication.rb
563
+ - test/distributed/test_connection.rb
564
+ - test/distributed/test_execution.rb
565
+ - test/distributed/test_mixed_plan.rb
566
+ - test/distributed/test_plan_notifications.rb
567
+ - test/distributed/test_protocol.rb
568
+ - test/distributed/test_query.rb
569
+ - test/distributed/test_remote_plan.rb
570
+ - test/distributed/test_transaction.rb
571
+ - test/planning/test_loops.rb
572
+ - test/planning/test_model.rb
573
+ - test/planning/test_task.rb
539
574
  - test/relations/test_conflicts.rb
540
575
  - test/relations/test_ensured.rb
576
+ - test/relations/test_executed_by.rb
577
+ - test/relations/test_hierarchy.rb
578
+ - test/relations/test_planned_by.rb
579
+ - test/test_bgl.rb
580
+ - test/test_control.rb
581
+ - test/test_event.rb
541
582
  - test/test_exceptions.rb
542
- - test/test_query.rb
543
- - test/planning/test_loops.rb
544
- - test/planning/test_task.rb
545
- - test/planning/test_model.rb
546
- - test/test_transactions.rb
547
- - test/test_support.rb
548
- - test/test_relations.rb
583
+ - test/test_gui.rb
549
584
  - test/test_interface.rb
585
+ - test/test_log.rb
550
586
  - test/test_log_server.rb
551
- - test/test_event.rb
552
- - test/test_bgl.rb
553
587
  - test/test_plan.rb
554
- - test/test_thread_task.rb
555
- - test/distributed/test_query.rb
556
- - test/distributed/test_communication.rb
557
- - test/distributed/test_transaction.rb
558
- - test/distributed/test_remote_plan.rb
559
- - test/distributed/test_plan_notifications.rb
560
- - test/distributed/test_mixed_plan.rb
561
- - test/distributed/test_connection.rb
562
- - test/distributed/test_execution.rb
563
- - test/distributed/test_protocol.rb
564
- - test/test_task.rb
565
- - test/test_control.rb
566
- - test/test_transactions_proxy.rb
567
- - test/test_testcase.rb
568
588
  - test/test_propagation.rb
589
+ - test/test_query.rb
590
+ - test/test_relations.rb
569
591
  - test/test_state.rb
570
- - test/test_log.rb
592
+ - test/test_support.rb
593
+ - test/test_task.rb
594
+ - test/test_testcase.rb
595
+ - test/test_thread_task.rb
596
+ - test/test_transactions.rb
597
+ - test/test_transactions_proxy.rb