Skip to content

Commit 61c7257

Browse files
committed
Test for chained class hooks
1 parent def5789 commit 61c7257

1 file changed

Lines changed: 48 additions & 11 deletions

File tree

Tests/InterposeKitTests/ClassHookTests.swift

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ fileprivate class ExampleClass: NSObject {
55
@objc static dynamic func doSomethingStatic() {}
66
@objc dynamic func doSomething() {}
77
@objc dynamic var intValue: Int { 1 }
8-
@objc dynamic var arrayValue: [String] { ["ExampleClass"] }
8+
@objc dynamic var arrayValue: [String] { ["superclass"] }
99
}
1010

1111
fileprivate class ExampleSubclass: ExampleClass {
1212
override var arrayValue: [String] {
13-
super.arrayValue + ["ExampleSubclass"]
13+
super.arrayValue + ["subclass"]
1414
}
1515
}
1616

@@ -87,7 +87,7 @@ final class ClassHookTests: XCTestCase {
8787
)
8888
}
8989

90-
func testLifecycle_idempotentApplyAndRevert() throws {
90+
func testIdempotentApplyAndRevert() throws {
9191
let object = ExampleClass()
9292

9393
let hook = try Interpose.prepareHook(
@@ -127,9 +127,9 @@ final class ClassHookTests: XCTestCase {
127127
XCTAssertEqual(hook.state, .pending)
128128
}
129129

130-
func testLifecycle_subclassOverride() throws {
130+
func testSubclassOverride() throws {
131131
let object = ExampleSubclass()
132-
XCTAssertEqual(object.arrayValue, ["ExampleClass", "ExampleSubclass"])
132+
XCTAssertEqual(object.arrayValue, ["superclass", "subclass"])
133133

134134
let superclassHook = try Interpose.applyHook(
135135
on: ExampleClass.self,
@@ -138,10 +138,10 @@ final class ClassHookTests: XCTestCase {
138138
hookSignature: (@convention(block) (NSObject) -> [String]).self
139139
) { hook in
140140
return { `self` in
141-
return hook.original(self, hook.selector) + ["ExampleClass.hook"]
141+
return hook.original(self, hook.selector) + ["superclass.hook"]
142142
}
143143
}
144-
XCTAssertEqual(object.arrayValue, ["ExampleClass", "ExampleClass.hook", "ExampleSubclass"])
144+
XCTAssertEqual(object.arrayValue, ["superclass", "superclass.hook", "subclass"])
145145

146146
let subclassHook = try Interpose.applyHook(
147147
on: ExampleSubclass.self,
@@ -150,17 +150,54 @@ final class ClassHookTests: XCTestCase {
150150
hookSignature: (@convention(block) (NSObject) -> [String]).self
151151
) { hook in
152152
return { `self` in
153-
return hook.original(self, hook.selector) + ["ExampleSubclass.hook"]
153+
return hook.original(self, hook.selector) + ["subclass.hook"]
154154
}
155155
}
156156

157-
XCTAssertEqual(object.arrayValue, ["ExampleClass", "ExampleClass.hook", "ExampleSubclass", "ExampleSubclass.hook"])
157+
XCTAssertEqual(object.arrayValue, ["superclass", "superclass.hook", "subclass", "subclass.hook"])
158158

159159
try superclassHook.revert()
160-
XCTAssertEqual(object.arrayValue, ["ExampleClass", "ExampleSubclass", "ExampleSubclass.hook"])
160+
XCTAssertEqual(object.arrayValue, ["superclass", "subclass", "subclass.hook"])
161161

162162
try subclassHook.revert()
163-
XCTAssertEqual(object.arrayValue, ["ExampleClass", "ExampleSubclass"])
163+
XCTAssertEqual(object.arrayValue, ["superclass", "subclass"])
164+
}
165+
166+
func testMultipleHooks() throws {
167+
let object = ExampleClass()
168+
XCTAssertEqual(object.arrayValue, ["superclass"])
169+
170+
let hook1 = try Interpose.applyHook(
171+
on: ExampleClass.self,
172+
for: #selector(getter: ExampleClass.arrayValue),
173+
methodSignature: (@convention(c) (NSObject, Selector) -> [String]).self,
174+
hookSignature: (@convention(block) (NSObject) -> [String]).self
175+
) { hook in
176+
return { `self` in
177+
return hook.original(self, hook.selector) + ["hook1"]
178+
}
179+
}
180+
XCTAssertEqual(object.arrayValue, ["superclass", "hook1"])
181+
182+
let hook2 = try Interpose.applyHook(
183+
on: ExampleClass.self,
184+
for: #selector(getter: ExampleClass.arrayValue),
185+
methodSignature: (@convention(c) (NSObject, Selector) -> [String]).self,
186+
hookSignature: (@convention(block) (NSObject) -> [String]).self
187+
) { hook in
188+
return { `self` in
189+
return hook.original(self, hook.selector) + ["hook2"]
190+
}
191+
}
192+
XCTAssertEqual(object.arrayValue, ["superclass", "hook1", "hook2"])
193+
194+
// For now, reverting works only in the opposite order. Reverting hook1 before hook2
195+
// would throw `revertCorrupted(…)` error.
196+
try hook2.revert()
197+
XCTAssertEqual(object.arrayValue, ["superclass", "hook1"])
198+
199+
try hook1.revert()
200+
XCTAssertEqual(object.arrayValue, ["superclass"])
164201
}
165202

166203
func testValidationFailure_methodNotFound_nonExistent() throws {

0 commit comments

Comments
 (0)