Skip to content

Commit

Permalink
Adds main actor annotations where needed (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrosen081 authored Jul 12, 2024
1 parent 278de59 commit cd0b332
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 8 deletions.
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/DependencyModule.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation

/// Provides dependencies to the object graph. Modules can be registered with WhoopDI via `WhoopDI.registerModules`.
@MainActor
open class DependencyModule {
private var dependencies: [DependencyDefinition] = []

Expand Down
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/DependencyRegister.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@MainActor
public protocol DependencyRegister {
static func removeAllDependencies()
static func registerModules(modules: [DependencyModule])
Expand Down
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/DependencyTree.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation

/// Performs a depth first, post ordered search of the given module's dependency tree and flattens the tree into a list of modules
/// in which the lowest level modules are ordered first.
@MainActor
public final class DependencyTree {

private let dependencyModule: [DependencyModule]
Expand Down
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/WhoopDI.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
@MainActor
public final class WhoopDI: DependencyRegister {
private static let serviceDict = ServiceDictionary<DependencyDefinition>()
private static var localServiceDict: ServiceDictionary<DependencyDefinition>? = nil
Expand Down
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/WhoopDIValidator.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/// Provides verification that the object graph is complete. This is intended to be called from within a test.
@MainActor
public final class WhoopDIValidator {
private let paramsDict = ServiceDictionary<Any>()

Expand Down
3 changes: 2 additions & 1 deletion Sources/WhoopDIKitMacros/InjectableMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ struct InjectableMacro: ExtensionMacro, MemberMacro {

return [
/// Adds the static inject function, such as:
/// @MainActor
/// public static func inject() -> Self {
/// Self.init(myValue: WhoopDI.inject(nil))
/// }
"""
@MainActor
\(raw: accessLevel) static func inject() -> Self {
Self.init(\(raw: injectingVariables))
}
Expand Down
14 changes: 12 additions & 2 deletions Tests/WhoopDIKitTests/DependencyModuleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,53 @@ class DependencyModuleTests: XCTestCase {
private let serviceKey = ServiceKey(String.self, name: "name")
private let serviceDict = ServiceDictionary<DependencyDefinition>()

private let module = DependencyModule()

@MainActor
func test_factory() {
let module = DependencyModule()
module.factory(name: "name") { "dependency" }
module.addToServiceDictionary(serviceDict: serviceDict)

let defintion = serviceDict[serviceKey]
XCTAssertTrue(defintion is FactoryDefinition)
}

@MainActor
func test_factoryWithParams() {
let module = DependencyModule()
module.factoryWithParams(name: "name") { (_: Any) in "dependency" }
module.addToServiceDictionary(serviceDict: serviceDict)

let defintion = serviceDict[serviceKey]
XCTAssertTrue(defintion is FactoryDefinition)
}

@MainActor
func test_singleton() {
let module = DependencyModule()
module.singleton(name: "name") { "dependency" }
module.addToServiceDictionary(serviceDict: serviceDict)

let defintion = serviceDict[serviceKey]
XCTAssertTrue(defintion is SingletonDefinition)
}

@MainActor
func test_singletonWithParams() {
let module = DependencyModule()
module.singletonWithParams(name: "name") { (_: Any) in "dependency" }
module.addToServiceDictionary(serviceDict: serviceDict)

let defintion = serviceDict[serviceKey]
XCTAssertTrue(defintion is SingletonDefinition)
}

@MainActor
func test_ServiceKey_Returns_Subclass_Type() {
let testModule = TestDependencyModule(testModuleDependencies: [])
XCTAssertEqual(testModule.serviceKey, ServiceKey(type(of: TestDependencyModule())))
}

@MainActor
func test_SetMultipleModuleDependencies() {
let moduleA = DependencyModule()
let moduleB = DependencyModule()
Expand All @@ -55,13 +63,15 @@ class DependencyModuleTests: XCTestCase {
XCTAssertEqual(module.moduleDependencies, [moduleD, moduleC, moduleB, moduleA])
}

@MainActor
func test_SetSingleModuleDependency() {
let moduleA = DependencyModule()

let module = TestDependencyModule(testModuleDependencies: [moduleA])
XCTAssertEqual(module.moduleDependencies, [moduleA])
}

@MainActor
func test_SetNoModuleDependencies() {
let module = TestDependencyModule()
XCTAssertEqual(module.moduleDependencies, [])
Expand Down
14 changes: 11 additions & 3 deletions Tests/WhoopDIKitTests/DependencyTreeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import XCTest
@testable import WhoopDIKit

final class DependencyTreeTests: XCTestCase {
override func tearDown() {
WhoopDI.removeAllDependencies()

override func tearDown() async throws {
await WhoopDI.removeAllDependencies()
}

@MainActor
func testDepthFirstSearch_SingleList() {
let moduleD = module("D")
let moduleC = module("C", dependentModules: [moduleD])
Expand All @@ -17,6 +18,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual([moduleD, moduleC, moduleB, moduleA], tree.modules)
}

@MainActor
func testDepthFirstSearch_SingeList_FilterDuplicates() {
let moduleDuplicate = module("C")
let moduleC = module("C", dependentModules: [moduleDuplicate])
Expand All @@ -27,6 +29,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual([moduleC, moduleB, moduleA], tree.modules)
}

@MainActor
func testDepthFirstSearch_NoDependencyLoop() {
var loopDependency: [DependencyModule] = []
let moduleC = KeyedModule(key: "C", keyedModuleDependencies: loopDependency)
Expand All @@ -38,6 +41,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual([moduleC, moduleB, moduleA], tree.modules)
}

@MainActor
func testDepthFirstSearch_OneTopLevelModule() {
let modules = generateTree(rootKey: "A")

Expand All @@ -58,6 +62,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual(keys, tree.modules.map { $0.serviceKey.name })
}

@MainActor
func testDepthFirstSearch_MultipleTopLevelModules() {
let modules = generateTree(rootKey: "A") + generateTree(rootKey: "B")

Expand All @@ -80,6 +85,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual(keys, tree.modules.map { $0.serviceKey.name })
}

@MainActor
func testDepthFirstSearch_DuplicateTopLevelModules() {
let modules = generateTree(rootKey: "A") + generateTree(rootKey: "A")

Expand All @@ -102,6 +108,7 @@ final class DependencyTreeTests: XCTestCase {
}

private extension DependencyTreeTests {
@MainActor
func generateTree(rootKey: String = "", depth: Int = 0) -> [KeyedModule] {
if depth == 3 { return [] }

Expand All @@ -112,6 +119,7 @@ private extension DependencyTreeTests {
}
}

@MainActor
func module(_ name: String, dependentModules: [DependencyModule] = []) -> KeyedModule {
KeyedModule(key: name, keyedModuleDependencies: dependentModules)
}
Expand Down
4 changes: 4 additions & 0 deletions Tests/WhoopDIKitTests/InjectableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ final class InjectableTests: XCTestCase {
var newerThing: String { "not again" }
let bestThing: Int
@MainActor
internal static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject("Test"))
}
Expand Down Expand Up @@ -60,6 +61,7 @@ final class InjectableTests: XCTestCase {
lazy var lazyVar: Double = 100
let otherStringType: String.Type
@MainActor
public static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject(nil), otherStringType: WhoopDI.inject(nil))
}
Expand Down Expand Up @@ -91,6 +93,7 @@ final class InjectableTests: XCTestCase {
var newerThing: String { "not again" }
var bestThing: Int = 1
@MainActor
private static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject(nil))
}
Expand All @@ -117,6 +120,7 @@ final class InjectableTests: XCTestCase {
struct ClosureHolder {
let closure: () -> String
@MainActor
internal static func inject() -> Self {
Self.init(closure: WhoopDI.inject(nil))
}
Expand Down
16 changes: 14 additions & 2 deletions Tests/WhoopDIKitTests/WhoopDITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,32 @@ import XCTest

class WhoopDITests: XCTestCase {

override func tearDown() {
WhoopDI.removeAllDependencies()
override func tearDown() async throws {
await WhoopDI.removeAllDependencies()
}

@MainActor
func test_inject() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: Dependency = WhoopDI.inject("C_Factory", "param")
XCTAssertTrue(dependency is DependencyC)
}

@MainActor
func test_inject_generic_integer() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: GenericDependency<Int> = WhoopDI.inject()
XCTAssertEqual(42, dependency.value)
}

@MainActor
func test_inject_generic_string() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: GenericDependency<String> = WhoopDI.inject()
XCTAssertEqual("string", dependency.value)
}

@MainActor
func test_inject_localDefinition() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: Dependency = WhoopDI.inject("C_Factory") { module in
Expand All @@ -35,12 +39,14 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(dependency is DependencyA)
}

@MainActor
func test_inject_localDefinition_noOverride() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: Dependency = WhoopDI.inject("C_Factory", params: "params") { _ in }
XCTAssertTrue(dependency is DependencyC)
}

@MainActor
func test_inject_localDefinition_withParams() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: Dependency = WhoopDI.inject("C_Factory", params: "params") { module in
Expand All @@ -49,6 +55,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(dependency is DependencyB)
}

@MainActor
func test_validation_fails_barParams() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let validator = WhoopDIValidator()
Expand All @@ -57,6 +64,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(failed)
}

@MainActor
func test_validation_fails_missingDependencies() {
WhoopDI.registerModules(modules: [BadTestModule()])
let validator = WhoopDIValidator()
Expand All @@ -70,6 +78,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(failed)
}

@MainActor
func test_validation_fails_nilFactoryDependency() {
WhoopDI.registerModules(modules: [NilFactoryModule()])
let validator = WhoopDIValidator()
Expand All @@ -83,6 +92,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(failed)
}

@MainActor
func test_validation_fails_nilSingletonDependency() {
WhoopDI.registerModules(modules: [NilSingletonModule()])
let validator = WhoopDIValidator()
Expand All @@ -96,6 +106,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(failed)
}

@MainActor
func test_validation_succeeds() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let validator = WhoopDIValidator()
Expand All @@ -110,6 +121,7 @@ class WhoopDITests: XCTestCase {
}
}

@MainActor
func test_injecting() {
WhoopDI.registerModules(modules: [FakeTestModuleForInjecting()])
let testInjecting: TestInjectingThing = WhoopDI.inject()
Expand Down

0 comments on commit cd0b332

Please sign in to comment.