/* * 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. */ #include <gtest/gtest.h> #include <react/featureflags/ReactNativeFeatureFlags.h> #include <react/featureflags/ReactNativeFeatureFlagsDefaults.h> #include <stdexcept> namespace facebook::react { uint overrideAccessCount = 0; class ReactNativeFeatureFlagsTestOverrides : public ReactNativeFeatureFlagsDefaults { public: bool commonTestFlag() override { overrideAccessCount++; return true; } }; class ReactNativeFeatureFlagsTest : public testing::Test { protected: void SetUp() override { overrideAccessCount = 0; } void TearDown() override { ReactNativeFeatureFlags::dangerouslyReset(); } }; TEST_F(ReactNativeFeatureFlagsTest, providesDefaults) { EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false); } TEST_F(ReactNativeFeatureFlagsTest, providesOverriddenValues) { ReactNativeFeatureFlags::override( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); } TEST_F(ReactNativeFeatureFlagsTest, preventsOverridingAfterAccess) { EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false); try { ReactNativeFeatureFlags::override( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); FAIL() << "Expected ReactNativeFeatureFlags::override() to throw an exception"; } catch (const std::runtime_error& e) { EXPECT_STREQ( "Feature flags were accessed before being overridden: commonTestFlag", e.what()); } // Overrides shouldn't be applied after they've been accessed EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false); } TEST_F(ReactNativeFeatureFlagsTest, preventsOverridingAfterOverride) { ReactNativeFeatureFlags::override( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); try { ReactNativeFeatureFlags::override( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); FAIL() << "Expected ReactNativeFeatureFlags::override() to throw an exception"; } catch (const std::runtime_error& e) { EXPECT_STREQ("Feature flags cannot be overridden more than once", e.what()); } // Original overrides should still work EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); } TEST_F(ReactNativeFeatureFlagsTest, cachesValuesFromOverride) { ReactNativeFeatureFlags::override( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); EXPECT_EQ(overrideAccessCount, 0); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); EXPECT_EQ(overrideAccessCount, 1); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); EXPECT_EQ(overrideAccessCount, 1); } TEST_F( ReactNativeFeatureFlagsTest, providesDefaulValuesAgainWhenResettingAfterAnOverride) { ReactNativeFeatureFlags::override( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); ReactNativeFeatureFlags::dangerouslyReset(); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false); } TEST_F(ReactNativeFeatureFlagsTest, allowsOverridingAgainAfterReset) { ReactNativeFeatureFlags::override( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); ReactNativeFeatureFlags::dangerouslyReset(); ReactNativeFeatureFlags::override( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); } TEST_F( ReactNativeFeatureFlagsTest, allowsDangerouslyForcingOverridesWhenValuesHaveNotBeenAccessed) { auto accessedFlags = ReactNativeFeatureFlags::dangerouslyForceOverride( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); EXPECT_EQ(accessedFlags.has_value(), false); } TEST_F( ReactNativeFeatureFlagsTest, allowsDangerouslyForcingOverridesWhenValuesHaveBeenAccessed) { EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false); auto accessedFlags = ReactNativeFeatureFlags::dangerouslyForceOverride( std::make_unique<ReactNativeFeatureFlagsTestOverrides>()); EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true); EXPECT_EQ(accessedFlags.has_value(), true); EXPECT_EQ(accessedFlags.value(), "commonTestFlag"); } } // namespace facebook::react