1/* 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * All rights reserved. 4 * 5 * This source code is licensed under the BSD-style license found in the 6 * LICENSE file in the root directory of this source tree. 7 */ 8 9#import "DynamicTestCase.h" 10 11#import <objc/runtime.h> 12#import <sys/utsname.h> 13 14#if TARGET_OS_IOS 15#import <UIKit/UIDevice.h> 16#endif 17 18static NSString *deviceInfoString(void) { 19 static NSString *deviceInfo; 20 static dispatch_once_t onceToken; 21 dispatch_once(&onceToken, ^{ 22 struct utsname systemInfo; 23 uname(&systemInfo); 24#if TARGET_OS_IOS 25 UIDevice *device = UIDevice.currentDevice; 26 deviceInfo = [NSString stringWithFormat:@"%@_%@_%@", 27 device.systemName, 28 device.systemVersion, 29 @(systemInfo.machine)]; 30#elif TARGET_OS_MAC 31 NSOperatingSystemVersion version = NSProcessInfo.processInfo.operatingSystemVersion; 32 deviceInfo = [NSString stringWithFormat:@"macOS_%ld_%ld_%ld_%@", 33 (long)version.majorVersion, 34 (long)version.minorVersion, (long)version.patchVersion, @(systemInfo.machine)]; 35#endif // TARGET_OS_IOS 36 deviceInfo = [[deviceInfo 37 componentsSeparatedByCharactersInSet:[NSCharacterSet 38 punctuationCharacterSet]] 39 componentsJoinedByString:@"_"]; 40 }); 41 return deviceInfo; 42} 43 44@implementation DynamicTestCase 45 46+ (void)initialize { 47 if (self != [DynamicTestCase class]) { 48 NSString *deviceInfo = deviceInfoString(); 49 [[self dynamicTests] 50 enumerateKeysAndObjectsUsingBlock:^(NSString *testName, 51 void (^testCase)(XCTestCase *), 52 BOOL __unused *stop) { 53 NSString *methodName = 54 [NSString stringWithFormat:@"test_%@_%@", testName, deviceInfo]; 55 class_addMethod(self, 56 NSSelectorFromString(methodName), 57 imp_implementationWithBlock(testCase), 58 "v@:"); 59 }]; 60 } 61} 62 63+ (NSDictionary<NSString *, void (^)(XCTestCase *)> *)dynamicTests { 64 return @{}; 65} 66 67@end 68