@react-native-firebase/app 26.4.0 → 27.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/README.md +10 -27
- package/RNFBApp.podspec +13 -5
- package/android/build.gradle +3 -0
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.kt +29 -0
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.kt +146 -0
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.kt +156 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.kt +44 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.kt +100 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.kt +250 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.kt +64 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppInitProvider.java → ReactNativeFirebaseAppInitProvider.kt} +3 -4
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.kt +47 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.kt +33 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.kt +185 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.kt +35 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.kt +662 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.kt +103 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.kt +96 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.kt +140 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.kt +109 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.kt +451 -0
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{ContextProvider.java → ContextProvider.kt} +8 -8
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeError.java → NativeError.kt} +8 -8
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeEvent.java → NativeEvent.kt} +6 -6
- package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.kt +219 -0
- package/android/src/test/java/expo/core/ModuleRegistry.java +9 -0
- package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +182 -59
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppComponentsJavaCompatibilityTest.java +70 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppJavaCompatibilityTest.java +60 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackageTest.java +165 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppTest.kt +167 -0
- package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseJavaCompatibilityTest.java +112 -0
- package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseTest.kt +317 -0
- package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.kt +309 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterJavaCompatibilityTest.java +176 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +143 -12
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventTest.kt +61 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONJavaCompatibilityTest.java +85 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.kt +296 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaJavaCompatibilityTest.java +67 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaTest.kt +246 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseModuleTest.kt +254 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesJavaCompatibilityTest.java +87 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesTest.kt +260 -0
- package/android/src/test/java/io/invertase/firebase/common/SharedUtilsJavaCompatibilityTest.java +255 -0
- package/android/src/test/java/io/invertase/firebase/common/SharedUtilsTest.kt +674 -0
- package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.kt +290 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebaseModuleJavaCompatibilityTest.java +178 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesJavaCompatibilityTest.java +99 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesTest.kt +217 -0
- package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleJavaCompatibilityTest.java +176 -0
- package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleKotlinCompatibilityTest.kt +52 -0
- package/android/src/test/java/io/invertase/firebase/interfaces/InterfacesJavaCompatibilityTest.java +144 -0
- package/android/src/test/java/io/invertase/firebase/interfaces/NativeEventTest.kt +56 -0
- package/android/src/test/java/io/invertase/firebase/utils/NativeRNFBTurboUtilsTest.java +517 -21
- package/dist/module/FirebaseApp.js +10 -0
- package/dist/module/FirebaseApp.js.map +1 -1
- package/dist/module/common/deeps.js +3 -0
- package/dist/module/common/deeps.js.map +1 -1
- package/dist/module/internal/FirebaseModule.js.map +1 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
- package/dist/module/internal/SharedEventEmitter.js +3 -1
- package/dist/module/internal/SharedEventEmitter.js.map +1 -1
- package/dist/module/internal/index.js +1 -0
- package/dist/module/internal/index.js.map +1 -1
- package/dist/module/internal/registry/app.js +7 -1
- package/dist/module/internal/registry/app.js.map +1 -1
- package/dist/module/types/app.js.map +1 -1
- package/dist/module/types/internal.js +2 -0
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
- package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
- package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
- package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
- package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
- package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
- package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
- package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/index.d.ts +1 -0
- package/dist/typescript/lib/internal/index.d.ts.map +1 -1
- package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/app.d.ts +10 -3
- package/dist/typescript/lib/types/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/internal.d.ts +12 -0
- package/dist/typescript/lib/types/internal.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/firebase-schema.json +4 -0
- package/firebase_spm.rb +552 -96
- package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
- package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
- package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
- package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
- package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
- package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
- package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
- package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
- package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
- package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
- package/ios/RNFBApp/RNFBAppModule.h +6 -2
- package/ios/RNFBApp/RNFBAppModule.mm +65 -228
- package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
- package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
- package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
- package/ios/RNFBApp/RNFBHandleMap.m +27 -56
- package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
- package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
- package/ios/RNFBApp/RNFBJSON.m +22 -38
- package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
- package/ios/RNFBApp/RNFBMeta.m +24 -26
- package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
- package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
- package/ios/RNFBApp/RNFBPreferences.m +22 -20
- package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
- package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
- package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
- package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
- package/ios/RNFBApp/RNFBSharedUtils.m +109 -198
- package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
- package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
- package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
- package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
- package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
- package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
- package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
- package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
- package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
- package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
- package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
- package/ios/RNFBApp/RNFBVersion.m +1 -1
- package/ios/RNFBApp.xcodeproj/project.pbxproj +100 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
- package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
- package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
- package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
- package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
- package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
- package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
- package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +355 -2
- package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
- package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
- package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
- package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
- package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
- package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
- package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
- package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
- package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
- package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
- package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
- package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
- package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
- package/ios/RNFBFirebase/Package.swift +53 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
- package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
- package/{android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +23 -14
- package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
- package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
- package/ios_config.sh +50 -22
- package/lib/FirebaseApp.ts +10 -0
- package/lib/common/deeps.ts +3 -0
- package/lib/internal/FirebaseModule.ts +6 -3
- package/lib/internal/NativeModules.ts +4 -1
- package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
- package/lib/internal/SharedEventEmitter.ts +5 -1
- package/lib/internal/index.ts +1 -0
- package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
- package/lib/internal/registry/app.ts +7 -1
- package/lib/types/app.ts +10 -3
- package/lib/types/internal.ts +19 -0
- package/lib/version.ts +1 -1
- package/package.json +8 -8
- package/plugin/build/ios/appDelegate.js +2 -2
- package/plugin/build/ios/podfile.js +16 -16
- package/plugin/build/pluginConfig.d.ts +4 -2
- package/plugin/src/ios/appDelegate.ts +2 -2
- package/plugin/src/ios/podfile.ts +20 -23
- package/plugin/src/pluginConfig.ts +4 -2
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.java +0 -150
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -148
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
- package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -224
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java +0 -35
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -192
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -109
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
- package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
- package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.java +0 -275
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.java +0 -108
- package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.java +0 -97
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
package io.invertase.firebase.common
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this library except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import android.content.Context
|
|
20
|
+
import android.util.Log
|
|
21
|
+
import com.facebook.react.bridge.Arguments
|
|
22
|
+
import com.facebook.react.bridge.ReadableArray
|
|
23
|
+
import com.facebook.react.bridge.ReadableMap
|
|
24
|
+
import com.facebook.react.bridge.WritableMap
|
|
25
|
+
import com.google.firebase.FirebaseApp
|
|
26
|
+
import com.google.firebase.FirebaseOptions
|
|
27
|
+
import io.invertase.firebase.app.NativeRNFBTurboApp
|
|
28
|
+
import org.json.JSONObject
|
|
29
|
+
import org.junit.After
|
|
30
|
+
import org.junit.Assert.assertEquals
|
|
31
|
+
import org.junit.Assert.assertFalse
|
|
32
|
+
import org.junit.Assert.assertNull
|
|
33
|
+
import org.junit.Assert.assertSame
|
|
34
|
+
import org.junit.Assert.assertTrue
|
|
35
|
+
import org.junit.Test
|
|
36
|
+
import org.mockito.ArgumentCaptor
|
|
37
|
+
import org.mockito.Mockito.mock
|
|
38
|
+
import org.mockito.Mockito.mockStatic
|
|
39
|
+
import org.mockito.Mockito.never
|
|
40
|
+
import org.mockito.Mockito.verify
|
|
41
|
+
import org.mockito.Mockito.`when`
|
|
42
|
+
import org.robolectric.RobolectricTestRunner
|
|
43
|
+
import java.util.ArrayList
|
|
44
|
+
import java.util.HashMap
|
|
45
|
+
|
|
46
|
+
@org.junit.runner.RunWith(RobolectricTestRunner::class)
|
|
47
|
+
class RCTConvertFirebaseTest {
|
|
48
|
+
private val touchedAuthDomains = mutableMapOf<String, String?>()
|
|
49
|
+
|
|
50
|
+
@After
|
|
51
|
+
fun tearDown() {
|
|
52
|
+
touchedAuthDomains.forEach { (name, original) ->
|
|
53
|
+
if (original == null) {
|
|
54
|
+
NativeRNFBTurboApp.authDomains.remove(name)
|
|
55
|
+
} else {
|
|
56
|
+
NativeRNFBTurboApp.authDomains[name] = original
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Test
|
|
62
|
+
fun firebaseAppToMap_returnsExactMutableStructureWithOptionalAuthDomain() {
|
|
63
|
+
val firebaseApp = mock(FirebaseApp::class.java)
|
|
64
|
+
val options = mock(FirebaseOptions::class.java)
|
|
65
|
+
`when`(firebaseApp.name).thenReturn("secondary")
|
|
66
|
+
`when`(firebaseApp.options).thenReturn(options)
|
|
67
|
+
`when`(firebaseApp.isDataCollectionDefaultEnabled).thenReturn(false)
|
|
68
|
+
`when`(options.apiKey).thenReturn("api-key")
|
|
69
|
+
`when`(options.applicationId).thenReturn("app-id")
|
|
70
|
+
`when`(options.projectId).thenReturn("project-id")
|
|
71
|
+
`when`(options.databaseUrl).thenReturn("database-url")
|
|
72
|
+
`when`(options.gaTrackingId).thenReturn("measurement-id")
|
|
73
|
+
`when`(options.gcmSenderId).thenReturn("sender-id")
|
|
74
|
+
`when`(options.storageBucket).thenReturn("storage-bucket")
|
|
75
|
+
rememberAuthDomain("secondary")
|
|
76
|
+
NativeRNFBTurboApp.authDomains["secondary"] = "auth.example"
|
|
77
|
+
|
|
78
|
+
val result = RCTConvertFirebase.firebaseAppToMap(firebaseApp)
|
|
79
|
+
|
|
80
|
+
assertTrue(result is HashMap)
|
|
81
|
+
val appConfig = result["appConfig"] as Map<*, *>
|
|
82
|
+
val convertedOptions = result["options"] as Map<*, *>
|
|
83
|
+
assertTrue(appConfig is HashMap)
|
|
84
|
+
assertTrue(convertedOptions is HashMap)
|
|
85
|
+
assertEquals(
|
|
86
|
+
mapOf("name" to "secondary", "automaticDataCollectionEnabled" to false),
|
|
87
|
+
appConfig,
|
|
88
|
+
)
|
|
89
|
+
assertEquals(
|
|
90
|
+
mapOf(
|
|
91
|
+
"apiKey" to "api-key",
|
|
92
|
+
"appId" to "app-id",
|
|
93
|
+
"projectId" to "project-id",
|
|
94
|
+
"databaseURL" to "database-url",
|
|
95
|
+
"measurementId" to "measurement-id",
|
|
96
|
+
"messagingSenderId" to "sender-id",
|
|
97
|
+
"storageBucket" to "storage-bucket",
|
|
98
|
+
"authDomain" to "auth.example",
|
|
99
|
+
),
|
|
100
|
+
convertedOptions,
|
|
101
|
+
)
|
|
102
|
+
(result as MutableMap)["later"] = true
|
|
103
|
+
(appConfig as MutableMap<String, Any>)["later"] = true
|
|
104
|
+
(convertedOptions as MutableMap<String, Any>)["later"] = true
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Test
|
|
108
|
+
fun firebaseAppToMap_omitsMissingAuthDomainAndWritableConversionUsesSameMap() {
|
|
109
|
+
val firebaseApp = mock(FirebaseApp::class.java)
|
|
110
|
+
val options = mock(FirebaseOptions::class.java)
|
|
111
|
+
`when`(firebaseApp.name).thenReturn("[DEFAULT]")
|
|
112
|
+
`when`(firebaseApp.options).thenReturn(options)
|
|
113
|
+
rememberAuthDomain("[DEFAULT]")
|
|
114
|
+
NativeRNFBTurboApp.authDomains.remove("[DEFAULT]")
|
|
115
|
+
|
|
116
|
+
val converted = RCTConvertFirebase.firebaseAppToMap(firebaseApp)
|
|
117
|
+
|
|
118
|
+
assertFalse((converted["options"] as Map<*, *>).containsKey("authDomain"))
|
|
119
|
+
mockStatic(Arguments::class.java).use { arguments ->
|
|
120
|
+
assertNull(RCTConvertFirebase.firebaseAppToWritableMap(firebaseApp))
|
|
121
|
+
arguments.verify {
|
|
122
|
+
Arguments.makeNativeMap(org.mockito.ArgumentMatchers.anyMap<String, Any?>())
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@Test
|
|
128
|
+
fun readableMapToFirebaseApp_buildsDefaultAppAndAppliesOptionalConfiguration() {
|
|
129
|
+
val options = completeOptions("measurement-id")
|
|
130
|
+
val appConfig = mock(ReadableMap::class.java)
|
|
131
|
+
val context = mock(Context::class.java)
|
|
132
|
+
val firebaseApp = mock(FirebaseApp::class.java)
|
|
133
|
+
`when`(appConfig.getString("name")).thenReturn("[DEFAULT]")
|
|
134
|
+
`when`(appConfig.hasKey("automaticDataCollectionEnabled")).thenReturn(true)
|
|
135
|
+
`when`(appConfig.getBoolean("automaticDataCollectionEnabled")).thenReturn(false)
|
|
136
|
+
`when`(appConfig.hasKey("automaticResourceManagement")).thenReturn(true)
|
|
137
|
+
`when`(appConfig.getBoolean("automaticResourceManagement")).thenReturn(true)
|
|
138
|
+
|
|
139
|
+
mockStatic(FirebaseApp::class.java).use { firebaseApps ->
|
|
140
|
+
firebaseApps
|
|
141
|
+
.`when`<FirebaseApp> {
|
|
142
|
+
FirebaseApp.initializeApp(
|
|
143
|
+
org.mockito.ArgumentMatchers.eq(context),
|
|
144
|
+
org.mockito.ArgumentMatchers.any(FirebaseOptions::class.java),
|
|
145
|
+
)
|
|
146
|
+
}.thenReturn(firebaseApp)
|
|
147
|
+
|
|
148
|
+
assertSame(firebaseApp, RCTConvertFirebase.readableMapToFirebaseApp(options, appConfig, context))
|
|
149
|
+
|
|
150
|
+
val captor = ArgumentCaptor.forClass(FirebaseOptions::class.java)
|
|
151
|
+
firebaseApps.verify { FirebaseApp.initializeApp(org.mockito.ArgumentMatchers.eq(context), captor.capture()) }
|
|
152
|
+
assertOptions(captor.value, "measurement-id")
|
|
153
|
+
verify(firebaseApp).setDataCollectionDefaultEnabled(false)
|
|
154
|
+
verify(firebaseApp).setAutomaticResourceManagementEnabled(true)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@Test
|
|
159
|
+
fun readableMapToFirebaseApp_buildsNamedAppWithoutAbsentOptionalConfiguration() {
|
|
160
|
+
val options = completeOptions(null)
|
|
161
|
+
val appConfig = mock(ReadableMap::class.java)
|
|
162
|
+
val context = mock(Context::class.java)
|
|
163
|
+
val firebaseApp = mock(FirebaseApp::class.java)
|
|
164
|
+
`when`(appConfig.getString("name")).thenReturn("secondary")
|
|
165
|
+
|
|
166
|
+
mockStatic(FirebaseApp::class.java).use { firebaseApps ->
|
|
167
|
+
firebaseApps
|
|
168
|
+
.`when`<FirebaseApp> {
|
|
169
|
+
FirebaseApp.initializeApp(
|
|
170
|
+
org.mockito.ArgumentMatchers.eq(context),
|
|
171
|
+
org.mockito.ArgumentMatchers.any(FirebaseOptions::class.java),
|
|
172
|
+
org.mockito.ArgumentMatchers.eq("secondary"),
|
|
173
|
+
)
|
|
174
|
+
}.thenReturn(firebaseApp)
|
|
175
|
+
|
|
176
|
+
assertSame(firebaseApp, RCTConvertFirebase.readableMapToFirebaseApp(options, appConfig, context))
|
|
177
|
+
|
|
178
|
+
val captor = ArgumentCaptor.forClass(FirebaseOptions::class.java)
|
|
179
|
+
firebaseApps.verify {
|
|
180
|
+
FirebaseApp.initializeApp(
|
|
181
|
+
org.mockito.ArgumentMatchers.eq(context),
|
|
182
|
+
captor.capture(),
|
|
183
|
+
org.mockito.ArgumentMatchers.eq("secondary"),
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
assertOptions(captor.value, null)
|
|
187
|
+
assertFalse(
|
|
188
|
+
org.mockito.Mockito
|
|
189
|
+
.mockingDetails(firebaseApp)
|
|
190
|
+
.invocations
|
|
191
|
+
.any { it.method.name == "setDataCollectionDefaultEnabled" },
|
|
192
|
+
)
|
|
193
|
+
verify(firebaseApp, never())
|
|
194
|
+
.setAutomaticResourceManagementEnabled(org.mockito.ArgumentMatchers.anyBoolean())
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@Test
|
|
199
|
+
fun mapPutValue_writesEveryScalarAndJsonNullAndReturnsTargetIdentity() {
|
|
200
|
+
val map = mock(WritableMap::class.java)
|
|
201
|
+
|
|
202
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("null", null, map))
|
|
203
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("boolean", true, map))
|
|
204
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("long", 4_294_967_296L, map))
|
|
205
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("float", 1.25F, map))
|
|
206
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("double", 2.5, map))
|
|
207
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("integer", 42, map))
|
|
208
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("string", "value", map))
|
|
209
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("jsonNull", JSONObject.NULL, map))
|
|
210
|
+
|
|
211
|
+
verify(map).putNull("null")
|
|
212
|
+
verify(map).putBoolean("boolean", true)
|
|
213
|
+
verify(map).putDouble("long", 4_294_967_296.0)
|
|
214
|
+
verify(map).putDouble("float", 1.25)
|
|
215
|
+
verify(map).putDouble("double", 2.5)
|
|
216
|
+
verify(map).putInt("integer", 42)
|
|
217
|
+
verify(map).putString("string", "value")
|
|
218
|
+
verify(map).putString("jsonNull", "null")
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@Test
|
|
222
|
+
fun mapPutValue_writesListsAndRecursiveMapsWithoutChangingInputs() {
|
|
223
|
+
val map = mock(WritableMap::class.java)
|
|
224
|
+
val childMap = mock(WritableMap::class.java)
|
|
225
|
+
val list = arrayListOf<Any>("item")
|
|
226
|
+
val nested = linkedMapOf<String, Any?>("boolean" to true, "null" to null)
|
|
227
|
+
|
|
228
|
+
mockStatic(Arguments::class.java).use { arguments ->
|
|
229
|
+
arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(childMap)
|
|
230
|
+
|
|
231
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("list", list, map))
|
|
232
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("map", nested, map))
|
|
233
|
+
arguments.verify { Arguments.makeNativeArray(list) }
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
verify(map).putArray("list", null)
|
|
237
|
+
verify(childMap).putBoolean("boolean", true)
|
|
238
|
+
verify(childMap).putNull("null")
|
|
239
|
+
verify(map).putMap("map", childMap)
|
|
240
|
+
assertEquals(arrayListOf<Any>("item"), list)
|
|
241
|
+
assertEquals(linkedMapOf<String, Any?>("boolean" to true, "null" to null), nested)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@Test
|
|
245
|
+
fun mapPutValue_logsUnknownTypeAndWritesNull() {
|
|
246
|
+
val map = mock(WritableMap::class.java)
|
|
247
|
+
val unknown = Any()
|
|
248
|
+
|
|
249
|
+
mockStatic(Log::class.java).use { log ->
|
|
250
|
+
assertSame(map, RCTConvertFirebase.mapPutValue("unknown", unknown, map))
|
|
251
|
+
log.verify {
|
|
252
|
+
Log.d(
|
|
253
|
+
"RCTConvertFirebase",
|
|
254
|
+
"utils:mapPutValue:unknownType:${unknown.javaClass.name}",
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
verify(map).putNull("unknown")
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@Test
|
|
262
|
+
fun readableDelegates_preserveReturnedMutableCollectionIdentity() {
|
|
263
|
+
val readableMap = mock(ReadableMap::class.java)
|
|
264
|
+
val writableMap = mock(WritableMap::class.java)
|
|
265
|
+
val hashMap = HashMap<String, Any?>()
|
|
266
|
+
val readableArray = mock(ReadableArray::class.java)
|
|
267
|
+
val arrayList = ArrayList<Any?>()
|
|
268
|
+
`when`(readableMap.toHashMap()).thenReturn(hashMap)
|
|
269
|
+
`when`(readableArray.toArrayList()).thenReturn(arrayList)
|
|
270
|
+
|
|
271
|
+
mockStatic(Arguments::class.java).use { arguments ->
|
|
272
|
+
arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(writableMap)
|
|
273
|
+
assertSame(writableMap, RCTConvertFirebase.readableMapToWritableMap(readableMap))
|
|
274
|
+
}
|
|
275
|
+
verify(writableMap).merge(readableMap)
|
|
276
|
+
assertSame(hashMap, RCTConvertFirebase.toHashMap(readableMap))
|
|
277
|
+
assertSame(arrayList, RCTConvertFirebase.toArrayList(readableArray))
|
|
278
|
+
hashMap["later"] = true
|
|
279
|
+
arrayList.add("later")
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private fun completeOptions(measurementId: String?): ReadableMap {
|
|
283
|
+
val options = mock(ReadableMap::class.java)
|
|
284
|
+
val values =
|
|
285
|
+
mapOf(
|
|
286
|
+
"apiKey" to "api-key",
|
|
287
|
+
"appId" to "app-id",
|
|
288
|
+
"projectId" to "project-id",
|
|
289
|
+
"databaseURL" to "database-url",
|
|
290
|
+
"storageBucket" to "storage-bucket",
|
|
291
|
+
"messagingSenderId" to "sender-id",
|
|
292
|
+
)
|
|
293
|
+
values.forEach { (key, value) -> `when`(options.getString(key)).thenReturn(value) }
|
|
294
|
+
`when`(options.hasKey("measurementId")).thenReturn(measurementId != null)
|
|
295
|
+
if (measurementId != null) {
|
|
296
|
+
`when`(options.getString("measurementId")).thenReturn(measurementId)
|
|
297
|
+
}
|
|
298
|
+
return options
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private fun assertOptions(
|
|
302
|
+
options: FirebaseOptions,
|
|
303
|
+
measurementId: String?,
|
|
304
|
+
) {
|
|
305
|
+
assertEquals("api-key", options.apiKey)
|
|
306
|
+
assertEquals("app-id", options.applicationId)
|
|
307
|
+
assertEquals("project-id", options.projectId)
|
|
308
|
+
assertEquals("database-url", options.databaseUrl)
|
|
309
|
+
assertEquals(measurementId, options.gaTrackingId)
|
|
310
|
+
assertEquals("storage-bucket", options.storageBucket)
|
|
311
|
+
assertEquals("sender-id", options.gcmSenderId)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private fun rememberAuthDomain(name: String) {
|
|
315
|
+
touchedAuthDomains.putIfAbsent(name, NativeRNFBTurboApp.authDomains[name])
|
|
316
|
+
}
|
|
317
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
package io.invertase.firebase.common
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this library except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import org.junit.Assert.assertEquals
|
|
21
|
+
import org.junit.Assert.assertFalse
|
|
22
|
+
import org.junit.Assert.assertNull
|
|
23
|
+
import org.junit.Assert.assertSame
|
|
24
|
+
import org.junit.Assert.assertTrue
|
|
25
|
+
import org.junit.Assert.fail
|
|
26
|
+
import org.junit.Before
|
|
27
|
+
import org.junit.Test
|
|
28
|
+
import java.util.concurrent.CountDownLatch
|
|
29
|
+
import java.util.concurrent.TimeUnit
|
|
30
|
+
import java.util.concurrent.atomic.AtomicReference
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* JVM coverage for [RNFBHandleMap]. Tests must not invoke methods on stored values — the map only
|
|
34
|
+
* moves pointers.
|
|
35
|
+
*/
|
|
36
|
+
class RNFBHandleMapTest {
|
|
37
|
+
private lateinit var map: RNFBHandleMap<Int, Any>
|
|
38
|
+
|
|
39
|
+
@Before
|
|
40
|
+
fun setUp() {
|
|
41
|
+
map = RNFBHandleMap()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Test
|
|
45
|
+
fun putGetTake_happyPath() {
|
|
46
|
+
val handle = Any()
|
|
47
|
+
map.put(1, handle)
|
|
48
|
+
|
|
49
|
+
assertSame(handle, map.get(1))
|
|
50
|
+
assertSame(handle, map.take(1))
|
|
51
|
+
assertNull(map.get(1))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@Test
|
|
55
|
+
fun take_missingKey_returnsNull() {
|
|
56
|
+
assertNull(map.take(99))
|
|
57
|
+
assertNull(map.get(99))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Test
|
|
61
|
+
fun takeAll_returnsSnapshotAndLeavesMapEmpty() {
|
|
62
|
+
val a = Any()
|
|
63
|
+
val b = Any()
|
|
64
|
+
map.put(1, a)
|
|
65
|
+
map.put(2, b)
|
|
66
|
+
|
|
67
|
+
val snapshot = map.takeAll()
|
|
68
|
+
|
|
69
|
+
assertEquals(2, snapshot.size)
|
|
70
|
+
assertTrue(snapshot.contains(a))
|
|
71
|
+
assertTrue(snapshot.contains(b))
|
|
72
|
+
assertNull(map.get(1))
|
|
73
|
+
assertNull(map.get(2))
|
|
74
|
+
assertTrue(map.takeAll().isEmpty())
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Test
|
|
78
|
+
fun put_occupiedId_throwsCollision() {
|
|
79
|
+
val first = Any()
|
|
80
|
+
map.put(1, first)
|
|
81
|
+
try {
|
|
82
|
+
map.put(1, Any())
|
|
83
|
+
fail("expected RNFBHandleCollisionException")
|
|
84
|
+
} catch (exception: RNFBHandleCollisionException) {
|
|
85
|
+
assertTrue(exception.message!!.contains("1"))
|
|
86
|
+
assertSame(first, map.get(1))
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@Test
|
|
91
|
+
fun put_nullValue_stillTreatsIdAsOccupied() {
|
|
92
|
+
val nullableMap = RNFBHandleMap<Int, Any?>()
|
|
93
|
+
nullableMap.put(1, null)
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
nullableMap.put(1, Any())
|
|
97
|
+
fail("expected RNFBHandleCollisionException")
|
|
98
|
+
} catch (exception: RNFBHandleCollisionException) {
|
|
99
|
+
assertEquals("Handle id already registered: 1", exception.message)
|
|
100
|
+
assertNull(nullableMap.get(1))
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@Test
|
|
105
|
+
fun putIfAbsent_whenFree_storesAndReturnsTrue() {
|
|
106
|
+
val handle = Any()
|
|
107
|
+
assertTrue(map.putIfAbsent(1, handle))
|
|
108
|
+
assertSame(handle, map.get(1))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@Test
|
|
112
|
+
fun putIfAbsent_whenOccupied_keepsExistingAndReturnsFalse() {
|
|
113
|
+
val first = Any()
|
|
114
|
+
val second = Any()
|
|
115
|
+
map.put(1, first)
|
|
116
|
+
assertFalse(map.putIfAbsent(1, second))
|
|
117
|
+
assertSame(first, map.get(1))
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@Test
|
|
121
|
+
fun putIfAbsent_nullableExistingValue_isOccupied() {
|
|
122
|
+
val nullableMap = RNFBHandleMap<Int, Any?>()
|
|
123
|
+
nullableMap.put(1, null)
|
|
124
|
+
|
|
125
|
+
assertFalse(nullableMap.putIfAbsent(1, Any()))
|
|
126
|
+
assertNull(nullableMap.get(1))
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@Test
|
|
130
|
+
fun putIfAbsentOrSame_whenAbsent_storesAndReturnsTrue() {
|
|
131
|
+
val handle = Any()
|
|
132
|
+
assertTrue(map.putIfAbsentOrSame(1, handle))
|
|
133
|
+
assertSame(handle, map.get(1))
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@Test
|
|
137
|
+
fun putIfAbsentOrSame_whenSameInstance_returnsTrue() {
|
|
138
|
+
val handle = Any()
|
|
139
|
+
map.put(1, handle)
|
|
140
|
+
assertTrue(map.putIfAbsentOrSame(1, handle))
|
|
141
|
+
assertSame(handle, map.get(1))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@Test
|
|
145
|
+
fun putIfAbsentOrSame_whenDifferent_returnsFalse() {
|
|
146
|
+
val first = Any()
|
|
147
|
+
val second = Any()
|
|
148
|
+
map.put(1, first)
|
|
149
|
+
assertFalse(map.putIfAbsentOrSame(1, second))
|
|
150
|
+
assertSame(first, map.get(1))
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@Test
|
|
154
|
+
fun putIfAbsentOrSame_sameNullInstance_returnsTrue() {
|
|
155
|
+
val nullableMap = RNFBHandleMap<Int, Any?>()
|
|
156
|
+
nullableMap.put(1, null)
|
|
157
|
+
|
|
158
|
+
assertTrue(nullableMap.putIfAbsentOrSame(1, null))
|
|
159
|
+
assertNull(nullableMap.get(1))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@Test
|
|
163
|
+
fun putIfAbsentOrSame_nullExistingAndDifferentHandle_returnsFalse() {
|
|
164
|
+
val nullableMap = RNFBHandleMap<Int, Any?>()
|
|
165
|
+
nullableMap.put(1, null)
|
|
166
|
+
|
|
167
|
+
assertFalse(nullableMap.putIfAbsentOrSame(1, Any()))
|
|
168
|
+
assertNull(nullableMap.get(1))
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@Test
|
|
172
|
+
fun putReplacing_whenFree_storesAndReturnsNull() {
|
|
173
|
+
val handle = Any()
|
|
174
|
+
assertNull(map.putReplacing(1, handle))
|
|
175
|
+
assertSame(handle, map.get(1))
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@Test
|
|
179
|
+
fun putReplacing_whenOccupied_replacesLastWins() {
|
|
180
|
+
val first = Any()
|
|
181
|
+
val second = Any()
|
|
182
|
+
map.put(1, first)
|
|
183
|
+
assertSame(first, map.putReplacing(1, second))
|
|
184
|
+
assertSame(second, map.get(1))
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@Test
|
|
188
|
+
fun put_afterTake_allowsReuse() {
|
|
189
|
+
val first = Any()
|
|
190
|
+
val second = Any()
|
|
191
|
+
map.put(1, first)
|
|
192
|
+
assertSame(first, map.take(1))
|
|
193
|
+
map.put(1, second)
|
|
194
|
+
assertSame(second, map.get(1))
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@Test
|
|
198
|
+
fun takeIf_whenPredicateTrue_removesAndReturns() {
|
|
199
|
+
val handle = Any()
|
|
200
|
+
map.put(1, handle)
|
|
201
|
+
assertSame(handle, map.takeIf(1) { it === handle })
|
|
202
|
+
assertNull(map.get(1))
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@Test
|
|
206
|
+
fun takeIf_whenPredicateFalse_leavesMapping() {
|
|
207
|
+
val handle = Any()
|
|
208
|
+
map.put(1, handle)
|
|
209
|
+
assertNull(map.takeIf(1) { false })
|
|
210
|
+
assertSame(handle, map.get(1))
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@Test
|
|
214
|
+
fun takeIf_whenMissing_returnsNull() {
|
|
215
|
+
assertNull(map.takeIf(99) { true })
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@Test
|
|
219
|
+
fun take_sameIdFromTwoThreads_onlyOneReturnsNonNull() {
|
|
220
|
+
val handle = Any()
|
|
221
|
+
map.put(1, handle)
|
|
222
|
+
|
|
223
|
+
val start = CountDownLatch(1)
|
|
224
|
+
val done = CountDownLatch(2)
|
|
225
|
+
val first = AtomicReference<Any>()
|
|
226
|
+
val second = AtomicReference<Any>()
|
|
227
|
+
|
|
228
|
+
val firstThread =
|
|
229
|
+
Thread {
|
|
230
|
+
try {
|
|
231
|
+
start.await()
|
|
232
|
+
first.set(map.take(1))
|
|
233
|
+
} catch (_: InterruptedException) {
|
|
234
|
+
Thread.currentThread().interrupt()
|
|
235
|
+
} finally {
|
|
236
|
+
done.countDown()
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
val secondThread =
|
|
240
|
+
Thread {
|
|
241
|
+
try {
|
|
242
|
+
start.await()
|
|
243
|
+
second.set(map.take(1))
|
|
244
|
+
} catch (_: InterruptedException) {
|
|
245
|
+
Thread.currentThread().interrupt()
|
|
246
|
+
} finally {
|
|
247
|
+
done.countDown()
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
firstThread.start()
|
|
252
|
+
secondThread.start()
|
|
253
|
+
start.countDown()
|
|
254
|
+
assertTrue(done.await(5, TimeUnit.SECONDS))
|
|
255
|
+
|
|
256
|
+
val a = first.get()
|
|
257
|
+
val b = second.get()
|
|
258
|
+
val onlyFirst = a === handle && b == null
|
|
259
|
+
val onlySecond = b === handle && a == null
|
|
260
|
+
assertTrue(onlyFirst || onlySecond)
|
|
261
|
+
assertNull(map.get(1))
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@Test
|
|
265
|
+
fun putReplacing_sameIdFromTwoThreads_lastWins() {
|
|
266
|
+
val first = Any()
|
|
267
|
+
val second = Any()
|
|
268
|
+
val third = Any()
|
|
269
|
+
map.put(1, first)
|
|
270
|
+
|
|
271
|
+
val start = CountDownLatch(1)
|
|
272
|
+
val done = CountDownLatch(2)
|
|
273
|
+
val previousA = AtomicReference<Any>()
|
|
274
|
+
val previousB = AtomicReference<Any>()
|
|
275
|
+
|
|
276
|
+
val firstThread =
|
|
277
|
+
Thread {
|
|
278
|
+
try {
|
|
279
|
+
start.await()
|
|
280
|
+
previousA.set(map.putReplacing(1, second))
|
|
281
|
+
} catch (_: InterruptedException) {
|
|
282
|
+
Thread.currentThread().interrupt()
|
|
283
|
+
} finally {
|
|
284
|
+
done.countDown()
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
val secondThread =
|
|
288
|
+
Thread {
|
|
289
|
+
try {
|
|
290
|
+
start.await()
|
|
291
|
+
previousB.set(map.putReplacing(1, third))
|
|
292
|
+
} catch (_: InterruptedException) {
|
|
293
|
+
Thread.currentThread().interrupt()
|
|
294
|
+
} finally {
|
|
295
|
+
done.countDown()
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
firstThread.start()
|
|
300
|
+
secondThread.start()
|
|
301
|
+
start.countDown()
|
|
302
|
+
assertTrue(done.await(5, TimeUnit.SECONDS))
|
|
303
|
+
|
|
304
|
+
val winner = map.get(1)
|
|
305
|
+
assertTrue(winner === second || winner === third)
|
|
306
|
+
val returnedFirst = if (previousA.get() === first) previousA.get() else previousB.get()
|
|
307
|
+
assertSame(first, returnedFirst)
|
|
308
|
+
}
|
|
309
|
+
}
|