@@ -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
1111fileprivate 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