This commit is contained in:
lawrencelomax 2015-12-29 17:39:10 +00:00
Родитель 0d7822c6dc
Коммит 0433ffe32d
20 изменённых файлов: 293 добавлений и 165 удалений

Просмотреть файл

@ -34,7 +34,7 @@
AA1D653F1C21A9690069F90D /* FBCollectionDescriptions.m in Sources */ = {isa = PBXBuildFile; fileRef = AA1D653D1C21A9690069F90D /* FBCollectionDescriptions.m */; };
AA1D65421C21B38D0069F90D /* FBCrashLogInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = AA1D65401C21B38D0069F90D /* FBCrashLogInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
AA1D65431C21B38D0069F90D /* FBCrashLogInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = AA1D65411C21B38D0069F90D /* FBCrashLogInfo.m */; };
AA1D65461C21CD2A0069F90D /* FBASLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = AA1D65441C21CD2A0069F90D /* FBASLParser.h */; };
AA1D65461C21CD2A0069F90D /* FBASLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = AA1D65441C21CD2A0069F90D /* FBASLParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
AA1D65471C21CD2A0069F90D /* FBASLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = AA1D65451C21CD2A0069F90D /* FBASLParser.m */; };
AA3230CB1BDA387700C5BA01 /* FBSimulatorControlAssertions.m in Sources */ = {isa = PBXBuildFile; fileRef = AA3230CA1BDA387700C5BA01 /* FBSimulatorControlAssertions.m */; };
AA5639551C060005009BAFAA /* FBSimulatorControl.h in Headers */ = {isa = PBXBuildFile; fileRef = AA5639541C05FFF5009BAFAA /* FBSimulatorControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -166,6 +166,8 @@
AACA2C381C2976B100979C45 /* FBAddVideoPolyfill.m in Sources */ = {isa = PBXBuildFile; fileRef = AACA2C361C2976B100979C45 /* FBAddVideoPolyfill.m */; };
AAD3051F1BD4D5B10047376E /* photo0.png in Resources */ = {isa = PBXBuildFile; fileRef = AAD3051D1BD4D5B10047376E /* photo0.png */; };
AAD305201BD4D5B10047376E /* photo1.png in Resources */ = {isa = PBXBuildFile; fileRef = AAD3051E1BD4D5B10047376E /* photo1.png */; };
AAF2D3561C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.h in Headers */ = {isa = PBXBuildFile; fileRef = AAF2D3541C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.h */; settings = {ATTRIBUTES = (Public, ); }; };
AAF2D3571C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF2D3551C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.m */; };
AAF8DA651C1AFF81003B519E /* FBProcessInfo+Helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = AAF8DA631C1AFF81003B519E /* FBProcessInfo+Helpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
AAF8DA661C1AFF81003B519E /* FBProcessInfo+Helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF8DA641C1AFF81003B519E /* FBProcessInfo+Helpers.m */; };
AAF8DA691C1AFFB1003B519E /* FBProcessInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = AAF8DA671C1AFFB1003B519E /* FBProcessInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -946,6 +948,8 @@
AACA2C361C2976B100979C45 /* FBAddVideoPolyfill.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBAddVideoPolyfill.m; sourceTree = "<group>"; };
AAD3051D1BD4D5B10047376E /* photo0.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = photo0.png; sourceTree = "<group>"; };
AAD3051E1BD4D5B10047376E /* photo1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = photo1.png; sourceTree = "<group>"; };
AAF2D3541C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FBSimulatorInteraction+Lifecycle.h"; sourceTree = "<group>"; };
AAF2D3551C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FBSimulatorInteraction+Lifecycle.m"; sourceTree = "<group>"; };
AAF8DA631C1AFF81003B519E /* FBProcessInfo+Helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FBProcessInfo+Helpers.h"; sourceTree = "<group>"; };
AAF8DA641C1AFF81003B519E /* FBProcessInfo+Helpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FBProcessInfo+Helpers.m"; sourceTree = "<group>"; };
AAF8DA671C1AFFB1003B519E /* FBProcessInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBProcessInfo.h; sourceTree = "<group>"; };
@ -1727,15 +1731,19 @@
AA9516DE1C15F54600A89CAD /* Interactions */ = {
isa = PBXGroup;
children = (
AA9516DF1C15F54600A89CAD /* FBInteraction+Private.h */,
AA9516E01C15F54600A89CAD /* FBInteraction.h */,
AA9516E11C15F54600A89CAD /* FBInteraction.m */,
AA9516DF1C15F54600A89CAD /* FBInteraction+Private.h */,
AA9516F11C15F54600A89CAD /* FBSimulatorInteraction.h */,
AA9516F21C15F54600A89CAD /* FBSimulatorInteraction.m */,
AA9516E21C15F54600A89CAD /* FBSimulatorInteraction+Agents.h */,
AA9516E31C15F54600A89CAD /* FBSimulatorInteraction+Agents.m */,
AA9516E41C15F54600A89CAD /* FBSimulatorInteraction+Applications.h */,
AA9516E51C15F54600A89CAD /* FBSimulatorInteraction+Applications.m */,
AA9516E81C15F54600A89CAD /* FBSimulatorInteraction+Diagnostics.h */,
AA9516E91C15F54600A89CAD /* FBSimulatorInteraction+Diagnostics.m */,
AAF2D3541C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.h */,
AAF2D3551C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.m */,
AA9516EA1C15F54600A89CAD /* FBSimulatorInteraction+Private.h */,
AA9516EB1C15F54600A89CAD /* FBSimulatorInteraction+Setup.h */,
AA9516EC1C15F54600A89CAD /* FBSimulatorInteraction+Setup.m */,
@ -1743,8 +1751,6 @@
AA9516EE1C15F54600A89CAD /* FBSimulatorInteraction+Upload.m */,
AA9516EF1C15F54600A89CAD /* FBSimulatorInteraction+Video.h */,
AA9516F01C15F54600A89CAD /* FBSimulatorInteraction+Video.m */,
AA9516F11C15F54600A89CAD /* FBSimulatorInteraction.h */,
AA9516F21C15F54600A89CAD /* FBSimulatorInteraction.m */,
);
path = Interactions;
sourceTree = "<group>";
@ -1973,7 +1979,6 @@
AA9517851C15F54600A89CAD /* FBSimulatorPool.h in Headers */,
AA9517621C15F54600A89CAD /* FBInteraction+Private.h in Headers */,
AA9517511C15F54600A89CAD /* FBSimulatorConfiguration.h in Headers */,
AA1D65461C21CD2A0069F90D /* FBASLParser.h in Headers */,
AA0771F11C1ADFA300E7FD52 /* FBBinaryParser.h in Headers */,
AA9517471C15F54600A89CAD /* FBProcessLaunchConfiguration+Helpers.h in Headers */,
AA9517BE1C15F54600A89CAD /* FBSimulatorVideoRecorder.h in Headers */,
@ -2025,6 +2030,8 @@
AA9517841C15F54600A89CAD /* FBSimulatorPool+Private.h in Headers */,
AACA2C371C2976B100979C45 /* FBAddVideoPolyfill.h in Headers */,
AA9517A51C15F54600A89CAD /* FBTask.h in Headers */,
AA1D65461C21CD2A0069F90D /* FBASLParser.h in Headers */,
AAF2D3561C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.h in Headers */,
AA95179D1C15F54600A89CAD /* FBProcessQuery.h in Headers */,
AA9517A11C15F54600A89CAD /* FBSimulatorSession+Private.h in Headers */,
AA9517871C15F54600A89CAD /* FBSimulatorPredicates.h in Headers */,
@ -2180,6 +2187,7 @@
AA9517A31C15F54600A89CAD /* FBSimulatorSession.m in Sources */,
AA9517BF1C15F54600A89CAD /* FBSimulatorVideoRecorder.m in Sources */,
AA95178F1C15F54600A89CAD /* FBSimulatorApplication.m in Sources */,
AAF2D3571C33EA3100434516 /* FBSimulatorInteraction+Lifecycle.m in Sources */,
AA95174F1C15F54600A89CAD /* FBSimulatorConfiguration+CoreSimulator.m in Sources */,
AAF8DA661C1AFF81003B519E /* FBProcessInfo+Helpers.m in Sources */,
AA9517B71C15F54600A89CAD /* FBSimDeviceWrapper.m in Sources */,

Просмотреть файл

@ -8,6 +8,7 @@
*/
#import <FBSimulatorControl/FBAddVideoPolyfill.h>
#import <FBSimulatorControl/FBASLParser.h>
#import <FBSimulatorControl/FBBinaryParser.h>
#import <FBSimulatorControl/FBCollectionDescriptions.h>
#import <FBSimulatorControl/FBCompositeSimulatorEventSink.h>
@ -47,6 +48,7 @@
#import <FBSimulatorControl/FBSimulatorInteraction+Agents.h>
#import <FBSimulatorControl/FBSimulatorInteraction+Applications.h>
#import <FBSimulatorControl/FBSimulatorInteraction+Diagnostics.h>
#import <FBSimulatorControl/FBSimulatorInteraction+Lifecycle.h>
#import <FBSimulatorControl/FBSimulatorInteraction+Private.h>
#import <FBSimulatorControl/FBSimulatorInteraction+Setup.h>
#import <FBSimulatorControl/FBSimulatorInteraction+Upload.h>

Просмотреть файл

@ -20,6 +20,7 @@
Chains an interaction using the provided block
@param block the block to perform the interaction with. Passes an NSError to return error information and the interaction for further chaining.
@return the reciever, for chaining.
*/
- (instancetype)interact:(BOOL (^)(NSError **error, id interaction))block;
@ -27,11 +28,14 @@
Fails the Interaction with the provided error.
@param error the error to fail the interaction with.
@return the reciever, for chaining.
*/
- (instancetype)failWith:(NSError *)error;
/**
Passes the interaction.
@return the reciever, for chaining.
*/
- (instancetype)succeed;

Просмотреть файл

@ -33,11 +33,16 @@
/**
Retries the last chained interaction by `retries`, if it fails.
@param retries the number of times to retry if the prior interaction fails.
@return the reciever, for chaining.
*/
- (instancetype)retry:(NSUInteger)retries;
/**
Ignores any failure that occurs in the last interaction if any occured.
@return the reciever, for chaining.
*/
- (instancetype)ignoreFailure;

Просмотреть файл

@ -16,11 +16,17 @@
/**
Launches the provided Agent with the given Configuration.
@param agentLaunch the Agent Launch Configuration to Launch.
@return the reciever, for chaining.
*/
- (instancetype)launchAgent:(FBAgentLaunchConfiguration *)agentLaunch;
/**
Launches the provided Agent.
@param agent the Agent Launch Configuration to Launch.
@return the reciever, for chaining.
*/
- (instancetype)killAgent:(FBSimulatorBinary *)agent;

Просмотреть файл

@ -32,9 +32,7 @@
{
NSParameterAssert(agentLaunch);
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
NSError *innerError = nil;
NSFileHandle *stdOut = nil;
NSFileHandle *stdErr = nil;
@ -66,9 +64,7 @@
{
NSParameterAssert(agent);
FBSimulator *simulator = self.simulator;
return [self binary:agent interact:^ BOOL (FBProcessInfo *process, NSError **error) {
return [self binary:agent interact:^ BOOL (NSError **error, FBSimulator *simulator, FBProcessInfo *process) {
if (!kill(process.processIdentifier, SIGKILL)) {
return [[[FBSimulatorError describeFormat:@"SIGKILL of Agent %@ of PID %d failed", agent, process.processIdentifier] inSimulator:simulator] failBool:error];
}

Просмотреть файл

@ -15,21 +15,33 @@
/**
Installs the given Application.
@param application the Application to Install.
@return the reciever, for chaining.
*/
- (instancetype)installApplication:(FBSimulatorApplication *)application;
/**
Launches the Application with the given Configuration.
@param appLaunch the Application Launch Configuration to Launch.
@return the reciever, for chaining.
*/
- (instancetype)launchApplication:(FBApplicationLaunchConfiguration *)appLaunch;
/**
Unix Signals the Application.
@param signal the unix signo to send.
@return the reciever, for chaining.
*/
- (instancetype)signal:(int)signal application:(FBSimulatorApplication *)application;
/**
Kills the provided Application.
@param application the Application to kill.
@return the reciever, for chaining.
*/
- (instancetype)killApplication:(FBSimulatorApplication *)application;

Просмотреть файл

@ -32,9 +32,7 @@
{
NSParameterAssert(application);
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
NSError *innerError = nil;
if (![simulator.simDeviceWrapper installApplication:[NSURL fileURLWithPath:application.path] withOptions:@{@"CFBundleIdentifier" : application.bundleID} error:error]) {
return [[[FBSimulatorError describeFormat:@"Failed to install Application %@", application] causedBy:innerError] failBool:error];
@ -48,9 +46,7 @@
{
NSParameterAssert(appLaunch);
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
NSError *innerError = nil;
NSDictionary *installedApps = [simulator.device installedAppsWithError:&innerError];
if (!installedApps) {
@ -93,9 +89,7 @@
{
NSParameterAssert(application);
FBSimulator *simulator = self.simulator;
return [self binary:application.binary interact:^ BOOL (FBProcessInfo *process, NSError **error) {
return [self binary:application.binary interact:^ BOOL (NSError **error, FBSimulator *simulator, FBProcessInfo *process) {
[simulator.eventSink applicationDidTerminate:process expected:YES];
int returnCode = kill(process.processIdentifier, signo);
if (returnCode != 0) {

Просмотреть файл

@ -52,9 +52,7 @@ typedef id<FBTask>(^FBDiagnosticTaskFactory)(FBTaskExecutor *executor, pid_t pro
NSParameterAssert(application);
NSParameterAssert(name);
FBSimulator *simulator = self.simulator;
return [self binary:application.binary interact:^ BOOL (FBProcessInfo *process, NSError **error) {
return [self binary:application.binary interact:^ BOOL (NSError **error, FBSimulator *simulator, FBProcessInfo *process) {
id<FBTask> task = taskFactory(FBTaskExecutor.sharedInstance, process.processIdentifier);
NSCAssert(task, @"Task should not be nil");
@ -78,9 +76,7 @@ typedef id<FBTask>(^FBDiagnosticTaskFactory)(FBTaskExecutor *executor, pid_t pro
NSParameterAssert(application);
NSParameterAssert(name);
FBSimulator *simulator = self.simulator;
return [self binary:application.binary interact:^ BOOL (FBProcessInfo *process, NSError **error) {
return [self binary:application.binary interact:^ BOOL (NSError **error, FBSimulator *simulator, FBProcessInfo *process) {
id<FBTask> task = taskFactory(FBTaskExecutor.sharedInstance, process.processIdentifier);
NSCAssert(task, @"Task should not be nil");

Просмотреть файл

@ -0,0 +1,41 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
#import <FBSimulatorControl/FBSimulatorInteraction.h>
/**
Interactions for the Lifecycle of the Simulator.
*/
@interface FBSimulatorInteraction (Lifecycle)
/**
Boots the Simulator.
@return the reciever, for chaining.
*/
- (instancetype)bootSimulator;
/**
Shuts the Simulator down.
@return the reciever, for chaining.
*/
- (instancetype)shutdownSimulator;
/**
Opens the provided URL on the Simulator.
@param url the URL to open.
@return the reciever, for chaining.
*/
- (instancetype)openURL:(NSURL *)url;
@end

Просмотреть файл

@ -0,0 +1,140 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "FBSimulatorInteraction+Lifecycle.h"
#import <CoreSimulator/SimDevice.h>
#import "FBSimulatorInteraction+Private.h"
#import "FBCollectionDescriptions.h"
#import "FBInteraction+Private.h"
#import "FBProcessLaunchConfiguration.h"
#import "FBProcessQuery+Simulators.h"
#import "FBSimulator+Helpers.h"
#import "FBSimulator.h"
#import "FBSimulatorApplication.h"
#import "FBSimulatorConfiguration+CoreSimulator.h"
#import "FBSimulatorConfiguration.h"
#import "FBSimulatorControl.h"
#import "FBSimulatorControlConfiguration.h"
#import "FBSimulatorControlGlobalConfiguration.h"
#import "FBSimulatorError.h"
#import "FBSimulatorEventSink.h"
#import "FBSimulatorLaunchInfo.h"
#import "FBSimulatorPool.h"
#import "FBSimulatorSession+Private.h"
#import "FBSimulatorTerminationStrategy.h"
#import "FBTaskExecutor.h"
@implementation FBSimulatorInteraction (Lifecycle)
- (instancetype)bootSimulator
{
return [self interactWithShutdownSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
// Construct the Arguments
NSMutableArray *arguments = [NSMutableArray arrayWithArray:@[
@"--args",
@"-CurrentDeviceUDID", simulator.udid,
@"-ConnectHardwareKeyboard", @"0"
]];
NSArray *scaleArguments = [simulator.configuration lastScaleCommandLineArgumentsWithError:nil];
if (scaleArguments) {
[arguments addObjectsFromArray:scaleArguments];
}
if (simulator.pool.configuration.deviceSetPath) {
if (!FBSimulatorControlGlobalConfiguration.supportsCustomDeviceSets) {
return [[[FBSimulatorError describe:@"Cannot use custom Device Set on current platform"] inSimulator:simulator] failBool:error];
}
[arguments addObjectsFromArray:@[@"-DeviceSetPath", simulator.pool.configuration.deviceSetPath]];
}
// Construct and start the task.
id<FBTask> task = [[[[[FBTaskExecutor.sharedInstance
withLaunchPath:FBSimulatorApplication.simulatorApplication.binary.path]
withArguments:[arguments copy]]
withEnvironmentAdditions:@{ FBSimulatorControlSimulatorLaunchEnvironmentSimulatorUDID : simulator.udid }]
build]
startAsynchronously];
// Expect no immediate error.
if (task.error) {
return [[[[FBSimulatorError describe:@"Failed to Launch Simulator Process"] causedBy:task.error] inSimulator:simulator] failBool:error];
}
// Expect the state of the simulator to be updated.
BOOL didBoot = [simulator waitOnState:FBSimulatorStateBooted];
if (!didBoot) {
return [[[FBSimulatorError describeFormat:@"Timed out waiting for device to be Booted, got %@", simulator.device.stateString] inSimulator:simulator] failBool:error];
}
// Expect the launch info for the process to exist.
FBSimulatorLaunchInfo *launchInfo = [FBSimulatorLaunchInfo fromSimDevice:simulator.device query:simulator.processQuery];
if (!launchInfo) {
return [[[FBSimulatorError describe:@"Could not obtain process info for booted simulator process"] inSimulator:simulator] failBool:error];
}
// Waitng for all required processes to start
NSSet *requiredProcessNames = simulator.requiredProcessNamesToVerifyBooted;
BOOL didStartAllRequiredProcesses = [NSRunLoop.mainRunLoop spinRunLoopWithTimeout:FBSimulatorControlGlobalConfiguration.slowTimeout untilTrue:^ BOOL {
NSSet *runningProcessNames = [NSSet setWithArray:[launchInfo.launchedProcesses valueForKey:@"processName"]];
return [requiredProcessNames isSubsetOfSet:runningProcessNames];
}];
if (!didStartAllRequiredProcesses) {
return [[[FBSimulatorError
describeFormat:@"Timed out waiting for all required processes %@ to start", [FBCollectionDescriptions oneLineDescriptionFromArray:requiredProcessNames.allObjects]]
inSimulator:simulator]
failBool:error];
}
// Pass on the success to the event sink.
[simulator.eventSink didStartWithLaunchInfo:launchInfo];
[simulator.eventSink terminationHandleAvailable:task];
return YES;
}];
}
- (instancetype)shutdownSimulator
{
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
FBSimulatorLaunchInfo *launchInfo = simulator.launchInfo;
if (!launchInfo) {
return [[[FBSimulatorError describe:@"Could not shutdown simulator as there is no available launch info"] inSimulator:simulator] failBool:error];
}
FBSimulatorTerminationStrategy *terminationStrategy = [FBSimulatorTerminationStrategy
withConfiguration:simulator.pool.configuration
processQuery:simulator.processQuery
logger:simulator.pool.logger];
NSError *innerError = nil;
if (![terminationStrategy killSimulators:@[simulator] withError:&innerError]) {
return [[[[FBSimulatorError describe:@"Could not shutdown simulator"] inSimulator:simulator] causedBy:innerError] failBool:error];
}
[simulator.eventSink didTerminate:YES];
return YES;
}];
}
- (instancetype)openURL:(NSURL *)url
{
NSParameterAssert(url);
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
NSError *innerError = nil;
if (![simulator.device openURL:url error:&innerError]) {
NSString *description = [NSString stringWithFormat:@"Failed to open URL %@ on simulator %@", url, simulator];
return [FBSimulatorError failBoolWithError:innerError description:description errorOut:error];
}
return YES;
}];
}
@end

Просмотреть файл

@ -18,7 +18,27 @@
/**
Chains an interaction on an process, for the given application.
@param binary the binary to interact with.
@param block the block to execute with the process.
@return the reciever, for chaining.
*/
- (instancetype)binary:(FBSimulatorBinary *)binary interact:(BOOL (^)(FBProcessInfo *process, NSError **error))block;
- (instancetype)binary:(FBSimulatorBinary *)binary interact:(BOOL (^)(NSError **error, FBSimulator *simulator, FBProcessInfo *process))block;
/**
Interact with a Shutdown Simulator. Will ensure that the Simulator is in the appropriate state.
@param block the block to execute with the Shutdown Simulator.
@return the reciever, for chaining.
*/
- (instancetype)interactWithShutdownSimulator:(BOOL (^)(NSError **error, FBSimulator *simulator))block;
/**
Interact with a Shutdown Simulator. Will ensure that the Simulator is in the appropriate state.s
@param block the block to execute with the Shutdown Simulator.
@return the reciever, for chaining.
*/
- (instancetype)interactWithBootedSimulator:(BOOL (^)(NSError **error, FBSimulator *simulator))block;
@end

Просмотреть файл

@ -15,6 +15,7 @@
Sets the locale for the simulator.
@param locale the locale to set, must not be nil.
@return the reciever, for chaining.
*/
- (instancetype)setLocale:(NSLocale *)locale;
@ -22,14 +23,17 @@
Authorizes the Location Settings for the provided application.
@param application the Application to authorize settings for.
@return the reciever, for chaining.
*/
- (instancetype)authorizeLocationSettingsForApplication:(FBSimulatorApplication *)application;
/**
Setups keyboard for simulator
Prepares the Simulator Keyboard, prior to launch.
1) Disables Caps Lock
2) Disables Auto Capitalize
3) Disables Auto Correction / QuickType
@return the reciever, for chaining.
*/
- (instancetype)setupKeyboard;

Просмотреть файл

@ -23,9 +23,7 @@
{
NSParameterAssert(locale);
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithShutdownSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
NSString *localeIdentifier = [locale localeIdentifier];
NSString *languageIdentifier = [NSLocale canonicalLanguageIdentifierFromString:localeIdentifier];
NSDictionary *preferencesDict = @{
@ -47,9 +45,7 @@
{
NSParameterAssert(application);
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithShutdownSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
NSString *simulatorRoot = simulator.device.dataPath;
NSString *bundleID = application.bundleID;
@ -81,9 +77,7 @@
- (instancetype)setupKeyboard
{
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithShutdownSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
NSString *simulatorRoot = simulator.device.dataPath;
NSString *preferencesPath = [simulatorRoot stringByAppendingPathComponent:@"Library/Preferences/com.apple.Preferences.plist"];
NSError *innerError = nil;

Просмотреть файл

@ -15,6 +15,7 @@
Uploads photos to the Camera Roll of the Simulator
@param photoPaths photoPaths an NSArray<NSString *> of File Paths for the Photos to Upload.
@return the reciever, for chaining.
*/
- (instancetype)uploadPhotos:(NSArray *)photoPaths;
@ -22,6 +23,7 @@
Uploads videos to the Camera Roll of the Simulator
@param videoPaths an NSArray<NSString *> of File Paths for the Videos to Upload.
@return the reciever, for chaining.
*/
- (instancetype)uploadVideos:(NSArray *)videoPaths;

Просмотреть файл

@ -32,9 +32,7 @@
return [self succeed];
}
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
if (simulator.state != FBSimulatorStateBooted) {
return [[FBSimulatorError describeFormat:@"Simulator must be booted to upload photos, is %@", simulator.device.stateString] failBool:error];
}
@ -57,8 +55,7 @@
return [self succeed];
}
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
NSError *innerError = nil;
BOOL success = [simulator.simDeviceWrapper addVideos:videoPaths error:&innerError];
if (!success) {

Просмотреть файл

@ -15,16 +15,23 @@
/**
Tiles the Simulator according to the 'tilingStrategy'.
@param tilingStrategy the Tiling Strategy to use.
@return the reciever, for chaining.
*/
- (instancetype)tileSimulator:(id<FBSimulatorWindowTilingStrategy>)tilingStrategy;
/**
Tiles the Simulator according to the occlusion other Simulators.
@return the reciever, for chaining.
*/
- (instancetype)tileSimulator;
/**
Records Video of the Simulator, until the Session is terminated.
@return the reciever, for chaining.
*/
- (instancetype)recordVideo;

Просмотреть файл

@ -24,9 +24,7 @@
{
NSParameterAssert(tilingStrategy);
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
FBSimulatorWindowTiler *tiler = [FBSimulatorWindowTiler withSimulator:simulator strategy:tilingStrategy];
NSError *innerError = nil;
if (CGRectIsNull([tiler placeInForegroundWithError:&innerError])) {
@ -43,9 +41,7 @@
- (instancetype)recordVideo
{
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
FBSimulatorVideoRecorder *recorder = [FBSimulatorVideoRecorder forSimulator:simulator logger:nil];
NSString *path = [simulator pathForStorage:@"video" ofExtension:@"mp4"];

Просмотреть файл

@ -18,7 +18,7 @@
@class FBSimulatorSessionLifecycle;
/**
Pre-session interactions used pre-launch of a Simulator
Interactions for FBSimulator Instances.
*/
@interface FBSimulatorInteraction : FBInteraction
@ -29,19 +29,4 @@
*/
+ (instancetype)withSimulator:(FBSimulator *)simulator;
/**
Boots the Simulator.
*/
- (instancetype)bootSimulator;
/**
Shuts the Simulator down.
*/
- (instancetype)shutdownSimulator;
/**
Opens the provided URL on the Device
*/
- (instancetype)openURL:(NSURL *)url;
@end

Просмотреть файл

@ -41,125 +41,44 @@
return interaction;
}
- (instancetype)bootSimulator
#pragma mark Private
- (instancetype)interactWithSimulator:(BOOL (^)(NSError **error, FBSimulator *simulator))block
{
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, FBSimulatorInteraction *interaction) {
return block(error, interaction.simulator);
}];
}
return [self interact:^ BOOL (NSError **error, id _) {
// Construct the Arguments
NSMutableArray *arguments = [NSMutableArray arrayWithArray:@[
@"--args",
@"-CurrentDeviceUDID", simulator.udid,
@"-ConnectHardwareKeyboard", @"0"
]];
NSArray *scaleArguments = [simulator.configuration lastScaleCommandLineArgumentsWithError:nil];
if (scaleArguments) {
[arguments addObjectsFromArray:scaleArguments];
}
if (simulator.pool.configuration.deviceSetPath) {
if (!FBSimulatorControlGlobalConfiguration.supportsCustomDeviceSets) {
return [[[FBSimulatorError describe:@"Cannot use custom Device Set on current platform"] inSimulator:simulator] failBool:error];
}
[arguments addObjectsFromArray:@[@"-DeviceSetPath", simulator.pool.configuration.deviceSetPath]];
}
// Construct and start the task.
id<FBTask> task = [[[[[FBTaskExecutor.sharedInstance
withLaunchPath:FBSimulatorApplication.simulatorApplication.binary.path]
withArguments:[arguments copy]]
withEnvironmentAdditions:@{ FBSimulatorControlSimulatorLaunchEnvironmentSimulatorUDID : simulator.udid }]
build]
startAsynchronously];
// Expect no immediate error.
if (task.error) {
return [[[[FBSimulatorError describe:@"Failed to Launch Simulator Process"] causedBy:task.error] inSimulator:simulator] failBool:error];
}
// Expect the state of the simulator to be updated.
BOOL didBoot = [simulator waitOnState:FBSimulatorStateBooted];
if (!didBoot) {
return [[[FBSimulatorError describeFormat:@"Timed out waiting for device to be Booted, got %@", simulator.device.stateString] inSimulator:simulator] failBool:error];
}
// Expect the launch info for the process to exist.
FBSimulatorLaunchInfo *launchInfo = [FBSimulatorLaunchInfo fromSimDevice:simulator.device query:simulator.processQuery];
if (!launchInfo) {
return [[[FBSimulatorError describe:@"Could not obtain process info for booted simulator process"] inSimulator:simulator] failBool:error];
}
// Waitng for all required processes to start
NSSet *requiredProcessNames = simulator.requiredProcessNamesToVerifyBooted;
BOOL didStartAllRequiredProcesses = [NSRunLoop.mainRunLoop spinRunLoopWithTimeout:FBSimulatorControlGlobalConfiguration.slowTimeout untilTrue:^ BOOL {
NSSet *runningProcessNames = [NSSet setWithArray:[launchInfo.launchedProcesses valueForKey:@"processName"]];
return [requiredProcessNames isSubsetOfSet:runningProcessNames];
}];
if (!didStartAllRequiredProcesses) {
- (instancetype)interactWithSimulatorAtState:(FBSimulatorState)state block:(BOOL (^)(NSError **error, FBSimulator *simulator))block
{
return [self interactWithSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
if (simulator.state != state) {
return [[[FBSimulatorError
describeFormat:@"Timed out waiting for all required processes %@ to start", [FBCollectionDescriptions oneLineDescriptionFromArray:requiredProcessNames.allObjects]]
describeFormat:@"Expected Simulator %@ to be %@, but it was '%@'", simulator.udid, simulator.stateString, [FBSimulator stateStringFromSimulatorState:simulator.state]]
inSimulator:simulator]
failBool:error];
}
// Pass on the success to the event sink.
[simulator.eventSink didStartWithLaunchInfo:launchInfo];
[simulator.eventSink terminationHandleAvailable:task];
return YES;
return block(error, simulator);
}];
}
- (instancetype)shutdownSimulator
- (instancetype)interactWithShutdownSimulator:(BOOL (^)(NSError **error, FBSimulator *simulator))block
{
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
FBSimulatorLaunchInfo *launchInfo = simulator.launchInfo;
if (!launchInfo) {
return [[[FBSimulatorError describe:@"Could not shutdown simulator as there is no available launch info"] inSimulator:simulator] failBool:error];
}
FBSimulatorTerminationStrategy *terminationStrategy = [FBSimulatorTerminationStrategy
withConfiguration:simulator.pool.configuration
processQuery:simulator.processQuery
logger:simulator.pool.logger];
NSError *innerError = nil;
if (![terminationStrategy killSimulators:@[simulator] withError:&innerError]) {
return [[[[FBSimulatorError describe:@"Could not shutdown simulator"] inSimulator:simulator] causedBy:innerError] failBool:error];
}
[simulator.eventSink didTerminate:YES];
return YES;
}];
return [self interactWithSimulatorAtState:FBSimulatorStateShutdown block:block];
}
- (instancetype)openURL:(NSURL *)url
- (instancetype)interactWithBootedSimulator:(BOOL (^)(NSError **error, FBSimulator *simulator))block
{
NSParameterAssert(url);
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
NSError *innerError = nil;
if (![simulator.device openURL:url error:&innerError]) {
NSString *description = [NSString stringWithFormat:@"Failed to open URL %@ on simulator %@", url, simulator];
return [FBSimulatorError failBoolWithError:innerError description:description errorOut:error];
}
return YES;
}];
return [self interactWithSimulatorAtState:FBSimulatorStateBooted block:block];
}
#pragma mark Private
- (instancetype)binary:(FBSimulatorBinary *)binary interact:(BOOL (^)(FBProcessInfo *process, NSError **error))block
- (instancetype)binary:(FBSimulatorBinary *)binary interact:(BOOL (^)(NSError **error, FBSimulator *simulator, FBProcessInfo *process))block
{
NSParameterAssert(binary);
NSParameterAssert(block);
FBSimulator *simulator = self.simulator;
return [self interact:^ BOOL (NSError **error, id _) {
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
FBProcessInfo *processInfo = [[[[simulator
launchInfo]
launchedProcesses]
@ -169,7 +88,7 @@
if (!processInfo) {
return [[[FBSimulatorError describeFormat:@"Could not find an active process for %@", binary] inSimulator:simulator] failBool:error];
}
return block(processInfo, error);
return block(error, simulator, processInfo);
}];
}