require File.expand_path('../../spec_helper', __FILE__) module Pod DONT_CODESIGN = true describe Command::Spec::Packagethk do describe 'CLAide' do after do Dir.glob("Archs-*").each { |dir| Pathname.new(dir).rmtree } Dir.glob("CPDColors-*").each { |dir| Pathname.new(dir).rmtree } Dir.glob("KFData-*").each { |dir| Pathname.new(dir).rmtree } Dir.glob("NikeKit-*").each { |dir| Pathname.new(dir).rmtree } Dir.glob("LocalNikeKit-*").each { |dir| Pathname.new(dir).rmtree } Dir.glob("foo-bar-*").each { |dir| Pathname.new(dir).rmtree } Dir.glob("a-*").each { |dir| Pathname.new(dir).rmtree } Dir.glob("FH-*").each { |dir| Pathname.new(dir).rmtree } Dir.glob("FirebaseAnalytics-*").each { |dir| Pathname.new(dir).rmtree } end def reject_block_symbols(symbols) symbols .reject { |e| e =~ /__block_descriptor.*/ } .reject { |e| e =~ /__destroy_helper_block.*/ } .reject { |e| e =~ /__copy_helper_block.*/ } end it 'registers itself' do Command.parse(%w{ package }).should.be.instance_of Command::Packagethk end it 'presents the help if no spec is provided' do command = Command.parse(%w{ package }) should.raise CLAide::Help do command.validate! end.message.should.match /required/ end it "errors if it cannot find a spec" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(%w{ package KFData }) should.raise CLAide::Help do command.run end.message.should.match /Unable to find/ end it "should produce a dynamic library when dynamic is specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--dynamic']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first file_command = "file #{lib}" output = `#{file_command}`.lines.to_a output[0].should.match /Mach-O universal binary with 5 architectures/ output[1].should.match /Mach-O dynamically linked shared library i386/ end it "should produce a dSYM when dynamic is specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--dynamic']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework.dSYM/Contents/Resources/DWARF/NikeKit").first file_command = "file #{lib}" output = `#{file_command}`.lines.to_a output[0].should.match /Mach-O universal binary with 3 architectures/ output[1].should.match /Mach-O dSYM companion file arm/ end it "should link category symbols when dynamic is specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--dynamic']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first file_command = "nm #{lib}" output = `#{file_command}`.lines.to_a match = output.detect { |line| line =~ /UIButton\(AFNetworking\)/ } match.should.not.be.empty end it "should produce a dynamic library for OSX when dynamic is specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('KFData.podspec'), '--dynamic']) command.run lib = Dir.glob("KFData-*/osx/KFData.framework/KFData").first file_command = "file #{lib}" output = `#{file_command}`.lines.to_a output[0].should.match /Mach-O 64-bit dynamically linked shared library x86_64/ end it "should produce a dSYM for OSX when dynamic is specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('KFData.podspec'), '--dynamic']) command.run lib = Dir.glob("KFData-*/osx/KFData.framework.dSYM/Contents/Resources/DWARF/KFData").first file_command = "file #{lib}" output = `#{file_command}`.lines.to_a output[0].should.match /Mach-O 64-bit dSYM companion file x86_64/ end it "should produce the default plist for iOS and OSX when --dynamic is specified but --bundle-identifier is not" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('KFData.podspec'), '--dynamic']) command.run ios_plist = File.expand_path(Dir.glob("KFData-*/ios/KFData.framework/Info.plist").first) osx_plist = File.expand_path(Dir.glob("KFData-*/osx/KFData.framework/Resources/Info.plist").first) ios_bundle_id = `defaults read #{ios_plist} CFBundleIdentifier` osx_bundle_id = `defaults read #{osx_plist} CFBundleIdentifier` ios_bundle_id.should.match /org.cocoapods.KFData/ osx_bundle_id.should.match /org.cocoapods.KFData/ end it "should produce the correct plist for iOS and OSX when --dynamic and --bundle-identifier are specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('KFData.podspec'), '--dynamic', '--bundle-identifier=com.example.KFData']) command.run ios_plist = File.expand_path(Dir.glob("KFData-*/ios/KFData.framework/Info.plist").first) osx_plist = File.expand_path(Dir.glob("KFData-*/osx/KFData.framework/Resources/Info.plist").first) ios_bundle_id = `defaults read #{ios_plist} CFBundleIdentifier` osx_bundle_id = `defaults read #{osx_plist} CFBundleIdentifier` ios_bundle_id.should.match /com.example.KFData/ osx_bundle_id.should.match /com.example.KFData/ end it "should produce a static library when dynamic is not specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec')]) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first file_command = "file #{lib}" output = `#{file_command}`.lines.to_a output[0].should.match /Mach-O universal binary with 5 architectures/ output[1].should.match /current ar archive/ end it "produces package using local sources when --local is specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('LocalSources/LocalNikeKit.podspec'), '--local']) command.run lib = Dir.glob("LocalNikeKit-*/ios/LocalNikeKit.framework/LocalNikeKit").first symbols = Symbols.symbols_from_library(lib) symbols.should.include('LocalNikeKit') symbols.should.not.include('BBUNikePlusActivity') end it "includes vendor symbols both from itself and pod dependencies" do command = Command.parse(%w{ package FirebaseAnalytics --no-mangle }) command.run lib = Dir.glob("FirebaseAnalytics-*/ios/FirebaseAnalytics.framework/FirebaseAnalytics").first symbols = Symbols.symbols_from_library(lib) # from itself symbols.should.include('FIRAnalytics') # from pod dependency symbols.should.include('FIRApp') end it "does not include vendor symbols from pod dependencies if option --exclude-deps is specified" do command = Command.parse(%w{ package FirebaseAnalytics --no-mangle --exclude-deps}) command.run lib = Dir.glob("FirebaseAnalytics-*/ios/FirebaseAnalytics.framework/FirebaseAnalytics").first symbols = Symbols.symbols_from_library(lib) # from itself symbols.should.include('FIRAnalytics') # from pod dependency symbols.should.not.include('FIRApp') end it "includes only available architectures when packaging an iOS Pod with binary dependencies" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('Archs.podspec'), '--no-mangle']) command.run lib = Dir.glob("Archs-*/ios/Archs.framework/Archs").first `lipo #{lib} -verify_arch x86_64 i386 armv7 arm64` $?.success?.should == true end it "mangles symbols if the Pod has dependencies" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec')]) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /PodNikeKit/ } symbols = reject_block_symbols(symbols) symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager BBUNikePlusTag } end it "mangles symbols if the Pod has dependencies and framework is dynamic" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--dynamic']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /PodNikeKit/ } symbols = reject_block_symbols(symbols) symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager BBUNikePlusTag NikeKitVersionNumber NikeKitVersionString } end it "mangles symbols if the Pod has dependencies regardless of name" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('a.podspec')]) command.run lib = Dir.glob("a-*/ios/a.framework/a").first symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /Poda/ } symbols = reject_block_symbols(symbols) symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager BBUNikePlusTag } end it "does not mangle symbols if option --no-mangle is specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--no-mangle']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /PodNikeKit/ } symbols.should == [] end it "does not mangle symbols if option --no-mangle and --dynamic are specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--no-mangle', '--dynamic']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /PodNikeKit/ } symbols.should == [] end it "does not include symbols from dependencies if option --exclude-deps is specified" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--exclude-deps']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /AFNetworking|ISO8601DateFormatter|KZPropertyMapper/ } symbols.should == [] end it "includes the correct architectures when packaging an iOS Pod" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec')]) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first `lipo #{lib} -verify_arch x86_64 i386 armv7 armv7s arm64` $?.success?.should == true end it "includes the correct architectures when packaging an iOS Pod as --dynamic" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--dynamic']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first `lipo #{lib} -verify_arch armv7 armv7s arm64` $?.success?.should == true end it "includes Bitcode for device arch slices when packaging an iOS Pod" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec')]) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first #Check for __LLVM segment in each device architecture `lipo -extract armv7 #{lib} -o armv7.a && otool -l armv7.a`.should.match /__LLVM/ `lipo -extract armv7s #{lib} -o armv7s.a && otool -l armv7s.a`.should.match /__LLVM/ `lipo -extract arm64 #{lib} -o arm64.a && otool -l arm64.a`.should.match /__LLVM/ `rm armv7.a armv7s.a arm64.a` end it "includes Bitcode for device arch slices when packaging an dynamic iOS Pod" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--dynamic']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first #Check for __LLVM segment in each device architecture `lipo -extract armv7 #{lib} -o armv7.a && otool -l armv7.a`.should.match /__LLVM/ `lipo -extract armv7s #{lib} -o armv7s.a && otool -l armv7s.a`.should.match /__LLVM/ `lipo -extract arm64 #{lib} -o arm64.a && otool -l arm64.a`.should.match /__LLVM/ `rm armv7.a armv7s.a arm64.a` end it "does not include Bitcode for simulator arch slices when packaging an iOS Pod" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec')]) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first #Check for __LLVM segment in each simulator architecture `lipo -extract i386 #{lib} -o i386.a && otool -l i386.a`.should.not.match /__LLVM/ `lipo -extract x86_64 #{lib} -o x86_64.a && otool -l x86_64.a`.should.not.match /__LLVM/ `rm i386.a x86_64.a` end it "does not include Bitcode for simulator arch slices when packaging an dynamic iOS Pod" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec'), '--dynamic']) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first #Check for __LLVM segment in each simulator architecture `lipo -extract i386 #{lib} -o i386.a && otool -l i386.a`.should.not.match /__LLVM/ `lipo -extract x86_64 #{lib} -o x86_64.a && otool -l x86_64.a`.should.not.match /__LLVM/ `rm i386.a x86_64.a` end it "does not include local ModuleCache references" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('NikeKit.podspec')]) command.run lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first #Check for ModuleCache references `strings #{lib}`.should.not.match /ModuleCache/ end it "does not fail when the pod name contains a dash" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('foo-bar.podspec')]) command.run true.should == true # To make the test pass without any shoulds end it "runs with a path to a spec" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('KFData.podspec')]) command.run true.should == true # To make the test pass without any shoulds end it "it respects module_map directive" do Pod::Config.instance.sources_manager.stubs(:search).returns(nil) command = Command.parse(['package', fixture('FH.podspec')]) command.run modulemap_contents = File.read(Dir.glob("FH-*/ios/FH.framework/Modules/module.modulemap").first) module_map = <