Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ipavlidakis committed Sep 26, 2023
1 parent c7ac38d commit f67723b
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 4 deletions.
21 changes: 17 additions & 4 deletions Sources/StreamVideo/Utils/ThermalStateObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ extension LogSubsystem {
}

public final class ThermalStateObserver: ObservableObject {

public static let shared = ThermalStateObserver()

/// Published property to observe the thermal state
@Published public private(set) var state: ProcessInfo.ThermalState {
didSet {
// Determine the appropriate log level based on the thermal state
let logLevel: LogLevel
switch state {
case .nominal, .fair:
Expand All @@ -26,6 +27,7 @@ public final class ThermalStateObserver: ObservableObject {
@unknown default:
logLevel = .debug
}
// Log the thermal state change with the calculated log level
log.log(
logLevel,
message: "Thermal state changed \(oldValue) → state",
Expand All @@ -35,22 +37,33 @@ public final class ThermalStateObserver: ObservableObject {
}
}

/// Cancellable object to manage notifications
private var notificationCenterCancellable: AnyCancellable?
private var thermalStateProvider: () -> ProcessInfo.ThermalState

convenience init() {
self.init { ProcessInfo.processInfo.thermalState }
}


private init() {
self.state = ProcessInfo.processInfo.thermalState
init(thermalStateProvider: @escaping () -> ProcessInfo.ThermalState) {
// Initialize the thermal state with the current process's thermal state
self.state = thermalStateProvider()
self.thermalStateProvider = thermalStateProvider

// Set up a publisher to monitor thermal state changes
notificationCenterCancellable = NotificationCenter
.default
.publisher(for: ProcessInfo.thermalStateDidChangeNotification)
.receive(on: DispatchQueue.global(qos: .utility))
.map { _ in ProcessInfo.processInfo.thermalState }
.map { [thermalStateProvider] _ in thermalStateProvider() }
.receive(on: DispatchQueue.main)
.assign(to: \.state, on: self)
}

/// Depending on the Device's thermal state we adapt the request participants resolution.
public var scale: CGFloat {
// Determine the appropriate scaling factor based on the thermal state
switch state {
case .nominal:
return 1
Expand Down
95 changes: 95 additions & 0 deletions StreamVideoTests/Utils/ThermalStateObserverTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
//

import Foundation
@testable import StreamVideo
import XCTest
import Combine

final class ThermalStateObserverTests: XCTestCase {

private var stubThermalState: ProcessInfo.ThermalState = .nominal
private lazy var subject: ThermalStateObserver! = .init { self.stubThermalState }

override func tearDown() {
subject = nil
super.tearDown()
}

// MARK: - init

func test_init_stateHasBeenCorrectlySetUp() {
XCTAssertEqual(ThermalStateObserver.shared.state, ProcessInfo.processInfo.thermalState)
}

// MARK: - notificationObserver

func test_notificationObserver_stateChangesWhenSystemPostsNotification() {
func assertThermalState(
_ expected: ProcessInfo.ThermalState,
file: StaticString = #file,
line: UInt = #line
) {
stubThermalState = expected

let expectation = self.expectation(description: "Notification was received")
var cancellable: AnyCancellable?
cancellable = subject
.$state
.dropFirst()
.sink {
XCTAssertEqual($0, expected, file: file, line: line)
expectation.fulfill()
cancellable?.cancel()
}

NotificationCenter
.default
.post(.init(name: ProcessInfo.thermalStateDidChangeNotification))

wait(for: [expectation], timeout: defaultTimeout)
}

assertThermalState(.fair)
assertThermalState(.serious)
assertThermalState(.critical)
assertThermalState(.nominal)
}

// MARK: - scale

func test_scale_hasExpectedValueForEachThermalState() {
func assertScale(
_ thermalState: ProcessInfo.ThermalState,
expected: CGFloat,
file: StaticString = #file,
line: UInt = #line
) {
stubThermalState = thermalState

let expectation = self.expectation(description: "Notification was received")
var cancellable: AnyCancellable?
cancellable = subject
.$state
.dropFirst()
.receive(on: DispatchQueue.main)
.sink { [subject] _ in
XCTAssertEqual(subject?.scale, expected, file: file, line: line)
expectation.fulfill()
cancellable?.cancel()
}

NotificationCenter
.default
.post(.init(name: ProcessInfo.thermalStateDidChangeNotification))

wait(for: [expectation], timeout: defaultTimeout)
}

assertScale(.nominal, expected: 1)
assertScale(.fair, expected: 1.5)
assertScale(.serious, expected: 2)
assertScale(.critical, expected: 4)
}
}

0 comments on commit f67723b

Please sign in to comment.