roby 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
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