diff --git a/Shims/Shimulator/TestLoadingShim/FBXCTestMain.m b/Shims/Shimulator/TestLoadingShim/FBXCTestMain.m index 7e074b94..1d3b76f4 100644 --- a/Shims/Shimulator/TestLoadingShim/FBXCTestMain.m +++ b/Shims/Shimulator/TestLoadingShim/FBXCTestMain.m @@ -8,12 +8,15 @@ #import "FBXCTestMain.h" #import +#import #import #import "FBDebugLog.h" #import "FBRuntimeTools.h" #import "FBXCTestConstants.h" +#import "XCTestCaseHelpers.h" #import "XCTestPrivate.h" +#import "XTSwizzle.h" #include "TargetConditionals.h" @@ -96,11 +99,32 @@ void FBDeployBlockWhenAppLoads(void(^mainBlock)()) { }]; } +/// Construct an XCTTestIdentifier using the same logic used to list the tests. +/// The identifier will contain the swift module prefix for tests written in swift, +/// as they used to in Xcode versions prior to 15.0 +static id XCTestCase__xctTestIdentifier(id self, SEL sel) +{ + NSString *classNameOut = nil; + NSString *methodNameOut = nil; + NSString *testKeyOut = nil; + parseXCTestCase(self, &classNameOut, &methodNameOut, &testKeyOut); + + Class XCTTestIdentifier_class = objc_lookUpClass("XCTTestIdentifier"); + return [[XCTTestIdentifier_class alloc] initWithStringRepresentation:[NSString stringWithFormat:@"%@/%@", classNameOut, methodNameOut] preserveModulePrefix:YES]; +} + BOOL FBXCTestMain() { if (!FBLoadXCTestIfNeeded()) { exit(TestShimExitCodeXCTestFailedLoading); } + + XTSwizzleSelectorForFunction( + objc_getClass("XCTestCase"), + @selector(_xctTestIdentifier), + (IMP)XCTestCase__xctTestIdentifier + ); + NSString *configurationPath = NSProcessInfo.processInfo.environment[@"XCTestConfigurationFilePath"]; if (!configurationPath) { NSLog(@"Failed to load XCTest as XCTestConfigurationFilePath environment variable is empty"); diff --git a/Shims/Shimulator/Tools/XCTestPrivate.h b/Shims/Shimulator/Tools/XCTestPrivate.h index 7d6af3f5..680e1761 100644 --- a/Shims/Shimulator/Tools/XCTestPrivate.h +++ b/Shims/Shimulator/Tools/XCTestPrivate.h @@ -185,6 +185,54 @@ struct __va_list_tag { - (instancetype)initWithSelector:(SEL)arg1; - (instancetype)initWithInvocation:(id)arg1; - (instancetype)init; +- (id)_xctTestIdentifier; + +@end + +@interface XCTTestIdentifier : NSObject +{ +} + ++ (_Bool)supportsSecureCoding; ++ (id)allocWithZone:(struct _NSZone *)arg1; ++ (id)bundleIdentifier; ++ (id)identifierForClass:(Class)arg1; ++ (id)leafIdentifierWithComponents:(id)arg1; ++ (id)containerIdentifierWithComponents:(id)arg1; ++ (id)containerIdentifierWithComponent:(id)arg1; +- (Class)classForCoder; +- (void)encodeWithCoder:(id)arg1; +- (id)initWithCoder:(id)arg1; +@property(readonly) unsigned long long options; +- (id)componentAtIndex:(unsigned long long)arg1; +@property(readonly) unsigned long long componentCount; +@property(readonly) NSArray *components; +- (id)initWithComponents:(id)arg1 options:(unsigned long long)arg2; +- (id)initWithStringRepresentation:(id)arg1 preserveModulePrefix:(_Bool)arg2; +- (id)initWithStringRepresentation:(id)arg1; +- (id)initWithClassName:(id)arg1; +- (id)initWithClassName:(id)arg1 methodName:(id)arg2; +- (id)initWithClassAndMethodComponents:(id)arg1; +- (id)initWithComponents:(id)arg1 isContainer:(_Bool)arg2; +- (id)copyWithZone:(struct _NSZone *)arg1; +@property(readonly) XCTTestIdentifier *swiftMethodCounterpart; +@property(readonly) XCTTestIdentifier *firstComponentIdentifier; +@property(readonly) XCTTestIdentifier *parentIdentifier; +- (id)_identifierString; +@property(readonly) NSString *identifierString; +@property(readonly) NSString *displayName; +@property(readonly) NSString *lastComponentDisplayName; +@property(readonly) NSString *lastComponent; +@property(readonly) NSString *firstComponent; +@property(readonly) _Bool representsBundle; +@property(readonly) _Bool isLeaf; +@property(readonly) _Bool isContainer; +- (unsigned long long)hash; +- (_Bool)isEqual:(id)arg1; +- (id)debugDescription; +- (id)description; +@property(readonly) _Bool isSwiftMethod; +@property(readonly) _Bool usesClassAndMethodSemantics; @end