Hi Brian! Thanks for the replies. I haven’t been able to hack on this for a few days but hopefully I can over the holiday break this weekend.
I’ve been experimenting with building XCTest for watchOS and constructing a test harness. I’ve gotten it to the point where I can execute the same test class in iOS and watchOS, with the caveat that I need to enumerate the test methods like so: import XCTest class ClaspTests: XCTestCase { static var allTests = { return [ ("testPassingTest", testPassingTest), ] }() func testPassingTest() { print("This is my test method.") XCTAssertTrue(true) } } This works fine for Swift tests, but the Swift implementation of XCTestCase doesn't inherit from NSObject, so I can’t run Objective-C tests in it. I was hoping to make a new Swift class, exposing it to Objective-C as a false XCTestCase using @objc(XCTestCase), and then making a subclass of XCTestCase in Swift to relay its tests back to XCTest. My goal here is to get as much drop-in support for running existing test suites in watchOS as possible. I can get there reasonably well with what I have so far—just by adding the allTests property—but it would be awesome to enumerate Objective-C classes as well. Being able to enumerate the test methods of the Swift classes would be a feather in the cap of this experiment, and would probably be beneficial to XCTest as a whole, but I’m not sure how I would go about that in a non-Objective-C-runtime world. Jeff Kelley slauncha...@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> | jeffkelley.org On Mon, Nov 21, 2016 at 11:06 AM, Brian Gesiak <modoca...@gmail.com> wrote: > I'm curious: what are you hoping to accomplish with corelibs-xctest? If we > can help you by modifying corelibs-xctest itself, that could be another > option here. :) > > - Brian Gesiak > > > On Mon, Nov 21, 2016 at 10:46 AM, Jeff Kelley via swift-users < > swift-users@swift.org> wrote: > >> The type comes from XCTest. I’m trying to enumerate Objective-C methods >> in order to use them with XCTest in the open-source Swift version of >> XCTest, which needs the tests to be supplied as this type: >> >> /// This is a compound type used by `XCTMain` to represent tests to run. It >> combines an >> /// `XCTestCase` subclass type with the list of test case methods to invoke >> on the class. >> /// This type is intended to be produced by the `testCase` helper function. >> /// - seealso: `testCase` >> /// - seealso: `XCTMain` >> public typealias XCTestCaseEntry = (testCaseClass: XCTestCase.Type, >> allTests: [(String, (XCTestCase) throws -> Void)]) >> >> >> >> >> Jeff Kelley >> >> slauncha...@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> | >> jeffkelley.org >> >> On Nov 21, 2016, at 1:13 AM, Jacob Bandes-Storch <jtban...@gmail.com> >> wrote: >> >> "throws" is the part that's not representable in Obj-C. Why are you using >> it? If you're interacting with method_getImplementation, you need to think >> like the Obj-C runtime. >> >> https://developer.apple.com/library/content/documentation/Co >> coa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWor >> ks.html#//apple_ref/doc/uid/TP40008048-CH104-SW1 >> >> This works: >> >> typealias DescriptionMethod = @convention(c) (NSObject, Selector) -> >> NSString >> >> let fn = >> unsafeBitCast(method_getImplementation(class_getInstanceMethod(NSObject.self, >> "description")), DescriptionMethod.self) >> >> fn(NSObject(), "description") as String >> >> >> Jacob >> >> On Sun, Nov 20, 2016 at 9:41 PM, Jeff Kelley <slauncha...@gmail.com> >> wrote: >> >>> Still trying on this (copied the code directly, Foo is actually >>> XCTestCase): >>> >>> typealias TestMethod = @convention(c) (XCTestCase) throws -> Void >>> >>> This seagulls the compiler with “error: '(XCTestCase) throws -> Void' >>> is not representable in Objective-C, so it cannot be used with >>> '@convention(c)’”. I’m trying to use it here: >>> >>> let testMethod: IMP = method_getImplementation(method) >>> >>> let test: TestMethod = unsafeBitCast(testMethod, >>> to: TestMethod.self) >>> >>> testMethods.append((methodName as String, test)) >>> >>> If I try to put the type directly in the call to unsafeBitCast(), the >>> compiler gives me an error: >>> >>> Attribute can only be applied to types, not declarations >>> >>> Thanks for your suggestions! I hadn’t seen @convention() before. >>> >>> >>> Jeff Kelley >>> >>> slauncha...@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> >>> | jeffkelley.org >>> >>> On Nov 21, 2016, at 12:08 AM, Jacob Bandes-Storch <jtban...@gmail.com> >>> wrote: >>> >>> For a function such as bar() above, the type you want to cast the IMP to >>> would probably be "@convention(c) (Foo, Selector) -> ()". >>> >>> On Sun, Nov 20, 2016 at 9:05 PM, Jeff Kelley <slauncha...@gmail.com> >>> wrote: >>> >>>> Thanks Jacob! I tried using unsafeBitCast, but it fails with the >>>> following: “fatal error: can't unsafeBitCast between types of different >>>> sizes”. I considered wrapping every call in a closure that calls >>>> objc_msgSend(), but alas, that’s not exposed to Swift. I have another >>>> approach in mind, so I’ll try that next. >>>> >>>> >>>> Jeff Kelley >>>> >>>> slauncha...@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> >>>> | jeffkelley.org >>>> >>>> On Nov 19, 2016, at 1:58 AM, Jacob Bandes-Storch <jtban...@gmail.com> >>>> wrote: >>>> >>>> I imagine unsafeBitCast would be the way to go here. But are you >>>> assuming that all of the instance methods have type "(Foo) throws -> Void" >>>> ? Or do you somehow want to dynamically use the type information? >>>> >>>> Jacob >>>> >>>> On Fri, Nov 18, 2016 at 10:37 PM, Jeff Kelley via swift-users < >>>> swift-users@swift.org> wrote: >>>> >>>>> Hello, >>>>> >>>>> I’m trying to enumerate the methods of a class in Swift using the >>>>> Objective-C runtime. Everything is working fine so far, except for the >>>>> very >>>>> last step. Suppose I have a Swift class like this: >>>>> >>>>> class Foo: SomeSuperclass { >>>>> >>>>> @objc func bar() { >>>>> print("Hello, World!") >>>>> } >>>>> >>>>> } >>>>> >>>>> Using the Objective-C runtime methods, I can get the method with >>>>> class_copyMethodList and then get to the method’s implementation >>>>> using method_getImplementation. However, what I need to do next is to >>>>> stick this into a tuple that looks like this: >>>>> >>>>> typealias FooEntry = (fooClass: SomeSuperclass.Type, methods: [(String, >>>>> (Foo) throws -> Void)]) >>>>> >>>>> For now, the workaround is to make a static variable that returns all >>>>> of the entries: >>>>> >>>>> static var allEntries = { >>>>> return [ >>>>> ("bar", bar), >>>>> ] >>>>> } >>>>> >>>>> Is there any way to go from the raw IMP that I get back from the >>>>> runtime to the Swift type so I can construct this list dynamically? >>>>> >>>>> >>>>> Jeff Kelley >>>>> >>>>> slauncha...@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> >>>>> | jeffkelley.org >>>>> >>>>> >>>>> _______________________________________________ >>>>> swift-users mailing list >>>>> swift-users@swift.org >>>>> https://lists.swift.org/mailman/listinfo/swift-users >>>>> >>>>> >>>> >>>> >>> >>> >> >> >> _______________________________________________ >> swift-users mailing list >> swift-users@swift.org >> https://lists.swift.org/mailman/listinfo/swift-users >> >> >
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users