Skip to content

Commit

Permalink
Decompose Mdm::Module::Instance#intersecting_platforms_with
Browse files Browse the repository at this point in the history
MSP-9228

Mdm::Module::Instance.intersecting_platforms will handle searching
Mdm::Platforms, while intersecting_platforms_with will handle searching
module_target and use intersecting_platforms to search the
module_target.platforms in turn.
intersecting_platform_fully_qualified_names will turn those
Mdm::Platform#fully_qualified_names into Mdm::Platforms that are then
passed to intersecting_platform.
  • Loading branch information
limhoff-r7 committed Jan 31, 2014
1 parent 14aa09a commit 1b6eafe
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 107 deletions.
46 changes: 37 additions & 9 deletions app/models/mdm/module/instance.rb
Expand Up @@ -290,21 +290,20 @@ class Mdm::Module::Instance < ActiveRecord::Base
)
}

# @!method intersecting_platforms_with(module_target)
# List of {Mdm::Module::Instance Mdm::Module::Instances} that share at least 1 {Mdm::Platform} or descendant with
# the given `module_target`'s {Mdm::Module::Target#platforms}.
# @!method self.intersecting_platforms(platforms)
# List of {Mdm::Module::Instance Mdm::Module::Instances} that has at least 1 {Mdm::Platform} from `platforms`.
#
# @param module_target [Mdm::Module::Target] target whose {Mdm::Module::Target#platforms} need to have at least 1
# {Mdm::Platform} or its descendants shared with the returned {Mdm::Module::Instance Mdm::Module::Instances'}
# @param platforms [Enumerable<Mdm::Platform>, #collect] list of {Mdm::Platform Mdm::Platforms} need to themselves
# or their descendants shared with the returned {Mdm::Module::Instance Mdm::Module::Instances'}
# {Mdm::Module::Instance#platforms}.
# @return [ActiveRecord::Relation<Mdm::Module::Instance>]
scope :intersecting_platforms_with,
->(module_target){
scope :intersecting_platforms,
->(platforms){
platforms_arel_table = Mdm::Platform.arel_table
platforms_left = platforms_arel_table[:left]
platforms_right = platforms_arel_table[:right]

platform_intersection_conditions = module_target.platforms.collect { |platform|
platform_intersection_conditions = platforms.collect { |platform|
platform_left = platform.left
platform_right = platform.right

Expand All @@ -320,13 +319,42 @@ class Mdm::Module::Instance < ActiveRecord::Base
}
platform_intersection_union = platform_intersection_conditions.reduce(:or)

includes(
joins(
:platforms
).where(
platform_intersection_union
)
}

# @!method self.intersecting_platform_fully_qualified_names(platform_fully_qualified_names)
# List of {Mdm::Module::Instance Mdm::Module::Instances} that has at least 1 {Mdm::Platform}
# that either has a {Mdm::Platform#fully_qualified_name} from `platform_fully_qualified_names` or that has an
# descendant with a {Mdm::Platform#fully_qualified_name} from `platform_fully_qualified_names`.
#
# @param platform_fully_qualified_names [Array<String>] `Array` of {Mdm::Platform#fully_qualified_name}.
# @return [ActiveRecord::Relation<Mdm::Module::Instance>]
scope :intersecting_platform_fully_qualified_names,
->(platform_fully_qualified_names){
intersecting_platforms(
Mdm::Platform.where(
fully_qualified_name: platform_fully_qualified_names
)
)
}

# @!method self.intersecting_platforms_with(module_target)
# List of {Mdm::Module::Instance Mdm::Module::Instances} that share at least 1 {Mdm::Platform} or descendant with
# the given `module_target`'s {Mdm::Module::Target#platforms}.
#
# @param module_target [Mdm::Module::Target] target whose {Mdm::Module::Target#platforms} need to have at least 1
# {Mdm::Platform} or its descendants shared with the returned {Mdm::Module::Instance Mdm::Module::Instances'}
# {Mdm::Module::Instance#platforms}.
# @return [ActiveRecord::Relation<Mdm::Module::Instance>]
scope :intersecting_platforms_with,
->(module_target){
intersecting_platforms(module_target.platforms)
}

# @!method nops_compatible_with(module_instance)
# {Mdm::Module::Instance Mdm::Module::Instances} that share at least 1 {Mdm::Architecture} with the given
# `module_instance`'s {Mdm::Module::Instance#archtiectures} and have {#module_class}
Expand Down
270 changes: 172 additions & 98 deletions spec/app/models/mdm/module/instance_spec.rb
@@ -1,6 +1,121 @@
require 'spec_helper'

describe Mdm::Module::Instance do
#
# Shared contexts
#

shared_context 'platforms' do
#
# lets
#

let(:platform) do
Mdm::Platform.where(fully_qualified_name: platform_fully_qualified_name).first
end

let(:platform_fully_qualified_name) do
'Windows XP'
end

let(:other_module_class) do
FactoryGirl.create(
:mdm_module_class,
module_type: other_module_type
)
end

let(:other_module_type) do
'payload'
end

let(:other_platform) do
Mdm::Platform.where(fully_qualified_name: other_platform_fully_qualified_name).first
end

#
# let!s
#

let!(:other_module_instance) do
FactoryGirl.build(
:mdm_module_instance,
module_class: other_module_class,
module_platforms_length: 0
).tap { |module_instance|
module_instance.module_platforms.build(
{
platform: other_platform
},
{
without_protection: true
}
)
module_instance.save!
}
end
end

#
# Shared Examples
#

shared_examples_for 'intersecting platforms' do
context 'with same platform' do
let(:other_platform) do
platform
end

it 'includes the Mdm::Module::Instance' do
expect(subject).to include(other_module_instance)
end
end

context 'with ancestor platform' do
let(:other_platform_fully_qualified_name) do
'Windows'
end

it 'includes the Mdm::Module::Instance' do
expect(subject).to include(other_module_instance)
end
end

context 'with descendant platform' do
let(:other_platform_fully_qualified_name) do
'Windows XP SP1'
end

it 'includes the Mdm::Module::Instance' do
expect(subject).to include(other_module_instance)
end
end

context 'with cousin platform' do
let(:other_platform_fully_qualified_name) do
'Windows XP SP1'
end

let(:platform_fully_qualified_name) do
'Windows 2000 SP1'
end

it 'does not include Mdm::Module::Instance' do
expect(subject).not_to include(other_module_instance)
end
end

context 'with unrelated platform' do
let(:other_platform_fully_qualified_name) do
'UNIX'
end

it 'does not include Mdm::Module::Instance' do
expect(subject).not_to include(other_module_instance)
end
end
end

subject(:module_instance) do
FactoryGirl.build(:mdm_module_instance)
end
Expand Down Expand Up @@ -297,21 +412,59 @@
end
end

context 'intersecting_platforms_with' do
subject(:intersecting_platforms_with) do
described_class.intersecting_platforms_with(module_target)
context 'intersecting_platforms' do
include_context 'platforms'

subject(:intersecting_platforms) do
described_class.intersecting_platforms(platforms)
end

#
# lets
#
let(:platforms) do
[
platform
]
end

let(:platform) do
Mdm::Platform.where(fully_qualified_name: platform_fully_qualified_name).first
it_should_behave_like 'intersecting platforms'
end

context 'intersecting_platform_fully_qualified_names' do
include_context 'platforms'

subject(:intersecting_platform_fully_qualified_names) do
described_class.intersecting_platform_fully_qualified_names(platform_fully_qualified_names)
end

let(:platform_fully_qualified_name) do
'Windows XP'
let(:other_platform_fully_qualified_name) do
platform_fully_qualified_name
end

let(:platform_fully_qualified_names) do
platform_fully_qualified_name
end

it_should_behave_like 'intersecting platforms'

it 'calls intersecting_platforms with ActiveRecord::Relation<Mdm::Platform>' do
expect(described_class).to receive(:intersecting_platforms).with(an_instance_of(ActiveRecord::Relation))

intersecting_platform_fully_qualified_names
end

it 'calls intersecting_platforms with Mdm::Platforms with platform_fully_qualified_names' do
expect(described_class).to receive(:intersecting_platforms) { |platforms|
expect(platforms).to match_array([platform])
}.and_call_original

intersecting_platform_fully_qualified_names
end
end

context 'intersecting_platforms_with' do
include_context 'platforms'

subject(:intersecting_platforms_with) do
described_class.intersecting_platforms_with(module_target)
end

let(:module_target) do
Expand All @@ -336,102 +489,23 @@
without_protection: true
}
)
}
end

