From dfbe240cf13e33e70709fb8fee0c5768da97ae8b Mon Sep 17 00:00:00 2001 From: Kyle Hammond Date: Wed, 3 Jan 2024 17:04:51 -0600 Subject: [PATCH 1/2] Fixes #59 - sort components and dependencies before output. --- lib/cyclonedx/cocoapods/bom_builder.rb | 6 +- spec/cyclonedx/cocoapods/bom_builder_spec.rb | 72 +++++++++++++++----- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/lib/cyclonedx/cocoapods/bom_builder.rb b/lib/cyclonedx/cocoapods/bom_builder.rb index 9633f5d..b318098 100644 --- a/lib/cyclonedx/cocoapods/bom_builder.rb +++ b/lib/cyclonedx/cocoapods/bom_builder.rb @@ -123,9 +123,9 @@ class BOMBuilder attr_reader :component, :pods, :dependencies def initialize(pods:, component: nil, dependencies: nil) - @pods = pods + @pods = pods.sort_by(&:purl) @component = component - @dependencies = dependencies + @dependencies = dependencies&.sort end def bom(version: 1) @@ -152,7 +152,7 @@ def bom(version: 1) def bom_dependencies(xml, dependencies) dependencies&.each do |key, array| xml.dependency(ref: key) do - array.each do |value| + array.sort.each do |value| xml.dependency(ref: value) end end diff --git a/spec/cyclonedx/cocoapods/bom_builder_spec.rb b/spec/cyclonedx/cocoapods/bom_builder_spec.rb index cfb7b55..96122d2 100644 --- a/spec/cyclonedx/cocoapods/bom_builder_spec.rb +++ b/spec/cyclonedx/cocoapods/bom_builder_spec.rb @@ -255,6 +255,7 @@ RSpec.describe CycloneDX::CocoaPods::BOMBuilder do context 'when generating a BOM' do + # Important: these pods are NOT in alphabetical order; they will be sorted in output let(:pods) do { 'Alamofire' => '5.6.2', @@ -265,6 +266,7 @@ 'MSAL/app-lib' => '1.2.1' }.map { |name, version| CycloneDX::CocoaPods::Pod.new(name: name, version: version) } end + # Important: these dependencies are NOT in alphabetical order; they will be sorted in output let(:dependencies) do { 'pkg:cocoapods/Alamofire@5.6.2' => [], @@ -362,13 +364,50 @@ it 'should properly delegate component node generation to pods' do components_generated_from_bom_builder = xml.at('bom/components') - components = Nokogiri::XML(Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml| - xml.components(xmlns: described_class::NAMESPACE) do - bom_builder.pods.each { |pod| pod.add_to_bom(xml) } - end - end.to_xml).at('components') - - expect(components_generated_from_bom_builder).to be_equivalent_to(components) + # Important: these expected components are sorted alphabetically + expected_components_string = + ' + + Alamofire + 5.6.2 + pkg:cocoapods/Alamofire@5.6.2 + pkg:cocoapods/Alamofire@5.6.2 + + + FirebaseAnalytics + 7.10.0 + pkg:cocoapods/FirebaseAnalytics@7.10.0 + pkg:cocoapods/FirebaseAnalytics@7.10.0 + + + MSAL + 1.2.1 + pkg:cocoapods/MSAL@1.2.1 + pkg:cocoapods/MSAL@1.2.1 + + + MSAL/app-lib + 1.2.1 + pkg:cocoapods/MSAL@1.2.1#app-lib + pkg:cocoapods/MSAL@1.2.1#app-lib + + + Realm + 5.5.1 + pkg:cocoapods/Realm@5.5.1 + pkg:cocoapods/Realm@5.5.1 + + + RxSwift + 5.1.2 + pkg:cocoapods/RxSwift@5.1.2 + pkg:cocoapods/RxSwift@5.1.2 + + ' + + components = Nokogiri::XML expected_components_string + + expect(components_generated_from_bom_builder.to_xml).to be_equivalent_to(components.root.to_xml).respecting_element_order end it 'should generate a child dependencies node' do @@ -380,7 +419,7 @@ dependencies = Nokogiri::XML dependencies_result - expect(dependencies_generated_from_bom_builder.to_xml).to be_equivalent_to(dependencies.root.to_xml) + expect(dependencies_generated_from_bom_builder.to_xml).to be_equivalent_to(dependencies.root.to_xml).respecting_element_order end end end @@ -395,16 +434,17 @@ context 'with a component' do let(:component) { CycloneDX::CocoaPods::Component.new(name: 'Application', version: '1.3.5', type: 'application') } let(:bom_builder) { described_class.new(component: component, pods: pods, dependencies: dependencies) } + # Important: these expected dependencies are sorted alphabetically let(:dependencies_result) do ' - - - - - - - - ' + + + + + + + + ' end it_behaves_like "bom_generator" From 79c6e81e21e0616d42b347f3af754098d8e623e0 Mon Sep 17 00:00:00 2001 From: Kyle Hammond Date: Wed, 3 Jan 2024 17:05:33 -0600 Subject: [PATCH 2/2] Change use of double quotes to single quotes for some simple strings, and fix a spelling error. --- spec/cyclonedx/cocoapods/bom_builder_spec.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/spec/cyclonedx/cocoapods/bom_builder_spec.rb b/spec/cyclonedx/cocoapods/bom_builder_spec.rb index 96122d2..84cc22b 100644 --- a/spec/cyclonedx/cocoapods/bom_builder_spec.rb +++ b/spec/cyclonedx/cocoapods/bom_builder_spec.rb @@ -185,7 +185,7 @@ context 'which includes text' do let(:license) { license_with_text = described_class.new(identifier: described_class::SPDX_LICENSES.sample) - license_with_text.text = "Copyright 2012\nPermission is granted to..." + license_with_text.text = 'Copyright 2012\nPermission is granted to...' license_with_text } @@ -198,7 +198,7 @@ context 'which includes url' do let(:license) { license_with_url = described_class.new(identifier: described_class::SPDX_LICENSES.sample) - license_with_url.url = "https://opensource.org/licenses/MIT" + license_with_url.url = 'https://opensource.org/licenses/MIT' license_with_url } @@ -214,7 +214,7 @@ RSpec.describe CycloneDX::CocoaPods::Component do context 'when generating a component in a BOM' do - shared_examples "component" do + shared_examples 'component' do it 'should generate a root component element' do expect(xml.at('/component')).not_to be_nil expect(xml.at('/component')['type']).to eq(component.type) @@ -232,7 +232,7 @@ let(:component) { described_class.new(name: 'Application', version: '1.3.5', type: 'application') } let(:xml) { Nokogiri::XML(Nokogiri::XML::Builder.new(encoding: 'UTF-8') { |xml| component.add_to_bom(xml) }.to_xml) } - it_behaves_like "component" + it_behaves_like 'component' it 'should not generate any group element' do expect(xml.at('/component/group')).to be_nil @@ -243,7 +243,7 @@ let(:component) { described_class.new(group: 'application-group', name: 'Application', version: '1.3.5', type: 'application') } let(:xml) { Nokogiri::XML(Nokogiri::XML::Builder.new(encoding: 'UTF-8') { |xml| component.add_to_bom(xml) }.to_xml) } - it_behaves_like "component" + it_behaves_like 'component' it 'should generate a proper group element' do expect(xml.at('/component/group')).not_to be_nil @@ -277,7 +277,7 @@ } end - shared_examples "bom_generator" do + shared_examples 'bom_generator' do context 'with an incorrect version' do it 'should raise for non integer versions' do expect { bom_builder.bom(version: 'foo') }.to raise_error(ArgumentError) @@ -414,7 +414,7 @@ expect(xml.at('bom/dependencies')).not_to be_nil end - it 'shoudl properly set dependencies node' do + it 'should properly set dependencies node' do dependencies_generated_from_bom_builder = xml.at('bom/dependencies') dependencies = Nokogiri::XML dependencies_result @@ -428,7 +428,7 @@ let(:bom_builder) { described_class.new(pods: pods) } let(:dependencies_result) { '' } - it_behaves_like "bom_generator" + it_behaves_like 'bom_generator' end context 'with a component' do @@ -447,7 +447,7 @@ ' end - it_behaves_like "bom_generator" + it_behaves_like 'bom_generator' end end end