Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions FirebaseFunctions/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 10.10.0
- [fixed] Fixed potential memory leak of Functions instances. (#11248)

# 10.0.0
- [fixed] Remove unnecessary and unused `encoder` and `decoder` parameters from
`public func call(_ data: Request) async throws -> Response` API. (#9891)
Expand Down
3 changes: 2 additions & 1 deletion FirebaseFunctions/Sources/Internal/FunctionsComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ protocol FunctionsProvider {
// MARK: - Private Variables

/// The app associated with all functions instances in this container.
private let app: FirebaseApp
/// This is `unowned` instead of `weak` so it can be used without unwrapping in `functions()`
private unowned let app: FirebaseApp

/// A map of active instances, grouped by app. Keys are FirebaseApp names and values are arrays
/// containing all instances of Functions associated with the given app.
Expand Down
18 changes: 18 additions & 0 deletions FirebaseFunctions/Tests/Unit/FunctionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,22 @@ class FunctionsTests: XCTestCase {
}
waitForExpectations(timeout: 1.5)
}

/// Test that Functions instances get deallocated.
func testFunctionsLifecycle() throws {
weak var weakApp: FirebaseApp?
weak var weakFunctions: Functions?
try autoreleasepool {
let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
gcmSenderID: "00000000000000000-00000000000-000000000")
options.projectID = "myProjectID"
let app1 = FirebaseApp(instanceWithName: "transitory app", options: options)
weakApp = try XCTUnwrap(app1)
let functions = Functions(app: app1, region: "transitory-region", customDomain: nil)
weakFunctions = functions
XCTAssertNotNil(weakFunctions)
}
XCTAssertNil(weakApp)
XCTAssertNil(weakFunctions)
}
}
10 changes: 5 additions & 5 deletions FirebaseFunctions/Tests/Unit/SerializerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class SerializerTests: XCTestCase {
1 as Int32,
"two",
[3 as Int32, ["@type": "type.googleapis.com/google.protobuf.Int64Value",
"value": "9876543210"]],
"value": "9876543210"]] as [Any],
] as NSArray
XCTAssertEqual(input, try serializer.encode(input) as? NSArray)
}
Expand All @@ -209,23 +209,23 @@ class SerializerTests: XCTestCase {
1 as Int64,
"two",
[3 as Int32, ["@type": "type.googleapis.com/google.protobuf.Int64Value",
"value": "9876543210"]],
"value": "9876543210"]] as [Any],
] as NSArray
let expected = [1 as Int64, "two", [3 as Int32, 9_876_543_210 as Int64]] as NSArray
let expected = [1 as Int64, "two", [3 as Int32, 9_876_543_210 as Int64] as [Any]] as NSArray
XCTAssertEqual(expected, try serializer.decode(input) as? NSArray)
}

func testEncodeMap() {
let input = [
"foo": 1 as Int32,
"bar": "hello",
"baz": [3 as Int32, 9_876_543_210 as Int64],
"baz": [3 as Int32, 9_876_543_210 as Int64] as [Any],
] as NSDictionary
let expected = [
"foo": 1,
"bar": "hello",
"baz": [3, ["@type": "type.googleapis.com/google.protobuf.Int64Value",
"value": "9876543210"]],
"value": "9876543210"]] as [Any],
] as NSDictionary
let serializer = FUNSerializer()
XCTAssertEqual(expected, try serializer.encode(input) as? NSDictionary)
Expand Down
3 changes: 3 additions & 0 deletions FirebaseStorage/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 10.10.0
- [fixed] Fixed potential memory leak of Storage instances. (#11248)

# 10.7.0
- [added] Provide server errors via the `NSUnderlyingErrorKey`.

Expand Down
3 changes: 2 additions & 1 deletion FirebaseStorage/Sources/StorageComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ protocol StorageProvider {
// MARK: - Private Variables

/// The app associated with all Storage instances in this container.
private let app: FirebaseApp
/// This is `unowned` instead of `weak` so it can be used without unwrapping in `storage(...)`
private unowned let app: FirebaseApp

/// A map of active instances, grouped by app. Keys are FirebaseApp names and values are arrays
/// containing all instances of Storage associated with the given app.
Expand Down
27 changes: 22 additions & 5 deletions FirebaseStorage/Tests/Unit/StorageComponentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class StorageComponentTests: StorageTestHelpers {

/// Tests that a Storage instance can be created properly by the StorageComponent.
func testStorageInstanceCreation() throws {
let component = StorageComponent(app: StorageComponentTests.app)
let app = try XCTUnwrap(StorageComponentTests.app)
let component = StorageComponent(app: app)
let storage = component.storage(for: "someBucket")
XCTAssertNotNil(storage)
}
Expand All @@ -61,11 +62,9 @@ class StorageComponentTests: StorageTestHelpers {

/// Tests that instances of Storage created are different.
func testMultipleStorageInstancesCreated() throws {
let app = try XCTUnwrap(StorageComponentTests.app)
let registrants = NSMutableSet(array: [StorageComponent.self])
let container = FirebaseComponentContainer(
app: StorageComponentTests.app,
registrants: registrants
)
let container = FirebaseComponentContainer(app: app, registrants: registrants)

let provider = ComponentType<StorageProvider>.instance(for: StorageProvider.self,
in: container)
Expand All @@ -83,4 +82,22 @@ class StorageComponentTests: StorageTestHelpers {

XCTAssert(storage1 !== storage3)
}

/// Test that Storage instances get deallocated.
func testStorageLifecycle() throws {
weak var weakApp: FirebaseApp?
weak var weakStorage: Storage?
try autoreleasepool {
let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
gcmSenderID: "00000000000000000-00000000000-000000000")
options.projectID = "myProjectID"
let app1 = FirebaseApp(instanceWithName: "transitory app", options: options)
weakApp = try XCTUnwrap(app1)
let storage = Storage(app: app1, bucket: "transitory bucket")
weakStorage = storage
XCTAssertNotNil(weakStorage)
}
XCTAssertNil(weakApp)
XCTAssertNil(weakStorage)
}
}