Skip to content

[Swift 6] Add Swift 6 testing for CoreInternal #14561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 13, 2025
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
10 changes: 10 additions & 0 deletions .github/workflows/core_internal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ jobs:
build-env:
- os: macos-14
xcode: Xcode_15.2
swift_version: 5.9
- os: macos-15
xcode: Xcode_16.2
swift_version: 5.9
- os: macos-15
xcode: Xcode_16.2
swift_version: 6.0
runs-on: ${{ matrix.build-env.os }}
steps:
- uses: actions/checkout@v4
Expand All @@ -31,6 +36,8 @@ jobs:
run: scripts/setup_bundler.sh
- name: Xcode
run: sudo xcode-select -s /Applications/${{ matrix.build-env.xcode }}.app/Contents/Developer
- name: Set Swift swift_version
run: sed -i "" "s/s.swift_version[[:space:]]*=[[:space:]]*'5.9'/s.swift_version = '${{ matrix.build-env.swift_version }}'/" FirebaseCoreInternal.podspec
- name: Build and test
run: scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseCoreInternal.podspec --platforms=${{ matrix.target }}

Expand Down Expand Up @@ -99,6 +106,9 @@ jobs:
run: scripts/setup_spm_tests.sh
- name: Xcode
run: sudo xcode-select -s /Applications/${{ matrix.xcode }}.app/Contents/Developer
- name: Install visionOS, if needed.
if: matrix.target == 'visionOS'
run: xcodebuild -downloadPlatform visionOS
- name: FirebaseCoreInternalTests
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FirebaseCoreInternalTests ${{ matrix.target }} spm

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
import XCTest

class HeartbeatLoggingIntegrationTests: XCTestCase {
// 2021-11-01 @ 00:00:00 (EST)
let date = Date(timeIntervalSince1970: 1_635_739_200)

override func setUpWithError() throws {
try HeartbeatLoggingTestUtils.removeUnderlyingHeartbeatStorageContainers()
}
Expand Down Expand Up @@ -52,7 +49,7 @@ class HeartbeatLoggingIntegrationTests: XCTestCase {
)
}

