Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 55 additions & 21 deletions lib/syskit/dependency_injection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,31 +202,65 @@ def self.normalize_selection(selection)
next
end

if value.respond_to?(:fullfills?) && !value.fullfills?(key)
raise ArgumentError,
"found #{value.name}(of class #{value.class}) " \
"as a selection for #{key.name}, but " \
"#{value.name} does not fullfill #{key.name}"
normalized[key] = normalize_component_model_selection(key, value)
end
normalized
end

# @api private
#
# Helper for normalize_selection when the key is a component model (e.g.
# "real" component model, data service model or placeholder model)
#
# @param [Class<AbstractComponent>] key
# @param [String,SpecialDIValue,#fullfills?] value
# @return [String,SpecialDIValue,#fullfills?] normalized selected value
def self.normalize_component_model_selection(key, value)
if value.respond_to?(:to_str)
return value
elsif value.kind_of?(SpecialDIValue)
return value
end

unless value.fullfills?(key)
raise ArgumentError,
"found #{value.name}(of class #{value.class}) " \
"as a selection for #{key.name}, but " \
"#{value.name} does not fullfill #{key.name}"
end

required_component_m = nil
required_services_m = []
required_component_m, required_services_m =
key.each_required_model.partition do |m|
m <= Component
end
if required_services_m.size > 1
raise NotImplementedError,
"there is no support (yet) to select for multiple services"
elsif !required_component_m && required_services_m.empty?
raise NotImplementedError, "nothing to select in #{key}"
end

if key <= Component
if value.kind_of?(Models::BoundDataService)
value = value.component_model
elsif value.kind_of?(Syskit::BoundDataService)
value = value.component
end
normalized[key] = value
elsif key <= DataService
if value.respond_to?(:find_data_service_from_type)
value = value.find_data_service_from_type(key)
end
normalized[key] = value
else
raise NotImplementedError,
"should not have get there, but did"
required_component_m = required_component_m.first
required_service_m = required_services_m.first

if required_service_m && !required_component_m
if value.respond_to?(:find_data_service_from_type)
value =
value.find_data_service_from_type(required_services_m.first)
end

value
else
if value.kind_of?(Models::BoundDataService)
value = value.component_model
elsif value.kind_of?(Syskit::BoundDataService)
value = value.component
end

value
end
normalized
end

# Add a list of objects to the default list.
Expand Down
16 changes: 16 additions & 0 deletions test/actions/test_profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,22 @@ module Actions
.requirements.instanciate(plan)
assert_kind_of srv_task_m, task.test_child
end

it "forwards explicitly selected services" do
srv_m = DataService.new_submodel
task_m = TaskContext.new_submodel
task_m.provides srv_m, as: "srv1"
task_m.provides srv_m, as: "srv2"
Comment on lines +233 to +234

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how providing the same service twice is relevant for this test?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sure that the system does not fall back on the implicit service selection code path (since that code path would fail). The caller must explicitly select a service.

cmp_m = Composition.new_submodel
cmp_m.add srv_m, as: "srv"
base_profile = Profile.new
base_profile.tag "srv", srv_m
base_profile.define "d", cmp_m.use("srv" => base_profile.srv_tag)
profile = Profile.new
profile.use_profile base_profile, "srv" => task_m.srv1_srv

profile.d_def.instanciate(plan)
end
end

describe "#define" do
Expand Down
Loading