From d96806bbc67f9a9e42791b319d1dddaf8a3cd34f Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 9 May 2022 02:55:30 -0700 Subject: [PATCH] Move Flipper to dedicated flipper.rb Summary: This Diff moves all the Flipper.rb related setup in the cocoapods scripts to a dedicated script. It also removes the not needed dummy files and add tests for flipper. ## Changelog [iOS][Internal] - Extract Flipper setup in a separate file and add tests Reviewed By: cortinico Differential Revision: D36129808 fbshipit-source-id: 5446203a69b527146c893aa9611e98688e20b778 --- .../cocoapods/__tests__/dummy_test-test.rb | 12 -- .../cocoapods/__tests__/dummy_test2-test.rb | 12 -- scripts/cocoapods/__tests__/flipper-test.rb | 162 ++++++++++++++++++ .../__tests__/subfolder/dummy_test3-test.rb | 12 -- .../__tests__/test_utils/InstallerMock.rb | 79 +++++++++ .../cocoapods/__tests__/test_utils/podSpy.rb | 36 ++++ scripts/cocoapods/flipper.rb | 94 ++++++++++ .../submodule/__tests__/dummy_test4-test.rb | 12 -- scripts/react_native_pods.rb | 59 +------ 9 files changed, 374 insertions(+), 104 deletions(-) delete mode 100644 scripts/cocoapods/__tests__/dummy_test-test.rb delete mode 100644 scripts/cocoapods/__tests__/dummy_test2-test.rb create mode 100644 scripts/cocoapods/__tests__/flipper-test.rb delete mode 100644 scripts/cocoapods/__tests__/subfolder/dummy_test3-test.rb create mode 100644 scripts/cocoapods/__tests__/test_utils/InstallerMock.rb create mode 100644 scripts/cocoapods/__tests__/test_utils/podSpy.rb create mode 100644 scripts/cocoapods/flipper.rb delete mode 100644 scripts/cocoapods/submodule/__tests__/dummy_test4-test.rb diff --git a/scripts/cocoapods/__tests__/dummy_test-test.rb b/scripts/cocoapods/__tests__/dummy_test-test.rb deleted file mode 100644 index 87ada0fc2af..00000000000 --- a/scripts/cocoapods/__tests__/dummy_test-test.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -require "test/unit" - -class DummyTest < Test::Unit::TestCase - def test_add - assert_equal(5, 2+3) - end -end diff --git a/scripts/cocoapods/__tests__/dummy_test2-test.rb b/scripts/cocoapods/__tests__/dummy_test2-test.rb deleted file mode 100644 index c8e4c5071a1..00000000000 --- a/scripts/cocoapods/__tests__/dummy_test2-test.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -require "test/unit" - -class DummyTest2 < Test::Unit::TestCase - def test_sub - assert_equal(5, 11-6) - end -end diff --git a/scripts/cocoapods/__tests__/flipper-test.rb b/scripts/cocoapods/__tests__/flipper-test.rb new file mode 100644 index 00000000000..300d80406b4 --- /dev/null +++ b/scripts/cocoapods/__tests__/flipper-test.rb @@ -0,0 +1,162 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "test/unit" +require_relative "../flipper.rb" +require_relative "./test_utils/podSpy.rb" +require_relative "./test_utils/InstallerMock.rb" + +class FlipperTests < Test::Unit::TestCase + def setup + podSpy_cleanUp() + end + + # =========================== # + # TEST - Install Dependencies # + # =========================== # + def test_installFlipperDependencies_whenProductionIsFalse_installDependencies + # Act + install_flipper_dependencies(false, '../..') + + # Assert + assert_equal($podInvocationCount, 1) + assert_equal($podInvocation['React-Core/DevSupport'][:path], "../../" ) + end + + def test_installFlipperDependencies_whenProductionIsTrue_skipDependencies + # Act + install_flipper_dependencies(true, '../..') + + # Assert + assert_equal($podInvocationCount, 0) + assert_true($podInvocation.empty?) + end + + # ======================= # + # TEST - Use Flipper Pods # + # ======================= # + + def test_UseFlipperPods_WithDefaultValues_InstallsPods + # Arrange + configurations = ['Debug'] + + # Act + use_flipper_pods() + + # Assert + check_all_flipper_pods($flipper_default_versions, configurations) + # the number of times the `pod` function has been invoked to install a dependency + assert_equal($podInvocationCount, 22) + end + + def test_UseFlipperPods_WithCustomValues_InstallsPods + # Arrange + versions = { + "Flipper" => "1.0.0", + "Flipper-Boost-iOSX" => "1.1.0", + "Flipper-DoubleConversion" => "1.1.1", + "Flipper-Fmt" => "1.2.1", + "Flipper-Folly" => "2.1.1", + "Flipper-Glog" => "0.1.2", + "Flipper-PeerTalk" => "0.0.1", + "Flipper-RSocket" => "0.1.4", + "OpenSSL-Universal" => "2.2.2200", + } + configurations = ['Debug', 'CI'] + + # Act + use_flipper_pods(versions, :configurations => configurations) + + # Assert + check_all_flipper_pods(versions, configurations) + # the number of times the `pod` function has been invoked to install a dependency + assert_equal($podInvocationCount, 22) + end + + # ================= # + # Test Post Install # + # ================= # + + def test_postInstall_updatesThePodCorrectly + # Arrange + installer = prepare_mocked_installer + + # Act + flipper_post_install(installer) + + # Assert + yoga_target = installer.target_with_name("YogaKit") + yoga_target.build_configurations.each do |config| + assert_equal(config.build_settings['SWIFT_VERSION'], '4.1') + end + + reactCore_target = installer.target_with_name("React-Core") + reactCore_target.build_configurations.each do |config| + if config.name == 'Debug' then + assert_equal(config.build_settings['OTHER_CFLAGS'], "$(inherited) -DFB_SONARKIT_ENABLED=1") + else + assert_true(config.build_settings.empty?) + end + end + end + + # ======= # + # HELPERS # + # ======= # + + def check_all_flipper_pods(versions, configurations) + check_flipper_pod('Flipper', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FlipperKitReactPlugin', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/Core', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/CppBridge', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FBDefines', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FKPortForwarding', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], configurations) + check_flipper_pod('FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], configurations) + check_flipper_pod('Flipper-Boost-iOSX', versions['Flipper-Boost-iOSX'], configurations) + check_flipper_pod('Flipper-DoubleConversion', versions['Flipper-DoubleConversion'], configurations) + check_flipper_pod('Flipper-Fmt', versions['Flipper-Fmt'], configurations) + check_flipper_pod('Flipper-Folly', versions['Flipper-Folly'], configurations) + check_flipper_pod('Flipper-Glog', versions['Flipper-Glog'], configurations) + check_flipper_pod('Flipper-PeerTalk', versions['Flipper-PeerTalk'], configurations) + check_flipper_pod('Flipper-RSocket', versions['Flipper-RSocket'], configurations) + check_flipper_pod('OpenSSL-Universal', versions['OpenSSL-Universal'], configurations) + end + + def check_flipper_pod(name, expectedVersion, expectedConfigurations) + params = $podInvocation[name] + assert_equal(params[:version], expectedVersion) + assert_equal(params[:configurations], expectedConfigurations) + end + + def prepare_mocked_installer + return InstallerMock.new( + PodsProjectMock.new([ + TargetMock.new( + "YogaKit", + [ + BuildConfigurationMock.new("Debug"), + BuildConfigurationMock.new("Release"), + ] + ), + TargetMock.new( + "React-Core", + [ + BuildConfigurationMock.new("Debug"), + BuildConfigurationMock.new("Release"), + ] + ) + ] + ) + ) + end + +end diff --git a/scripts/cocoapods/__tests__/subfolder/dummy_test3-test.rb b/scripts/cocoapods/__tests__/subfolder/dummy_test3-test.rb deleted file mode 100644 index f93c8ea8c86..00000000000 --- a/scripts/cocoapods/__tests__/subfolder/dummy_test3-test.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -require "test/unit" - -class DummyTest3 < Test::Unit::TestCase - def test_mul - assert_equal(12, 3*4) - end -end diff --git a/scripts/cocoapods/__tests__/test_utils/InstallerMock.rb b/scripts/cocoapods/__tests__/test_utils/InstallerMock.rb new file mode 100644 index 00000000000..856169b679f --- /dev/null +++ b/scripts/cocoapods/__tests__/test_utils/InstallerMock.rb @@ -0,0 +1,79 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +# This file replicate the structure of the Installer used Cocoapods in the post_install step. +# +# To use it, add `require_relative path/to/InstallerMock.rb` into your test file +# +# ## Initialization +# You can create a new mock with the `InstallerMock.new` statement. In this case, you will +# create an empty mock. +# +# It's possible to create complex with the initializer. To create an Installer with a pod, for example, we can +# use the following code: +# +# ```ruby +# installer = Installer.new( +# PodsProjectMock.new([ +# TargetMock.new( +# "MyPod", +# [ +# BuildConfigurationMock.new("Debug"), +# ] +# ) +# ) +# ) +# ``` +# +# ## Assert +# All the properties of these objects are accessible in read mode. +# To access the target's list, for example, you can use the following line: +# +# ```ruby +# targets = installer.pods_project.targets +# ``` + +class InstallerMock + attr_reader :pods_project + + def initialize(pods_project = PodsProjectMock.new) + @pods_project = pods_project + end + + def target_with_name(name) + return @pods_project.targets + .select { |target| target.name == name } + .first + end +end + +class PodsProjectMock + attr_reader :targets + + def initialize(targets = []) + @targets = targets + end +end + +class TargetMock + attr_reader :name + attr_reader :build_configurations + + def initialize(name, build_configurations = []) + @name = name + @build_configurations = build_configurations + end +end + +class BuildConfigurationMock + attr_reader :name + attr_reader :build_settings + + def initialize(name, build_settings = {}) + @name = name + @build_settings = build_settings + end +end diff --git a/scripts/cocoapods/__tests__/test_utils/podSpy.rb b/scripts/cocoapods/__tests__/test_utils/podSpy.rb new file mode 100644 index 00000000000..415bc73f832 --- /dev/null +++ b/scripts/cocoapods/__tests__/test_utils/podSpy.rb @@ -0,0 +1,36 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# This file contains the utilities required to mock properly the +# usage of the `pod` function. +# +# To use this file, just add `require_relative "path/to/podSpy.rb"` to your test file. +# +# Remember to invoke `podSpy_cleanUp` in your setup/teardown method, to start from a clean situation. +# +# Whenever your ruby script uses the `pod` function, the invocation is recorded in the `$podInvocation` global +# variable. A $podInvocationCount counter is increased as well. +# +# You can assert against these variables to check: +# * The `pod` function has been invoked X times: `assert_equal($podInvocationCount, X)` +# * A specific pod has been installed: `assert_equal($podInvocation["MyPod"][:version], "15.4.6")` + + +$podInvocation = {} +$podInvocationCount = 0 + +def podSpy_cleanUp + $podInvocation = {} + $podInvocationCount = 0 +end + +def pod(name, version = nil, path: nil, configurations: nil) + $podInvocationCount += 1 + params = {} + if version != nil then params[:version] = version end + if path != nil then params[:path] = path end + if configurations != nil then params[:configurations] = configurations end + $podInvocation[name] = params +end diff --git a/scripts/cocoapods/flipper.rb b/scripts/cocoapods/flipper.rb new file mode 100644 index 00000000000..d86cdfc2644 --- /dev/null +++ b/scripts/cocoapods/flipper.rb @@ -0,0 +1,94 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Default versions of Flipper and related dependencies. +# Update this map to bump the dependencies. +$flipper_default_versions = { + 'Flipper' => '0.125.0', + 'Flipper-Boost-iOSX' => '1.76.0.1.11', + 'Flipper-DoubleConversion' => '3.2.0', + 'Flipper-Fmt' => '7.1.7', + 'Flipper-Folly' => '2.6.10', + 'Flipper-Glog' => '0.5.0.4', + 'Flipper-PeerTalk' => '0.0.4', + 'Flipper-RSocket' => '1.4.3', + 'OpenSSL-Universal' => '1.1.1100', +} + +# This function installs the `React-Core/DevSupport` subpods +# when the dependencies are installed for a non production app. +# +# @parameter production: a boolean that indicates whether we are in production or not. +# @parameter pathToReactNative: the path to the React Native installation +def install_flipper_dependencies(production, pathToReactNative) + unless production + pod 'React-Core/DevSupport', :path => "#{pathToReactNative}/" + end +end + + +# This function installs all the dependencies required by flipper. +# +# @parameter versions: a dictionary to specify a version of a dependencies. Default versions will be used if not specified +# @parameter configurations: an array of configurations to install the flipper dependencies. Defaults to ['Debug']. +def use_flipper_pods(versions = {}, configurations: ['Debug']) + versions['Flipper'] ||= $flipper_default_versions['Flipper'] + versions['Flipper-Boost-iOSX'] ||= $flipper_default_versions['Flipper-Boost-iOSX'] + versions['Flipper-DoubleConversion'] ||= $flipper_default_versions['Flipper-DoubleConversion'] + versions['Flipper-Fmt'] ||= $flipper_default_versions['Flipper-Fmt'] + versions['Flipper-Folly'] ||= $flipper_default_versions['Flipper-Folly'] + versions['Flipper-Glog'] ||= $flipper_default_versions['Flipper-Glog'] + versions['Flipper-PeerTalk'] ||= $flipper_default_versions['Flipper-PeerTalk'] + versions['Flipper-RSocket'] ||= $flipper_default_versions['Flipper-RSocket'] + versions['OpenSSL-Universal'] ||= $flipper_default_versions['OpenSSL-Universal'] + pod 'FlipperKit', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configurations => configurations + # List all transitive dependencies for FlipperKit pods + # to avoid them being linked in Release builds + pod 'Flipper', versions['Flipper'], :configurations => configurations + pod 'Flipper-Boost-iOSX', versions['Flipper-Boost-iOSX'], :configurations => configurations + pod 'Flipper-DoubleConversion', versions['Flipper-DoubleConversion'], :configurations => configurations + pod 'Flipper-Fmt', versions['Flipper-Fmt'], :configurations => configurations + pod 'Flipper-Folly', versions['Flipper-Folly'], :configurations => configurations + pod 'Flipper-Glog', versions['Flipper-Glog'], :configurations => configurations + pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configurations => configurations + pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configurations => configurations + pod 'FlipperKit/Core', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/CppBridge', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FBDefines', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configurations => configurations + pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configurations => configurations + pod 'OpenSSL-Universal', versions['OpenSSL-Universal'], :configurations => configurations +end + +# Applies some changes to some pods of the project: +# * it sets the Swift version for Yoga kit to 4.1 +# * it sets the sonar-kit flag to React-Core pod +# +# @parameter installer: the installer object used to install the pods. +def flipper_post_install(installer) + installer.pods_project.targets.each do |target| + if target.name == 'YogaKit' + target.build_configurations.each do |config| + config.build_settings['SWIFT_VERSION'] = '4.1' + end + end + + # Enable flipper for React-Core Debug configuration + if target.name == 'React-Core' + target.build_configurations.each do |config| + if config.name == 'Debug' + config.build_settings['OTHER_CFLAGS'] = "$(inherited) -DFB_SONARKIT_ENABLED=1" + end + end + end + end +end diff --git a/scripts/cocoapods/submodule/__tests__/dummy_test4-test.rb b/scripts/cocoapods/submodule/__tests__/dummy_test4-test.rb deleted file mode 100644 index 23c122b877d..00000000000 --- a/scripts/cocoapods/submodule/__tests__/dummy_test4-test.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -require "test/unit" - -class DummyTest4 < Test::Unit::TestCase - def test_div - assert_equal(5, 10/2) - end -end diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index d95ff4ab625..afe26ced32f 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -5,6 +5,7 @@ require 'pathname' require_relative './react_native_pods_utils/script_phases.rb' +require_relative './cocoapods/flipper.rb' $CODEGEN_OUTPUT_DIR = 'build/generated/ios' $CODEGEN_COMPONENT_DIR = 'react/renderer/components' @@ -59,9 +60,7 @@ def use_react_native! (options={}) pod 'React-RCTVibration', :path => "#{prefix}/Libraries/Vibration" pod 'React-Core/RCTWebSocket', :path => "#{prefix}/" - unless production - pod 'React-Core/DevSupport', :path => "#{prefix}/" - end + install_flipper_dependencies(production, prefix) pod 'React-bridging', :path => "#{prefix}/ReactCommon/react/bridging" pod 'React-cxxreact', :path => "#{prefix}/ReactCommon/cxxreact" @@ -140,65 +139,13 @@ def get_default_flags() end def use_flipper!(versions = {}, configurations: ['Debug']) - versions['Flipper'] ||= '0.125.0' - versions['Flipper-Boost-iOSX'] ||= '1.76.0.1.11' - versions['Flipper-DoubleConversion'] ||= '3.2.0' - versions['Flipper-Fmt'] ||= '7.1.7' - versions['Flipper-Folly'] ||= '2.6.10' - versions['Flipper-Glog'] ||= '0.5.0.4' - versions['Flipper-PeerTalk'] ||= '0.0.4' - versions['Flipper-RSocket'] ||= '1.4.3' - versions['OpenSSL-Universal'] ||= '1.1.1100' - pod 'FlipperKit', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configurations => configurations - # List all transitive dependencies for FlipperKit pods - # to avoid them being linked in Release builds - pod 'Flipper', versions['Flipper'], :configurations => configurations - pod 'Flipper-Boost-iOSX', versions['Flipper-Boost-iOSX'], :configurations => configurations - pod 'Flipper-DoubleConversion', versions['Flipper-DoubleConversion'], :configurations => configurations - pod 'Flipper-Fmt', versions['Flipper-Fmt'], :configurations => configurations - pod 'Flipper-Folly', versions['Flipper-Folly'], :configurations => configurations - pod 'Flipper-Glog', versions['Flipper-Glog'], :configurations => configurations - pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configurations => configurations - pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configurations => configurations - pod 'FlipperKit/Core', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/CppBridge', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FBDefines', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configurations => configurations - pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configurations => configurations - pod 'OpenSSL-Universal', versions['OpenSSL-Universal'], :configurations => configurations + use_flipper_pods(versions, :configurations => configurations) end def has_pod(installer, name) installer.pods_project.pod_group(name) != nil end -# Post Install processing for Flipper -def flipper_post_install(installer) - installer.pods_project.targets.each do |target| - if target.name == 'YogaKit' - target.build_configurations.each do |config| - config.build_settings['SWIFT_VERSION'] = '4.1' - end - end - - # Enable flipper for React-Core Debug configuration - if target.name == 'React-Core' - target.build_configurations.each do |config| - if config.name == 'Debug' - config.build_settings['OTHER_CFLAGS'] = "$(inherited) -DFB_SONARKIT_ENABLED=1" - end - end - end - end -end - def exclude_architectures(installer) projects = installer.aggregate_targets .map{ |t| t.user_project }