func testLogAndFlushAsync() throws {
@MainActor func testLogAndFlushAsync() throws {
// Given
let heartbeatController = HeartbeatController(id: #function)
let expectedDate = HeartbeatsPayload.dateFormatter.string(from: Date())
Expand Down Expand Up @@ -123,8 +120,9 @@ class HeartbeatLoggingIntegrationTests: XCTestCase {

func testMultipleControllersWithTheSameIDUseTheSameStorageInstance() throws {
// Given
let heartbeatController1 = HeartbeatController(id: #function, dateProvider: { self.date })
let heartbeatController2 = HeartbeatController(id: #function, dateProvider: { self.date })
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let heartbeatController1 = HeartbeatController(id: #function, dateProvider: { date })
let heartbeatController2 = HeartbeatController(id: #function, dateProvider: { date })
// When
heartbeatController1.log("dummy_agent")
// Then
Expand All @@ -146,92 +144,85 @@ class HeartbeatLoggingIntegrationTests: XCTestCase {
assertHeartbeatControllerFlushesEmptyPayload(heartbeatController1)
}

func testLogAndFlushConcurrencyStressTest() throws {
@MainActor func testLogAndFlushConcurrencyStressTest() throws {
// Given
let heartbeatController = HeartbeatController(id: #function, dateProvider: { self.date })
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let heartbeatController = HeartbeatController(id: #function, dateProvider: { date })

// When
DispatchQueue.concurrentPerform(iterations: 100) { _ in
heartbeatController.log("dummy_agent")
}

var payloads: [HeartbeatsPayload] = []
let expectation = self.expectation(description: #function)

DispatchQueue.concurrentPerform(iterations: 100) { _ in
let payload = heartbeatController.flush()
payloads.append(payload)
}

// Then
let nonEmptyPayloads = payloads.filter { payload in
// Filter out non-empty payloads.
!payload.userAgentPayloads.isEmpty
}

XCTAssertEqual(nonEmptyPayloads.count, 1)

let payload = try XCTUnwrap(nonEmptyPayloads.first)
try HeartbeatLoggingTestUtils.assertEqualPayloadStrings(
payload.headerValue(),
"""
{
"version": 2,
"heartbeats": [
if !payload.userAgentPayloads.isEmpty {
try! HeartbeatLoggingTestUtils.assertEqualPayloadStrings(
payload.headerValue(),
"""
{
"agent": "dummy_agent",
"dates": ["2021-11-01"]
"version": 2,
"heartbeats": [
{
"agent": "dummy_agent",
"dates": ["2021-11-01"]
}
]
}
]
"""
)
expectation.fulfill()
}
"""
)
}

// Then
wait(for: [expectation])
}

func testLogAndFlushHeartbeatFromTodayConcurrencyStressTest() throws {
@MainActor func testLogAndFlushHeartbeatFromTodayConcurrencyStressTest() throws {
// Given
let heartbeatController = HeartbeatController(id: #function, dateProvider: { self.date })
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let heartbeatController = HeartbeatController(id: #function, dateProvider: { date })

// When
DispatchQueue.concurrentPerform(iterations: 100) { _ in
heartbeatController.log("dummy_agent")
}

var payloads: [HeartbeatsPayload] = []
let expectation = self.expectation(description: #function)

DispatchQueue.concurrentPerform(iterations: 100) { _ in
let payload = heartbeatController.flushHeartbeatFromToday()
payloads.append(payload)
}

// Then
let nonEmptyPayloads = payloads.filter { payload in
// Filter out non-empty payloads.
!payload.userAgentPayloads.isEmpty
}

XCTAssertEqual(nonEmptyPayloads.count, 1)

let payload = try XCTUnwrap(nonEmptyPayloads.first)
try HeartbeatLoggingTestUtils.assertEqualPayloadStrings(
payload.headerValue(),
"""
{
"version": 2,
"heartbeats": [
if !payload.userAgentPayloads.isEmpty {
try! HeartbeatLoggingTestUtils.assertEqualPayloadStrings(
payload.headerValue(),
"""
{
"agent": "dummy_agent",
"dates": ["2021-11-01"],
"version": 2,
"heartbeats": [
{
"agent": "dummy_agent",
"dates": ["2021-11-01"],
}
]
}
]
"""
)
expectation.fulfill()
}
"""
)
}

// Then
wait(for: [expectation])

assertHeartbeatControllerFlushesEmptyPayload(heartbeatController)
}

func testLogRepeatedly_WithoutFlushing_LimitsOnWrite() throws {
// Given
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let testDate = AdjustableDate(date: date)
let heartbeatController = HeartbeatController(id: #function, dateProvider: { testDate.date })

Expand Down Expand Up @@ -313,7 +304,8 @@ class HeartbeatLoggingIntegrationTests: XCTestCase {

func testLogAndFlush_AfterUnderlyingStorageIsDeleted_CreatesNewStorage() throws {
// Given
let heartbeatController = HeartbeatController(id: #function, dateProvider: { self.date })
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let heartbeatController = HeartbeatController(id: #function, dateProvider: { date })
heartbeatController.log("dummy_agent")
_ = XCTWaiter.wait(for: [expectation(description: "Wait for async log.")], timeout: 0.1)

Expand Down
23 changes: 14 additions & 9 deletions FirebaseCore/Internal/Tests/Unit/HeartbeatControllerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
import XCTest

class HeartbeatControllerTests: XCTestCase {
// 2021-11-01 @ 00:00:00 (EST)
let date = Date(timeIntervalSince1970: 1_635_739_200)

func testFlush_WhenEmpty_ReturnsEmptyPayload() throws {
// Given
let controller = HeartbeatController(storage: HeartbeatStorageFake())
Expand All @@ -28,9 +25,10 @@ class HeartbeatControllerTests: XCTestCase {

func testLogAndFlush() throws {
// Given
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let controller = HeartbeatController(
storage: HeartbeatStorageFake(),
dateProvider: { self.date }
dateProvider: { date }
)

assertHeartbeatControllerFlushesEmptyPayload(controller)
Expand Down Expand Up @@ -58,11 +56,12 @@ class HeartbeatControllerTests: XCTestCase {
assertHeartbeatControllerFlushesEmptyPayload(controller)
}

func testLogAndFlushAsync() throws {
@MainActor func testLogAndFlushAsync() throws {
// Given
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let controller = HeartbeatController(
storage: HeartbeatStorageFake(),
dateProvider: { self.date }
dateProvider: { date }
)
let expectation = expectation(description: #function)

Expand Down Expand Up @@ -99,6 +98,7 @@ class HeartbeatControllerTests: XCTestCase {

func testLogAtEndOfTimePeriodAndAcceptAtStartOfNextOne() throws {
// Given
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let testDate = AdjustableDate(date: date)

let controller = HeartbeatController(
Expand Down Expand Up @@ -148,9 +148,10 @@ class HeartbeatControllerTests: XCTestCase {

func testDoNotLogMoreThanOnceInACalendarDay() throws {
// Given
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let controller = HeartbeatController(
storage: HeartbeatStorageFake(),
dateProvider: { self.date }
dateProvider: { date }
)

// When
Expand Down Expand Up @@ -178,9 +179,10 @@ class HeartbeatControllerTests: XCTestCase {

func testDoNotLogMoreThanOnceInACalendarDay_AfterFlushing() throws {
// Given
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let controller = HeartbeatController(
storage: HeartbeatStorageFake(),
dateProvider: { self.date }
dateProvider: { date }
)

// When
Expand Down Expand Up @@ -308,6 +310,7 @@ class HeartbeatControllerTests: XCTestCase {

func testLoggingDependsOnDateNotUserAgent() throws {
// Given
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let testDate = AdjustableDate(date: date)
let heartbeatController = HeartbeatController(
storage: HeartbeatStorageFake(),
Expand Down Expand Up @@ -355,6 +358,7 @@ class HeartbeatControllerTests: XCTestCase {

func testFlushHeartbeatFromToday_WhenTodayHasAHeartbeat_ReturnsPayloadWithOnlyTodaysHeartbeat() throws {
// Given
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let yesterdaysDate = date.addingTimeInterval(-1 * 60 * 60 * 24)
let todaysDate = date
let tomorrowsDate = date.addingTimeInterval(60 * 60 * 24)
Expand Down Expand Up @@ -416,7 +420,8 @@ class HeartbeatControllerTests: XCTestCase {

func testFlushHeartbeatFromToday_WhenTodayDoesNotHaveAHeartbeat_ReturnsEmptyPayload() throws {
// Given
let heartbeatController = HeartbeatController(id: #function, dateProvider: { self.date })
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
let heartbeatController = HeartbeatController(id: #function, dateProvider: { date })
// When
heartbeatController.flushHeartbeatFromToday()
// Then
Expand Down
21 changes: 11 additions & 10 deletions FirebaseCore/Internal/Tests/Unit/HeartbeatStorageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
import XCTest

extension HeartbeatsBundle {
static let testHeartbeatBundle: Self = {
static func testHeartbeatBundle() -> HeartbeatsBundle {
var heartbeatBundle = HeartbeatsBundle(capacity: 1)
heartbeatBundle.append(Heartbeat(agent: "dummy_agent", date: Date()))
let date = Date(timeIntervalSince1970: 1_635_739_200) // 2021-11-01 @ 00:00:00 (EST)
heartbeatBundle.append(Heartbeat(agent: "dummy_agent", date: date))
return heartbeatBundle
}()
}
}

class HeartbeatStorageTests: XCTestCase {
Expand Down Expand Up @@ -108,15 +109,15 @@ class HeartbeatStorageTests: XCTestCase {
// Assert that heartbeat storage is empty.
XCTAssertNil(heartbeatsBundle)
// Write new value.
return HeartbeatsBundle.testHeartbeatBundle
return HeartbeatsBundle.testHeartbeatBundle()
}

heartbeatStorage.readAndWriteAsync { heartbeatsBundle in
expectation.fulfill()
// Assert old value is read.
XCTAssertEqual(
heartbeatsBundle?.makeHeartbeatsPayload(),
HeartbeatsBundle.testHeartbeatBundle.makeHeartbeatsPayload()
HeartbeatsBundle.testHeartbeatBundle().makeHeartbeatsPayload()
)
// Write some new value.
return heartbeatsBundle
Expand Down Expand Up @@ -158,18 +159,18 @@ class HeartbeatStorageTests: XCTestCase {

heartbeatStorage.readAndWriteAsync { heartbeatsBundle in
expectation.fulfill()
return HeartbeatsBundle.testHeartbeatBundle
return HeartbeatsBundle.testHeartbeatBundle()
}

// Then
heartbeatStorage.readAndWriteAsync { heartbeatsBundle in
expectation.fulfill()
XCTAssertNotEqual(
heartbeatsBundle?.makeHeartbeatsPayload(),
HeartbeatsBundle.testHeartbeatBundle.makeHeartbeatsPayload(),
HeartbeatsBundle.testHeartbeatBundle().makeHeartbeatsPayload(),
"They should not be equal because the previous save failed."
)
return HeartbeatsBundle.testHeartbeatBundle
return HeartbeatsBundle.testHeartbeatBundle()
}

wait(for: [expectation], timeout: 0.5)
Expand Down Expand Up @@ -220,7 +221,7 @@ class HeartbeatStorageTests: XCTestCase {
// Assert that heartbeat storage is empty.
XCTAssertNil(heartbeatsBundle)
// Write new value.
return HeartbeatsBundle.testHeartbeatBundle
return HeartbeatsBundle.testHeartbeatBundle()
} completion: { result in
switch result {
case .success: break
Expand All @@ -236,7 +237,7 @@ class HeartbeatStorageTests: XCTestCase {
// Assert old value is read.
XCTAssertEqual(
heartbeatsBundle?.makeHeartbeatsPayload(),
HeartbeatsBundle.testHeartbeatBundle.makeHeartbeatsPayload()
HeartbeatsBundle.testHeartbeatBundle().makeHeartbeatsPayload()
)
// Write some new value.
expectation2.fulfill()
Expand Down
Loading