let(:other_module_class) do
FactoryGirl.create(
:mdm_module_class,
module_type: other_module_type
)
end

let(:other_module_instance) do
FactoryGirl.build(
:mdm_module_instance,
module_class: other_module_class,
module_platforms_length: 0
).tap { |module_instance|
module_instance.module_platforms.build(
{
platform: other_platform
},
{
without_protection: true
}
)
module_target.save!
}
end

let(:other_module_type) do
'payload'
end

let(:other_platform) do
Mdm::Platform.where(fully_qualified_name: other_platform_fully_qualified_name).first
end

#
# Callbacks
#

before(:each) do
module_target.save!
other_module_instance.save!
let(:other_platform_fully_qualified_name) do
platform_fully_qualified_name
end

context 'with same platform' do
let(:other_platform) do
platform
end
it_should_behave_like 'intersecting platforms'

it 'includes the Mdm::Module::Instance' do
expect(intersecting_platforms_with).to include(other_module_instance)
end
end

context 'with ancestor platform' do
let(:other_platform_fully_qualified_name) do
'Windows'
end

it 'includes the Mdm::Module::Instance' do
expect(intersecting_platforms_with).to include(other_module_instance)
end
end
it 'calls #intersecting_platforms with module_target.platforms' do
expect(described_class).to receive(:intersecting_platforms) { |platforms|
expect(platforms).to match_array(module_target.platforms)
}.and_call_original

context 'with descendant platform' do
let(:other_platform_fully_qualified_name) do
'Windows XP SP1'
end

it 'includes the Mdm::Module::Instance' do
expect(intersecting_platforms_with).to include(other_module_instance)
end
end

context 'with cousin platform' do
let(:other_platform_fully_qualified_name) do
'Windows XP SP1'
end

let(:platform_fully_qualified_name) do
'Windows 2000 SP1'
end

it 'does not include Mdm::Module::Instance' do
expect(intersecting_platforms_with).not_to include(other_module_instance)
end
end

context 'with unrelated platform' do
let(:other_platform_fully_qualified_name) do
'UNIX'
end

it 'does not include Mdm::Module::Instance' do
expect(intersecting_platforms_with).not_to include(other_module_instance)
end
intersecting_platforms_with
end
end

Expand Down

0 comments on commit 1b6eafe

Please sign in to comment.