diff --git a/XCTestBootstrap/Configuration/FBXCTestConfiguration.h b/XCTestBootstrap/Configuration/FBXCTestConfiguration.h index a33677272..768d27e75 100644 --- a/XCTestBootstrap/Configuration/FBXCTestConfiguration.h +++ b/XCTestBootstrap/Configuration/FBXCTestConfiguration.h @@ -186,10 +186,15 @@ typedef NS_OPTIONS(NSUInteger, FBLogicTestMirrorLogs) { */ @property (nonatomic, readonly) FBLogicTestMirrorLogs mirroring; +/** + The Directory to use for storing logs generated during the execution of the test run. + */ +@property (nonatomic, nullable, copy, readonly) NSString *logDirectoryPath; + /** The Designated Initializer. */ -+ (instancetype)configurationWithShims:(FBXCTestShimConfiguration *)shims environment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(nullable NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring; ++ (instancetype)configurationWithShims:(FBXCTestShimConfiguration *)shims environment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory logDirectoryPath:(nullable NSString *)logDirectoryPath testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(nullable NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring; @end diff --git a/XCTestBootstrap/Configuration/FBXCTestConfiguration.m b/XCTestBootstrap/Configuration/FBXCTestConfiguration.m index 9ae855777..3d65dbfa3 100644 --- a/XCTestBootstrap/Configuration/FBXCTestConfiguration.m +++ b/XCTestBootstrap/Configuration/FBXCTestConfiguration.m @@ -247,12 +247,12 @@ @implementation FBLogicTestConfiguration #pragma mark Initializers -+ (instancetype)configurationWithShims:(FBXCTestShimConfiguration *)shims environment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring ++ (instancetype)configurationWithShims:(FBXCTestShimConfiguration *)shims environment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory logDirectoryPath:(nullable NSString *)logDirectoryPath testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring { - return [[FBLogicTestConfiguration alloc] initWithShims:shims environment:environment workingDirectory:workingDirectory testBundlePath:testBundlePath waitForDebugger:waitForDebugger timeout:timeout testFilter:testFilter mirroring:mirroring]; + return [[FBLogicTestConfiguration alloc] initWithShims:shims environment:environment workingDirectory:workingDirectory logDirectoryPath:logDirectoryPath testBundlePath:testBundlePath waitForDebugger:waitForDebugger timeout:timeout testFilter:testFilter mirroring:mirroring]; } -- (instancetype)initWithShims:(FBXCTestShimConfiguration *)shims environment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring +- (instancetype)initWithShims:(FBXCTestShimConfiguration *)shims environment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory logDirectoryPath:(NSString *)logDirectoryPath testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring { self = [super initWithShims:shims environment:environment workingDirectory:workingDirectory testBundlePath:testBundlePath waitForDebugger:waitForDebugger timeout:timeout]; if (!self) { @@ -261,6 +261,7 @@ - (instancetype)initWithShims:(FBXCTestShimConfiguration *)shims environment:(NS _testFilter = testFilter; _mirroring = mirroring; + _logDirectoryPath = logDirectoryPath; return self; } diff --git a/XCTestBootstrap/Reporters/FBJSONTestReporter.h b/XCTestBootstrap/Reporters/FBJSONTestReporter.h index 2bbcfdb0a..a33ec55e3 100644 --- a/XCTestBootstrap/Reporters/FBJSONTestReporter.h +++ b/XCTestBootstrap/Reporters/FBJSONTestReporter.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN /** A Reporter using xctool's linewise-json output. */ -@interface FBJSONTestReporter : NSObject +@interface FBJSONTestReporter : NSObject /** The Designated Initializer. diff --git a/XCTestBootstrap/Reporters/FBJSONTestReporter.m b/XCTestBootstrap/Reporters/FBJSONTestReporter.m index 18a41d2a6..6e2bf70e3 100644 --- a/XCTestBootstrap/Reporters/FBJSONTestReporter.m +++ b/XCTestBootstrap/Reporters/FBJSONTestReporter.m @@ -332,6 +332,10 @@ - (NSString *)noStartOfTestPlanErrorMessage }; } +- (void)setLogDirectoryPath:(NSString *)logDirectoryPath +{ +} + @end static inline NSString *FBFullyFormattedXCTestName(NSString *className, NSString *methodName) diff --git a/XCTestBootstrap/Reporters/FBLogicReporterAdapter.h b/XCTestBootstrap/Reporters/FBLogicReporterAdapter.h index 08ee009b2..cccf707f0 100644 --- a/XCTestBootstrap/Reporters/FBLogicReporterAdapter.h +++ b/XCTestBootstrap/Reporters/FBLogicReporterAdapter.h @@ -7,17 +7,17 @@ #import #import +#import NS_ASSUME_NONNULL_BEGIN -@protocol FBXCTestReporter; @protocol FBControlCoreLogger; /** This adapter parses streams of events in JSON and invokes the corresponding methods in the provided FBXCTestReporter */ -@interface FBLogicReporterAdapter : NSObject +@interface FBLogicReporterAdapter : NSObject /** The Designated Initializer. @@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN @param logger an optional logger to log to, @return a new FBLogicXCTestReporter instance. */ -- (instancetype)initWithReporter:(id)reporter logger:(nullable id)logger; +- (instancetype)initWithReporter:(id)reporter logger:(nullable id)logger; @end diff --git a/XCTestBootstrap/Reporters/FBLogicReporterAdapter.m b/XCTestBootstrap/Reporters/FBLogicReporterAdapter.m index f2e7684da..b872b914d 100644 --- a/XCTestBootstrap/Reporters/FBLogicReporterAdapter.m +++ b/XCTestBootstrap/Reporters/FBLogicReporterAdapter.m @@ -13,14 +13,14 @@ @interface FBLogicReporterAdapter () -@property (nonatomic, readonly) id reporter; +@property (nonatomic, readonly) id reporter; @property (nonatomic, readonly) FBXCTestLogger *logger; @end @implementation FBLogicReporterAdapter -- (instancetype)initWithReporter:(id)reporter logger:(nullable id)logger +- (instancetype)initWithReporter:(id)reporter logger:(nullable id)logger { self = [self init]; if (!self) { @@ -138,4 +138,8 @@ - (void)didCrashDuringTest:(NSError *)error } } +- (void)setLogDirectoryPath:(NSString *)logDirectoryPath { + [self.reporter setLogDirectoryPath:logDirectoryPath]; +} + @end diff --git a/XCTestBootstrap/Reporters/FBXCTestReporter.h b/XCTestBootstrap/Reporters/FBXCTestReporter.h index 9b796abcc..66de0e571 100644 --- a/XCTestBootstrap/Reporters/FBXCTestReporter.h +++ b/XCTestBootstrap/Reporters/FBXCTestReporter.h @@ -170,4 +170,21 @@ NS_ASSUME_NONNULL_BEGIN @end + + +/** + fbxtest's reporting protocol to handle log files. + */ +@protocol FBXCTestReporterWithFiles + +/** + Add log files contained in the directory to the report. + @param logDirectoryPath the path to the log directory + */ +- (void)setLogDirectoryPath:(NSString *)logDirectoryPath; + +@end + + + NS_ASSUME_NONNULL_END diff --git a/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.m b/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.m index 474d4be86..a07b3bafb 100644 --- a/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.m +++ b/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.m @@ -217,7 +217,6 @@ - (instancetype)initWithExecutor:(id)executor configura id reporter = self.reporter; id logger = self.logger; dispatch_queue_t queue = self.executor.workQueue; - FBXCTestLogger *mirrorLogger = [FBXCTestLogger defaultLoggerInDefaultDirectory]; BOOL mirrorToLogger = (self.configuration.mirroring & FBLogicTestMirrorLogger) != 0; BOOL mirrorToFiles = (self.configuration.mirroring & FBLogicTestMirrorFileLogs) != 0; @@ -256,6 +255,8 @@ - (instancetype)initWithExecutor:(id)executor configura FBFuture> *stdErrFuture = [FBFuture futureWithResult:stdErrConsumer]; FBFuture> *shimFuture = [FBFuture futureWithResult:shimConsumer]; if (mirrorToFiles) { + FBXCTestLogger *mirrorLogger = self.configuration.logDirectoryPath ? [FBXCTestLogger defaultLoggerInDirectory:self.configuration.logDirectoryPath] : [FBXCTestLogger defaultLoggerInDefaultDirectory]; + stdOutFuture = [mirrorLogger logConsumptionToFile:stdOutConsumer outputKind:@"out" udid:udid logger:logger]; stdErrFuture = [mirrorLogger logConsumptionToFile:stdErrConsumer outputKind:@"err" udid:udid logger:logger]; shimFuture = [mirrorLogger logConsumptionToFile:shimConsumer outputKind:@"shim" udid:udid logger:logger]; diff --git a/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.h b/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.h index 0d65d41dd..d4876bbfe 100644 --- a/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.h +++ b/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN /** A Double for verifiying callers of FBXCTestReporter */ -@interface FBXCTestReporterDouble : NSObject +@interface FBXCTestReporterDouble : NSObject /** An array of the started test suites. @@ -46,6 +46,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, assign, readonly) BOOL printReportWasCalled; +/** + Path to logs directory + */ +@property (nonatomic, nullable, copy) NSString *logDirectoryPath; + /** Get events by name that were recieved from `-[FBXCTestReporter handleExternalEvent:]` */ diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.m b/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.m index e684c9d40..40a79435b 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.m +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.m @@ -75,6 +75,7 @@ + (nullable instancetype)commandLineFromArguments:(NSArray *)argumen configurationWithShims:shims environment:environment workingDirectory:workingDirectory + logDirectoryPath:nil testBundlePath:testBundlePath waitForDebugger:waitForDebugger timeout:timeout diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.h b/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.h index 88a4338b5..49481ea44 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.h +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.h @@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN @class FBXCTestCommandLine; @class FBXCTestLogger; @protocol FBXCTestReporter; +@protocol FBXCTestReporterWithFiles; /** Context for the Test Run. @@ -32,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN @param logger the logger to log with. @return a new context. */ -+ (instancetype)contextWithReporter:(nullable id)reporter logger:(nullable FBXCTestLogger *)logger; ++ (instancetype)contextWithReporter:(nullable id)reporter logger:(nullable FBXCTestLogger *)logger; #pragma mark Properties @@ -44,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN /** The Reporter to report to. */ -@property (nonatomic, strong, readonly, nullable) id reporter; +@property (nonatomic, strong, readonly, nullable) id reporter; #pragma mark Public Methods diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.m b/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.m index 8cd2adef8..2558e5366 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.m +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.m @@ -22,13 +22,13 @@ @implementation FBXCTestContext #pragma mark Initializers -+ (instancetype)contextWithReporter:(nullable id)reporter logger:(nullable FBXCTestLogger *)logger ++ (instancetype)contextWithReporter:(nullable id)reporter logger:(nullable FBXCTestLogger *)logger { return [[FBXCTestContext alloc] initWithReporter:reporter logger:logger]; } -- (instancetype)initWithReporter:(nullable id)reporter logger:(nullable FBXCTestLogger *)logger +- (instancetype)initWithReporter:(nullable id)reporter logger:(nullable FBXCTestLogger *)logger { self = [super init]; if (!self) { diff --git a/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXLogicTestConfigurationTests.m b/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXLogicTestConfigurationTests.m index 3e2a89d4d..db9e2a0fd 100644 --- a/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXLogicTestConfigurationTests.m +++ b/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXLogicTestConfigurationTests.m @@ -59,6 +59,7 @@ - (void)testMacLogicTests configurationWithShims:configuration.shims environment:processEnvironment workingDirectory:workingDirectory + logDirectoryPath:nil testBundlePath:testBundlePath waitForDebugger:NO timeout:0 @@ -94,6 +95,7 @@ - (void)testMacLogicTestsIgnoresDestination configurationWithShims:configuration.shims environment:processEnvironment workingDirectory:workingDirectory + logDirectoryPath:nil testBundlePath:testBundlePath waitForDebugger:NO timeout:0 diff --git a/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSLogicTestConfigurationTests.m b/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSLogicTestConfigurationTests.m index 1c54ded3e..cc6ef3ee1 100644 --- a/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSLogicTestConfigurationTests.m +++ b/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSLogicTestConfigurationTests.m @@ -60,6 +60,7 @@ - (void)testiOSLogicTestsWithDestinationAndSDK configurationWithShims:configuration.shims environment:processEnvironment workingDirectory:workingDirectory + logDirectoryPath:nil testBundlePath:self.iOSUnitTestBundlePath waitForDebugger:NO timeout:0 @@ -98,6 +99,7 @@ - (void)testiOSLogicTestsWithDestinationWithoutSDK configurationWithShims:configuration.shims environment:processEnvironment workingDirectory:workingDirectory + logDirectoryPath:nil testBundlePath:self.iOSUnitTestBundlePath waitForDebugger:NO timeout:0 @@ -138,6 +140,7 @@ - (void)testiOSLogicTestsWithSDKWithoutDestination configurationWithShims:configuration.shims environment:processEnvironment workingDirectory:workingDirectory + logDirectoryPath:nil testBundlePath:self.iOSUnitTestBundlePath waitForDebugger:NO timeout:0 diff --git a/idb_companion/Server/FBIDBCommandExecutor.h b/idb_companion/Server/FBIDBCommandExecutor.h index 8fda8c232..75ad15676 100644 --- a/idb_companion/Server/FBIDBCommandExecutor.h +++ b/idb_companion/Server/FBIDBCommandExecutor.h @@ -321,7 +321,7 @@ This allows to avoid the permission popup the first time we open a deeplink @param logger the logger to log to. @return a Future that resolves with the xctest operation. */ -- (FBFuture *)xctest_run:(FBXCTestRunRequest *)request reporter:(id)reporter logger:(id)logger; +- (FBFuture *)xctest_run:(FBXCTestRunRequest *)request reporter:(id)reporter logger:(id)logger; /** Starts the debugserver diff --git a/idb_companion/Server/FBIDBCommandExecutor.m b/idb_companion/Server/FBIDBCommandExecutor.m index c15cb693c..442c12584 100644 --- a/idb_companion/Server/FBIDBCommandExecutor.m +++ b/idb_companion/Server/FBIDBCommandExecutor.m @@ -238,7 +238,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor if (self.target.state == FBiOSTargetStateShutdown) { return [self remove_all_storage_and_clear_keychain]; } - + return [[self uninstall_all_applications] onQueue:self.target.workQueue fmap:^FBFuture *(id _) { return [self remove_all_storage_and_clear_keychain]; }]; @@ -314,7 +314,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor [replacements addEntriesFromDictionary:self.storageManager.replacementMapping]; [replacements addEntriesFromDictionary:self.target.replacementMapping]; NSDictionary *environment = [self applyEnvironmentReplacements:configuration.environment replacements:replacements]; - + FBApplicationLaunchConfiguration *derived = [[FBApplicationLaunchConfiguration alloc] initWithBundleID:configuration.bundleID bundleName:configuration.bundleName @@ -343,7 +343,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor return interpolatedEnvironment; } -- (FBFuture *)xctest_run:(FBXCTestRunRequest *)request reporter:(id)reporter logger:(id)logger +- (FBFuture *)xctest_run:(FBXCTestRunRequest *)request reporter:(id)reporter logger:(id)logger { return [request startWithBundleStorageManager:self.storageManager.xctest target:self.target reporter:reporter logger:logger temporaryDirectory:self.temporaryDirectory]; } diff --git a/idb_companion/Server/FBIDBServiceHandler.mm b/idb_companion/Server/FBIDBServiceHandler.mm index 95f6591d6..9a63eac53 100644 --- a/idb_companion/Server/FBIDBServiceHandler.mm +++ b/idb_companion/Server/FBIDBServiceHandler.mm @@ -262,6 +262,7 @@ static Status respond_file_path(NSURL *source, NSString *destination, grpc::inte NSString *testBundleID = nsstring_from_c_string(request->test_bundle_id()); BOOL reportActivities = request->report_activities(); BOOL collectCoverage = request->collect_coverage(); + BOOL collectLogs = request->collect_logs(); if (request->tests_to_run_size() > 0) { testsToRun = NSMutableSet.set; @@ -278,7 +279,7 @@ static Status respond_file_path(NSURL *source, NSString *destination, grpc::inte switch (request->mode().mode_case()) { case idb::XctestRunRequest_Mode::kLogic: { - return [FBXCTestRunRequest logicTestWithTestBundleID:testBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities collectCoverage:collectCoverage]; + return [FBXCTestRunRequest logicTestWithTestBundleID:testBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities collectCoverage:collectCoverage collectLogs:collectLogs]; } case idb::XctestRunRequest_Mode::kApplication: { const idb::XctestRunRequest::Application application = request->mode().application(); @@ -1023,12 +1024,12 @@ static void populate_companion_info(idb::CompanionInfo *info, idreport_attachments() queue:_target.workQueue logger:_target.logger]; FBIDBTestOperation *operation = [[_commandExecutor xctest_run:xctestRunRequest reporter:reporter logger:[FBControlCoreLogger loggerToConsumer:reporter]] block:&error]; - reporter.resultBundlePath = operation.resultBundlePath; - reporter.coveragePath = operation.coveragePath; - reporter.binaryPath = operation.binaryPath; if (!operation) { return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); } + reporter.resultBundlePath = operation.resultBundlePath; + reporter.coveragePath = operation.coveragePath; + reporter.binaryPath = operation.binaryPath; // First wait for the test operation to finish [operation.completed block:&error]; // Then make sure we've reported everything, otherwise we could write in the background (use-after-free) diff --git a/idb_companion/Utility/FBIDBXCTestReporter.h b/idb_companion/Utility/FBIDBXCTestReporter.h index 6c58cae4c..94404d5f5 100644 --- a/idb_companion/Utility/FBIDBXCTestReporter.h +++ b/idb_companion/Utility/FBIDBXCTestReporter.h @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN Bridges from the FBXCTestReporter protocol to a GRPC result writer. This also keeps track of the terminal condition of the reporter, so this can be used to know when reporting has fully terminated. */ -@interface FBIDBXCTestReporter : NSObject +@interface FBIDBXCTestReporter : NSObject #pragma mark Initializers @@ -51,6 +51,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, copy, nullable, readwrite) NSString *coveragePath; +/** + Log directory path + */ +@property (nonatomic, copy, nullable, readwrite) NSString *logDirectoryPath; + /** App binary path */ diff --git a/idb_companion/Utility/FBIDBXCTestReporter.mm b/idb_companion/Utility/FBIDBXCTestReporter.mm index d47fcf0f8..88896c0e0 100644 --- a/idb_companion/Utility/FBIDBXCTestReporter.mm +++ b/idb_companion/Utility/FBIDBXCTestReporter.mm @@ -347,6 +347,19 @@ - (void)insertFinalDataThenWriteResponse:(const idb::XctestRunResponse &)respons return [FBFuture futureWithResult:NSNull.null]; }]]; } + if (self.logDirectoryPath) { + [futures addObject:[[self getLogDirectoryData] onQueue:self.queue chain:^FBFuture *(FBFuture *future) { + NSData *data = future.result; + if (data) { + idb::Payload *payload = responseCaptured.mutable_log_directory(); + payload->set_data(data.bytes, data.length); + } else { + [self.logger.info logFormat:@"Failed to get log drectory %@", future]; + } + return [FBFuture futureWithResult:NSNull.null]; + }]]; + + } if (futures.count == 0) { [self writeResponseFinal:responseCaptured]; return; @@ -363,7 +376,7 @@ - (void)writeResponseFinal:(const idb::XctestRunResponse &)response { // Break out if the terminating condition happens twice. if (self.reportingTerminated.hasCompleted || self.writer == nil) { - [self.logger.error log:@"writeResponse called, but the last response has already be written!!"]; + [self.logger.error log:@"writeResponse called, but the last response has already been written!!"]; return; } @@ -406,5 +419,10 @@ - (void)writeResponseFinal:(const idb::XctestRunResponse &)response return [FBArchiveOperations createGzippedTarDataForPath:self.resultBundlePath queue:self.queue logger:self.logger]; } +-(FBFuture *)getLogDirectoryData +{ + return [FBArchiveOperations createGzippedTarDataForPath:self.logDirectoryPath queue:self.queue logger:self.logger]; + +} @end diff --git a/idb_companion/Utility/FBXCTestDescriptor.h b/idb_companion/Utility/FBXCTestDescriptor.h index 9a4d7fd33..8ce5a969c 100644 --- a/idb_companion/Utility/FBXCTestDescriptor.h +++ b/idb_companion/Utility/FBXCTestDescriptor.h @@ -59,7 +59,7 @@ NS_ASSUME_NONNULL_BEGIN @param collectCoverage will collect llvm coverage data @return an FBXCTestRunRequest instance. */ -+ (instancetype)logicTestWithTestBundleID:(NSString *)testBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities collectCoverage:(BOOL)collectCoverage; ++ (instancetype)logicTestWithTestBundleID:(NSString *)testBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities collectCoverage:(BOOL)collectCoverage collectLogs:(BOOL)collectLogs; /** The Initializer for App Tests. @@ -157,6 +157,11 @@ The Initializer for UI Tests. */ @property (nonatomic, assign, readonly) BOOL collectCoverage; +/** + If set tests' output logs will be collected + */ +@property (nonatomic, assign, readonly) BOOL collectLogs; + /** Starts the test operation. diff --git a/idb_companion/Utility/FBXCTestDescriptor.m b/idb_companion/Utility/FBXCTestDescriptor.m index add2c875e..bb7c5339a 100644 --- a/idb_companion/Utility/FBXCTestDescriptor.m +++ b/idb_companion/Utility/FBXCTestDescriptor.m @@ -106,7 +106,7 @@ - (BOOL)isUITest return NO; } -- (FBFuture *)startWithTestDescriptor:(id)testDescriptor target:(id)target reporter:(id)reporter logger:(id)logger temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory +- (FBFuture *)startWithTestDescriptor:(id)testDescriptor target:(id)target reporter:(id)reporter logger:(id)logger temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory { return [[FBXCTestShimConfiguration defaultShimConfigurationWithLogger:logger] @@ -116,6 +116,17 @@ - (BOOL)isUITest if (![NSFileManager.defaultManager createDirectoryAtURL:workingDirectory withIntermediateDirectories:YES attributes:nil error:&error]) { return [FBFuture futureWithError:error]; } + + NSString *logDirectoryPath = nil; + if (self.collectLogs) { + NSURL *dir = [temporaryDirectory ephemeralTemporaryDirectory]; + if (![NSFileManager.defaultManager createDirectoryAtURL:dir withIntermediateDirectories:YES attributes:nil error:&error]) { + return [FBFuture futureWithError:error]; + } + logDirectoryPath = dir.path; + [reporter setLogDirectoryPath:logDirectoryPath]; + } + NSString *testFilter = nil; NSArray *testsToSkip = self.testsToSkip.allObjects ?: @[]; if (testsToSkip.count > 0) { @@ -136,6 +147,7 @@ - (BOOL)isUITest configurationWithShims:shims environment:self.environment workingDirectory:workingDirectory.path + logDirectoryPath:logDirectoryPath testBundlePath:testDescriptor.testBundle.path waitForDebugger:NO timeout:timeout @@ -146,7 +158,7 @@ - (BOOL)isUITest }]; } -- (FBFuture *)startTestExecution:(FBLogicTestConfiguration *)configuration target:(id)target reporter:(id)reporter logger:(id)logger +- (FBFuture *)startTestExecution:(FBLogicTestConfiguration *)configuration target:(id)target reporter:(id)reporter logger:(id)logger { return [[self executorWithConfiguration:configuration target:target] @@ -157,7 +169,7 @@ - (BOOL)isUITest if (completed.error) { return [FBFuture futureWithError:completed.error]; } - FBIDBTestOperation *operation = [[FBIDBTestOperation alloc] initWithConfiguration:configuration resultBundlePath:nil coveragePath:nil binaryPath:nil reporter:reporter logger:logger completed:completed queue:target.workQueue]; + FBIDBTestOperation *operation = [[FBIDBTestOperation alloc] initWithConfiguration:configuration resultBundlePath:nil coveragePath:nil binaryPath:nil reporter:reporter logger:logger completed:completed queue:target.workQueue]; return [FBFuture futureWithResult:operation]; }]; } @@ -197,7 +209,7 @@ - (BOOL)isUITest return NO; } -- (FBFuture *)startWithTestDescriptor:(id)testDescriptor target:(id)target reporter:(id)reporter logger:(id)logger temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory +- (FBFuture *)startWithTestDescriptor:(id)testDescriptor target:(id)target reporter:(id)reporter logger:(id)logger temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory { return [[FBXCTestShimConfiguration defaultShimConfigurationWithLogger:logger] @@ -270,22 +282,22 @@ @implementation FBXCTestRunRequest #pragma mark Initializers -+ (instancetype)logicTestWithTestBundleID:(NSString *)testBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities collectCoverage:(BOOL)collectCoverage ++ (instancetype)logicTestWithTestBundleID:(NSString *)testBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities collectCoverage:(BOOL)collectCoverage collectLogs:(BOOL)collectLogs { - return [[FBXCTestRunRequest_LogicTest alloc] initWithTestBundleID:testBundleID appBundleID:nil testHostAppBundleID:nil environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities collectCoverage:collectCoverage]; + return [[FBXCTestRunRequest_LogicTest alloc] initWithTestBundleID:testBundleID appBundleID:nil testHostAppBundleID:nil environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities collectCoverage:collectCoverage collectLogs:collectLogs]; } + (instancetype)applicationTestWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities collectCoverage:(BOOL)collectCoverage { - return [[FBXCTestRunRequest_AppTest alloc] initWithTestBundleID:testBundleID appBundleID:appBundleID testHostAppBundleID:nil environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities collectCoverage:collectCoverage]; + return [[FBXCTestRunRequest_AppTest alloc] initWithTestBundleID:testBundleID appBundleID:appBundleID testHostAppBundleID:nil environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities collectCoverage:collectCoverage collectLogs:NO]; } + (instancetype)uiTestWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID testHostAppBundleID:(NSString *)testHostAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities collectCoverage:(BOOL)collectCoverage { - return [[FBXCTestRunRequest_UITest alloc] initWithTestBundleID:testBundleID appBundleID:appBundleID testHostAppBundleID:testHostAppBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities collectCoverage:collectCoverage]; + return [[FBXCTestRunRequest_UITest alloc] initWithTestBundleID:testBundleID appBundleID:appBundleID testHostAppBundleID:testHostAppBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities collectCoverage:collectCoverage collectLogs:NO]; } -- (instancetype)initWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID testHostAppBundleID:(NSString *)testHostAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities collectCoverage:(BOOL)collectCoverage +- (instancetype)initWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID testHostAppBundleID:(NSString *)testHostAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities collectCoverage:(BOOL)collectCoverage collectLogs:(BOOL)collectLogs { self = [super init]; if (!self) { @@ -302,6 +314,7 @@ - (instancetype)initWithTestBundleID:(NSString *)testBundleID appBundleID:(NSStr _testTimeout = testTimeout; _reportActivities = reportActivities; _collectCoverage = collectCoverage; + _collectLogs = collectLogs; return self; } @@ -316,7 +329,7 @@ - (BOOL)isUITest return NO; } -- (FBFuture *)startWithBundleStorageManager:(FBXCTestBundleStorage *)bundleStorage target:(id)target reporter:(id)reporter logger:(id)logger temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory +- (FBFuture *)startWithBundleStorageManager:(FBXCTestBundleStorage *)bundleStorage target:(id)target reporter:(id)reporter logger:(id)logger temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory { return [[self fetchAndSetupDescriptorWithBundleStorage:bundleStorage target:target] @@ -325,7 +338,7 @@ - (BOOL)isUITest }]; } -- (FBFuture *)startWithTestDescriptor:(id)testDescriptor target:(id)target reporter:(id)reporter logger:(id)logger temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory +- (FBFuture *)startWithTestDescriptor:(id)testDescriptor target:(id)target reporter:(id)reporter logger:(id)logger temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory { return [[FBIDBError describeFormat:@"%@ not implemented in abstract base class", NSStringFromSelector(_cmd)]