From 9c2c8408b63b75b06f051665ed7761414c911663 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Tue, 22 Jul 2014 20:13:43 -0700 Subject: [PATCH 01/11] Use `NSUserDefaults` to communicate with UIAutomation in iOS 8. --- .../Classes/Internal/Terminal/SLTerminal.m | 85 ++++++++++++------- 1 file changed, 55 insertions(+), 30 deletions(-) diff --git a/Sources/Classes/Internal/Terminal/SLTerminal.m b/Sources/Classes/Internal/Terminal/SLTerminal.m index 8c59d59..ad1164f 100644 --- a/Sources/Classes/Internal/Terminal/SLTerminal.m +++ b/Sources/Classes/Internal/Terminal/SLTerminal.m @@ -22,6 +22,12 @@ #import "SLTerminal.h" +// So that Subliminal may continue to be built using Xcode 5/the iOS 7.1 SDK, +// and also so that this file may be imported by `subliminal-instrument`, an OS X +// CLI tool, as part of the SLLogger framework. +#ifndef kCFCoreFoundationVersionNumber_iOS_7_1 +#define kCFCoreFoundationVersionNumber_iOS_7_1 847.24 +#endif NSString *const SLTerminalJavaScriptException = @"SLTerminalJavaScriptException"; @@ -114,11 +120,23 @@ - (BOOL)currentQueueIsEvalQueue return dispatch_get_specific(kEvalQueueIdentifier) != NULL; } -#if TARGET_IPHONE_SIMULATOR -// in the simulator, UIAutomation uses a target-specific plist in ~/Library/Application Support/iPhone Simulator/[system version]/Library/Preferences/[bundle ID].plist -// _not_ the NSUserDefaults plist, in the sandboxed Library -// see http://stackoverflow.com/questions/4977673/reading-preferences-set-by-uiautomations-uiaapplication-setpreferencesvaluefork -- (NSString *)simulatorPreferencesPath { +#if TARGET_IPHONE_SIMULATOR || TARGET_OS_MAC +/** + In Simulators below iOS 8, UIAutomation does not use the `NSUserDefaults` plist + found in the sandboxed Library, but rather a target-specific plist found at the + host domain level i.e. at `~/Library/Application Support/iPhone Simulator/[system version]/Library/Preferences/`. + See http://stackoverflow.com/questions/4977673/reading-preferences-set-by-uiautomations-uiaapplication-setpreferencesvaluefork . + + On devices, and in Simulators as of iOS 8, UIAutomation uses the same plist as + `NSUserDefaults`. + + The Mac conditional allows `subliminal-instrument`, an OS X CLI tool, to import + this file as part of the SLLogger framework. + */ +- (NSString *)preIOS8SimulatorPreferencesPath { + NSAssert(kCFCoreFoundationVersionNumber <= kCFCoreFoundationVersionNumber_iOS_7_1, + @"This method must only be called below iOS 8."); + static NSString *path = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -127,6 +145,7 @@ - (NSString *)simulatorPreferencesPath { // 1. get into the simulator's app support directory by fetching the sandboxed Library's path NSString *userDirectoryPath = [(NSURL *)[[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject] path]; + // 2. get out of our application directory, back to the root support directory for this system version plistRootPath = [userDirectoryPath substringToIndex:([userDirectoryPath rangeOfString:@"Applications"].location)]; @@ -139,7 +158,7 @@ - (NSString *)simulatorPreferencesPath { }); return path; } -#endif // TARGET_IPHONE_SIMULATOR +#endif // TARGET_IPHONE_SIMULATOR || TARGET_OS_MAC #pragma mark - Communication @@ -188,36 +207,42 @@ - (id)eval:(NSString *)script { } // Step 1: Write the script to UIAutomation + BOOL targetIsSimulator = NO; #if TARGET_IPHONE_SIMULATOR - NSMutableDictionary *prefs = [NSMutableDictionary dictionaryWithContentsOfFile:[self simulatorPreferencesPath]]; - if (!prefs) { - prefs = [NSMutableDictionary dictionary]; - } - [prefs setObject:@( _scriptIndex ) forKey:SLTerminalPreferencesKeyScriptIndex]; - [prefs setObject:script forKey:SLTerminalPreferencesKeyScript]; - [prefs removeObjectForKey:SLTerminalPreferencesKeyResultIndex]; - [prefs removeObjectForKey:SLTerminalPreferencesKeyResult]; - [prefs removeObjectForKey:SLTerminalPreferencesKeyException]; - [prefs writeToFile:[self simulatorPreferencesPath] atomically:YES]; -#else - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setObject:@( _scriptIndex ) forKey:SLTerminalPreferencesKeyScriptIndex]; - [defaults setObject:script forKey:SLTerminalPreferencesKeyScript]; - [defaults removeObjectForKey:SLTerminalPreferencesKeyResultIndex]; - [defaults removeObjectForKey:SLTerminalPreferencesKeyResult]; - [defaults removeObjectForKey:SLTerminalPreferencesKeyException]; - [defaults synchronize]; + targetIsSimulator = YES; #endif + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + if (targetIsSimulator && (kCFCoreFoundationVersionNumber <= kCFCoreFoundationVersionNumber_iOS_7_1)) { + NSMutableDictionary *prefs = [NSMutableDictionary dictionaryWithContentsOfFile:[self preIOS8SimulatorPreferencesPath]]; + if (!prefs) { + prefs = [NSMutableDictionary dictionary]; + } + [prefs setObject:@( _scriptIndex ) forKey:SLTerminalPreferencesKeyScriptIndex]; + [prefs setObject:script forKey:SLTerminalPreferencesKeyScript]; + [prefs removeObjectForKey:SLTerminalPreferencesKeyResultIndex]; + [prefs removeObjectForKey:SLTerminalPreferencesKeyResult]; + [prefs removeObjectForKey:SLTerminalPreferencesKeyException]; + [prefs writeToFile:[self preIOS8SimulatorPreferencesPath] atomically:YES]; + } else { + [defaults setObject:@( _scriptIndex ) forKey:SLTerminalPreferencesKeyScriptIndex]; + [defaults setObject:script forKey:SLTerminalPreferencesKeyScript]; + [defaults removeObjectForKey:SLTerminalPreferencesKeyResultIndex]; + [defaults removeObjectForKey:SLTerminalPreferencesKeyResult]; + [defaults removeObjectForKey:SLTerminalPreferencesKeyException]; + [defaults synchronize]; + } // Step 2: Wait for the result NSDictionary *resultPrefs = nil; while (1) { -#if TARGET_IPHONE_SIMULATOR - resultPrefs = [NSDictionary dictionaryWithContentsOfFile:[self simulatorPreferencesPath]]; -#else - [defaults synchronize]; - resultPrefs = [defaults dictionaryRepresentation]; -#endif + if (targetIsSimulator && (kCFCoreFoundationVersionNumber <= kCFCoreFoundationVersionNumber_iOS_7_1)) { + resultPrefs = [NSDictionary dictionaryWithContentsOfFile:[self preIOS8SimulatorPreferencesPath]]; + } else { + [defaults synchronize]; + resultPrefs = [defaults dictionaryRepresentation]; + } if (resultPrefs[SLTerminalPreferencesKeyResultIndex]) { NSAssert([resultPrefs[SLTerminalPreferencesKeyResultIndex] intValue] == _scriptIndex, @"Result index is out of sync with script index"); From 304d487257be13c64559ad0624381055709928a3 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Wed, 23 Jul 2014 01:09:07 -0700 Subject: [PATCH 02/11] Locate the simulator preferences on iOS 8. With a different directory layout for simulator configurations inside `~/Library/Developer/CoreSimulator/Devices` rather than `~/Library/Application Support/iPhone Simulator`. --- Sources/Classes/SLTestController.m | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Sources/Classes/SLTestController.m b/Sources/Classes/SLTestController.m index 7c05075..9c64464 100644 --- a/Sources/Classes/SLTestController.m +++ b/Sources/Classes/SLTestController.m @@ -35,6 +35,10 @@ #import +// So that Subliminal may continue to be built using Xcode 5/the iOS 7.1 SDK. +#ifndef kCFCoreFoundationVersionNumber_iOS_7_1 +#define kCFCoreFoundationVersionNumber_iOS_7_1 847.24 +#endif const unsigned int SLTestControllerRandomSeed = UINT_MAX; @@ -278,7 +282,12 @@ - (void)warnIfAccessibilityInspectorIsEnabled { NSString *userDirectoryPath = [(NSURL *)[[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject] path]; // 2. get out of our application directory, back to the root support directory for this system version - NSString *plistRootPath = [userDirectoryPath substringToIndex:([userDirectoryPath rangeOfString:@"Applications"].location)]; + NSString *plistRootPath = nil; + if (kCFCoreFoundationVersionNumber <= kCFCoreFoundationVersionNumber_iOS_7_1) { + plistRootPath = [userDirectoryPath substringToIndex:([userDirectoryPath rangeOfString:@"Applications"].location)]; + } else { + plistRootPath = [userDirectoryPath substringToIndex:([userDirectoryPath rangeOfString:@"data"].location)]; + } // 3. locate, relative to here, the Accessibility preferences NSString *relativePlistPath = @"Library/Preferences/com.apple.Accessibility.plist"; From dc9ebe6d93811384a7dfd9d28c9ba4511aa020e1 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Tue, 22 Jul 2014 21:18:11 -0700 Subject: [PATCH 03/11] Fix typos in `simulator-set`'s documentation. --- Supporting Files/CI/simulator-set | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Supporting Files/CI/simulator-set b/Supporting Files/CI/simulator-set index 570f8ec..735ad27 100755 --- a/Supporting Files/CI/simulator-set +++ b/Supporting Files/CI/simulator-set @@ -27,11 +27,11 @@ print_usage_and_fail () { echo """ usage: simulator-set [--device ] [--version ] [--reset] - -device A device type like \"iPhone\". + --device A device type like \"iPhone\". Acceptable types are listed in the iOS Simulator's \"Hardware\" -> \"Device\" menu. - -version A string like \"5.1\" specifying the simulator SDK + --version A string like \"5.1\" specifying the simulator SDK version to use. Note that the iOS Simulator does not accept certain From e2ef282ebcf03ed2609c33d66ae45c8b5efe29af Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Tue, 22 Jul 2014 21:39:03 -0700 Subject: [PATCH 04/11] `simulator-set` only overwrites the simulator's version if one is specified. `simulator-set`'s documentation describes the version argument as optional. --- Supporting Files/CI/simulator-set | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Supporting Files/CI/simulator-set b/Supporting Files/CI/simulator-set index 735ad27..8ebeadc 100755 --- a/Supporting Files/CI/simulator-set +++ b/Supporting Files/CI/simulator-set @@ -108,10 +108,12 @@ sleep 1.0 ### Set properties ## Device -# If the device type contains punctuation, it needs to be single-quoted to be written into the plist -# but we only quote it if necessary, because the simulator rejects e.g. "'iPhone'" -SAFE_DEVICE=`[[ "$DEVICE" =~ [[:punct:]] ]] && echo "'$DEVICE'" || echo "$DEVICE"` -defaults write com.apple.iphonesimulator SimulateDevice "$SAFE_DEVICE" +if [[ -n "$DEVICE" ]]; then + # If the device type contains punctuation, it needs to be single-quoted to be written into the plist + # but we only quote it if necessary, because the simulator rejects e.g. "'iPhone'" + SAFE_DEVICE=`[[ "$DEVICE" =~ [[:punct:]] ]] && echo "'$DEVICE'" || echo "$DEVICE"` + defaults write com.apple.iphonesimulator SimulateDevice "$SAFE_DEVICE" +fi ## Version if [[ -n "$VERSION" ]]; then From cb268485519d98f8b9f3689f4b180d3a02875607 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Tue, 22 Jul 2014 23:07:08 -0700 Subject: [PATCH 05/11] Update `simulator-set` for Xcode 6. In Xcode 6, the Simulator's device type and version are not stored separately in the Simulator's preferences, but as a unified configuration (a "device") identified by a UDID. To change the device type and version, we must thus determine which UDID to set, which we do by examining the mapping provided by `instruments -s devices`. Similarly, the Simulator's content and settings are no longer stored under version-specific directories, but under device-specific directories. However, it's not safe to delete these directories directly--some devices will not recreate them on launch. Fortunately, Apple has added a command-line utility for managing devices. --- Supporting Files/CI/simulator-set | 124 ++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 40 deletions(-) diff --git a/Supporting Files/CI/simulator-set b/Supporting Files/CI/simulator-set index 8ebeadc..96bb0ca 100755 --- a/Supporting Files/CI/simulator-set +++ b/Supporting Files/CI/simulator-set @@ -29,14 +29,17 @@ usage: simulator-set [--device ] [--version ] [--reset] --device A device type like \"iPhone\". Acceptable types are listed in the iOS Simulator's - \"Hardware\" -> \"Device\" menu. + \"Hardware\" -> \"Device\" menu (under SDK version + submenus, if you are running Xcode 6). + + If both device type and version are specified, + the device type must support the specified version. --version A string like \"5.1\" specifying the simulator SDK version to use. - Note that the iOS Simulator does not accept certain - combinations of device type and SDK, - e.g. \"iPhone Retina (4-inch)\" and \"5.1\". + If both device type and version are specified, + the device type must support the specified version. --reset Deletes all applications from, and resets the settings of, the SDK specified by \`-version\` (if \`--version\` @@ -100,55 +103,96 @@ if [[ -n "$CURRENT_ARG" ]]; then fi +### Determine platform defaults +if [[ "$(xcrun xcodebuild -version | head -n 1)" == "Xcode 6"* ]]; then + SIMULATOR_NAME="iOS Simulator" + CURRENT_DEVICE_UDID=`defaults read com.apple.iphonesimulator CurrentDeviceUDID 2> /dev/null` +else + SIMULATOR_NAME="iPhone Simulator" +fi + + ### Kill the Simulator -killall "iPhone Simulator" 2> /dev/null +killall "$SIMULATOR_NAME" 2> /dev/null sleep 1.0 ### Set properties -## Device -if [[ -n "$DEVICE" ]]; then - # If the device type contains punctuation, it needs to be single-quoted to be written into the plist - # but we only quote it if necessary, because the simulator rejects e.g. "'iPhone'" - SAFE_DEVICE=`[[ "$DEVICE" =~ [[:punct:]] ]] && echo "'$DEVICE'" || echo "$DEVICE"` - defaults write com.apple.iphonesimulator SimulateDevice "$SAFE_DEVICE" -fi +if [[ -n "$CURRENT_DEVICE_UDID" ]]; then + # We need to translate the desired device and version into a UDID + # filling in the current values if device and/or version are not specified + CURRENT_DEVICE_SPECIFICATION=`xcrun instruments -s devices | grep "$CURRENT_DEVICE_UDID"` + + # Guide to interpreting the below regexes: we expect "device specifications" + # to be of the form "iPhone 4s (7.1 Simulator) [EE99513B-680F-4955-AE47-989230D6B697]" + # i.e. "CURRENT_DEVICE (CURRENT_VERSION Simulator) [DEVICE_UDID]" + + # use perl for minimal matching, not supported by bash/sed + CURRENT_DEVICE=`echo "$CURRENT_DEVICE_SPECIFICATION" | perl -pe "s/^(.+?) \(.+/\1/"` + CURRENT_VERSION=`echo "$CURRENT_DEVICE_SPECIFICATION" | perl -pe "s/^.+? \(([0-9\.]+) Simulator.+/\1/"` + + if [[ -z "$DEVICE" ]]; then DEVICE="$CURRENT_DEVICE"; fi + if [[ -z "$VERSION" ]]; then VERSION="$CURRENT_VERSION"; fi + + DEVICE_SPECIFICATION_PREFIX="$DEVICE ($VERSION Simulator)" + # cut the prefix off the front of the specification before extracting the UDID + # because it contains parentheses, so can't be substituted into the `sed` regex + DEVICE_UDID=`xcrun instruments -s devices | grep "$DEVICE_SPECIFICATION_PREFIX" | + cut -c"$(expr ${#DEVICE_SPECIFICATION_PREFIX} + 1)"- | sed -E "s/ \[(.+)\]/\1/"` + + defaults write com.apple.iphonesimulator CurrentDeviceUDID "$DEVICE_UDID" + + # Update the current device ID for benefit of the reset procedure below + CURRENT_DEVICE_UDID="$DEVICE_UDID" +else + ## Device + if [[ -n "$DEVICE" ]]; then + # If the device type contains punctuation, it needs to be single-quoted to be written into the plist + # but we only quote it if necessary, because the simulator rejects e.g. "'iPhone'" + SAFE_DEVICE=`[[ "$DEVICE" =~ [[:punct:]] ]] && echo "'$DEVICE'" || echo "$DEVICE"` + defaults write com.apple.iphonesimulator SimulateDevice "$SAFE_DEVICE" + fi -## Version -if [[ -n "$VERSION" ]]; then - # Set new SDK root - # The quoting of "xcode-select" is just so that "select" doesn't mess up this file's syntax highlighting - SDK_ROOT=`find "$('xcode-select' -print-path)" -type d -iname "iphonesimulator$VERSION.sdk"` - if [[ -z "$SDK_ROOT" ]]; then - echo "Error: Simulator SDK $VERSION not found." - exit 1 + ## Version + if [[ -n "$VERSION" ]]; then + # Set new SDK root + # The quoting of "xcode-select" is just so that "select" doesn't mess up this file's syntax highlighting + SDK_ROOT=`find "$('xcode-select' -print-path)" -type d -iname "iphonesimulator$VERSION.sdk" -print -quit` + if [[ -z "$SDK_ROOT" ]]; then + echo "Error: Simulator SDK $VERSION not found." + exit 1 + fi + defaults write com.apple.iphonesimulator currentSDKRoot "$SDK_ROOT" fi - defaults write com.apple.iphonesimulator currentSDKRoot "$SDK_ROOT" fi ### Reset the Simulator's content and settings if [[ -n "$RESET" ]] && $RESET; then - # Determine the SDK version e.g. "5.1" used by the simulator - SDK_ROOT=`defaults read com.apple.iphonesimulator currentSDKRoot` - SDK=`echo "$SDK_ROOT" | perl -pe 's|.*iphonesimulator(.+)\.sdk|$1|i'` - - # Delete the `Application Support` directory for this SDK version, - # which will erase both the content and settings for this version. - # The Simulator will recreate this support directory when relaunched below. - - # There may be multiple support directories for this SDK version, - # e.g. 7.0, 7.0.3, 7.0.3-64 --we just delete them all. - # We can't quote the directory prefix or we'll disable globbing, - # so prevent splitting by unsetting IFS. - OLD_IFS="$IFS"; unset IFS - SUPPORT_DIRS=`echo $HOME/Library/Application\ Support/iPhone\ Simulator/$SDK* | perl -pe "s| /|\\n/|g"` - while read -r dir; do - rm -rf "$dir" - done <<< "$SUPPORT_DIRS" - IFS="$OLD_IFS" + if [[ -n "$CURRENT_DEVICE_UDID" ]]; then + xcrun simctl erase "$CURRENT_DEVICE_UDID" + else + # Determine the SDK version e.g. "5.1" used by the simulator + SDK_ROOT=`defaults read com.apple.iphonesimulator currentSDKRoot` + SDK=`echo "$SDK_ROOT" | perl -pe 's|.*iphonesimulator(.+)\.sdk|$1|i'` + + # Delete the `Application Support` directory for this SDK version, + # which will erase both the content and settings for this version. + # The Simulator will recreate this support directory when relaunched below. + + # There may be multiple support directories for this SDK version, + # e.g. 7.0, 7.0.3, 7.0.3-64 --we just delete them all. + # We can't quote the directory prefix or we'll disable globbing, + # so prevent splitting by unsetting IFS. + OLD_IFS="$IFS"; unset IFS + SUPPORT_DIRS=`echo $HOME/Library/Application\ Support/iPhone\ Simulator/$SDK* | perl -pe "s| /|\\n/|g"` + while read -r dir; do + rm -rf "$dir" + done <<< "$SUPPORT_DIRS" + IFS="$OLD_IFS" + fi fi @@ -156,6 +200,6 @@ fi # Make sure to open the simulator corresponding to the current dev toolchain # The quoting of "xcode-select" is just so that "select" doesn't mess up this file's syntax highlighting -SIMULATOR_PATH=`find "$('xcode-select' -print-path)" -name "iPhone Simulator.app"` +SIMULATOR_PATH=`find "$('xcode-select' -print-path)" -name "$SIMULATOR_NAME.app" -print -quit` open "$SIMULATOR_PATH" sleep 2.0 From 4342fa7b095712f468b10d6082c9181a334553ff Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Wed, 23 Jul 2014 01:07:06 -0700 Subject: [PATCH 06/11] Supply Xcode 6-format device specifications to `instruments`. --- Supporting Files/CI/subliminal-test | 38 +++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Supporting Files/CI/subliminal-test b/Supporting Files/CI/subliminal-test index 01b6916..e50acee 100755 --- a/Supporting Files/CI/subliminal-test +++ b/Supporting Files/CI/subliminal-test @@ -71,14 +71,19 @@ Required arguments: -sim_device The type of device to simulate. Acceptable values are listed by executing \`instruments -s devices\`: - given a listing like \"iPad - Simulator - iOS 7.1\", the device - type is the first dash-separated component, trimmed of spaces, - e.g. \"iPad\". - Note that (despite the response of \`instruments -s devices\`) - the iOS Simulator does not accept certain combinations - of device type and SDK (as specified using the \`-sim_version\` - argument), e.g. \"iPhone\" and \"7.1\". + * if you are using the Xcode 5 toolchain, you will see listings like + \"iPad - Simulator - iOS 7.1\". The device type is the first + dash-separated component, trimmed of spaces, e.g. \"iPad\". + * if you are using the Xcode 6 toolchain, you will see listings like + \"iPad 2 (7.1 Simulator)\". The device type is the text + preceding the parenthetical expression, trimmed of spaces, + e.g. \"iPad 2\". + + Note that (despite the response of \`instruments -s devices\` + when using the Xcode 5 toolchain) the iOS Simulator does not accept + certain combinations of device type and SDK (as specified using the + \`-sim_version\` argument), e.g. \"iPhone\" and \"7.1\". Either this or \`-hw_id\` must be specified. @@ -530,7 +535,7 @@ if [[ -n "$LOGIN_PASSWORD" ]]; then AUTHORIZE_INSTRUMENTS_PID=$! fi -launch_instruments () { +launch_instruments () { # Second attempt to authorize `instruments` ourselves # (in case the dialog does not show, as in certain CI environments # like Travis): enter the login password on the command line, @@ -540,12 +545,25 @@ launch_instruments () { # Note that the Subliminal trace template includes the UIASCRIPT # and the environment variables passed to this script # are passed to instruments and the app by being exported at the top of this script + local timeout_arg=`[[ -n "$TIMEOUT" ]] && echo "-l $TIMEOUT" || echo ""` - local device=`[[ -n "$HW_ID" ]] && echo "$HW_ID" || echo "$SIM_DEVICE - Simulator - iOS $SIM_VERSION"` + + device_string() { + if [[ -n "$HW_ID" ]]; then + echo "$HW_ID" + else + if [[ "$(xcrun xcodebuild -version | head -n 1)" == "Xcode 6"* ]]; then + echo "$SIM_DEVICE ($SIM_VERSION Simulator)" + else + echo "$SIM_DEVICE - Simulator - iOS $SIM_VERSION" + fi + fi + } + printf "$LOGIN_PASSWORD\n" | "$SCRIPT_DIR/subliminal-instrument.sh"\ -D "$TRACE_FILE"\ $timeout_arg\ - -w "$device"\ + -w "$(device_string)"\ "$APP"\ -e UIARESULTSPATH "$RESULTS_DIR" \ $ENV_STR & From fd77294adfd59eb01cb64073f008c3d980704fd6 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Thu, 28 Aug 2014 16:50:16 -0700 Subject: [PATCH 07/11] Force Xcode 6 to run OCUnit tests. (refs #258) --- Subliminal.xcodeproj/project.pbxproj | 8 ++++++++ .../subliminal-instrument.xcodeproj/project.pbxproj | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Subliminal.xcodeproj/project.pbxproj b/Subliminal.xcodeproj/project.pbxproj index 264b91e..25cc07f 100644 --- a/Subliminal.xcodeproj/project.pbxproj +++ b/Subliminal.xcodeproj/project.pbxproj @@ -1767,6 +1767,10 @@ ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Unit Tests/Subliminal Unit Tests-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SENTEST_IGNORE_DEPRECATION_WARNING=1", + ); GCC_WARN_UNDECLARED_SELECTOR = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1790,6 +1794,10 @@ ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Unit Tests/Subliminal Unit Tests-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SENTEST_IGNORE_DEPRECATION_WARNING=1", + ); GCC_WARN_UNDECLARED_SELECTOR = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", diff --git a/Supporting Files/CI/subliminal-instrument/subliminal-instrument.xcodeproj/project.pbxproj b/Supporting Files/CI/subliminal-instrument/subliminal-instrument.xcodeproj/project.pbxproj index 9a7d2a5..3c5398a 100644 --- a/Supporting Files/CI/subliminal-instrument/subliminal-instrument.xcodeproj/project.pbxproj +++ b/Supporting Files/CI/subliminal-instrument/subliminal-instrument.xcodeproj/project.pbxproj @@ -686,8 +686,8 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "subliminal-instrument Tests/subliminal-instrument Tests-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", "$(inherited)", + "SENTEST_IGNORE_DEPRECATION_WARNING=1", ); INFOPLIST_FILE = "subliminal-instrument Tests/subliminal-instrument Tests-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -706,6 +706,10 @@ ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "subliminal-instrument Tests/subliminal-instrument Tests-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SENTEST_IGNORE_DEPRECATION_WARNING=1", + ); INFOPLIST_FILE = "subliminal-instrument Tests/subliminal-instrument Tests-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = octest; From f4a02cfe161d85fe4d241bb0047aecb4bb8c2c73 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Mon, 7 Jul 2014 19:31:50 -0700 Subject: [PATCH 08/11] Support running Subliminal's tests against iOS 8 in CI. --- Rakefile | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Rakefile b/Rakefile index 69b2548..22e5281 100644 --- a/Rakefile +++ b/Rakefile @@ -33,7 +33,14 @@ DOCSET_DIR = "#{ENV['HOME']}/Library/Developer/Shared/Documentation/DocSets" DOCSET_NAME = "com.inkling.Subliminal.docset" DOCSET_VERSION = "1.1.0" -SUPPORTED_SDKS = [ "6.1", "7.1" ] +USING_XCODE_6 = `xcrun xcodebuild -version | head -n 1`.start_with?("Xcode 6") + +if USING_XCODE_6 + SUPPORTED_SDKS = [ "7.1", "8.0" ] +else + SUPPORTED_SDKS = [ "6.1", "7.1" ] +end + TEST_SDK = ENV["TEST_SDK"] if TEST_SDK raise "Test SDK #{TEST_SDK} is not supported." unless SUPPORTED_SDKS.include?(TEST_SDK) @@ -485,8 +492,9 @@ namespace :test do # Use system so we see the tests' output results_dir = fresh_results_dir!("iphone", sdk) - # Use the 3.5" iPhone Retina because that can support both our target SDKs - if system("#{base_test_command} -output \"#{results_dir}\" -sim_device 'iPhone Retina (3.5-inch)' -sim_version #{sdk}") + # Use the iPhone 4s because that can support all our target SDKs + device_type = USING_XCODE_6 ? "iPhone 4s" : "iPhone Retina (3.5-inch)" + if system("#{base_test_command} -output \"#{results_dir}\" -sim_device '#{device_type}' -sim_version #{sdk}") puts "iPhone integration tests succeeded on iOS #{sdk}.\n\n" else puts "iPhone integration tests failed on iOS #{sdk}.\n\n" @@ -512,7 +520,8 @@ namespace :test do # Use system so we see the tests' output results_dir = fresh_results_dir!("ipad", sdk) - if system("#{base_test_command} -output \"#{results_dir}\" -sim_device 'iPad' -sim_version #{sdk}") + # Use the iPad Retina because that can support all our target SDKs + if system("#{base_test_command} -output \"#{results_dir}\" -sim_device 'iPad Retina' -sim_version #{sdk}") puts "iPad integration tests succeeded on iOS #{sdk}.\n\n" else puts "iPad integration tests failed on iOS #{sdk}.\n\n" From 637b7fd8f451b3f8237926f52a37e004dfb16eda Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Sat, 2 Aug 2014 10:55:24 -0700 Subject: [PATCH 09/11] Update UIAutomation's visibility bugs for iOS 8. This also corrects the name of an existing test case in the visibility test documentation. --- Integration Tests/Tests/SLElementVisibilityTest.m | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Integration Tests/Tests/SLElementVisibilityTest.m b/Integration Tests/Tests/SLElementVisibilityTest.m index 82a13ee..0f57b1d 100644 --- a/Integration Tests/Tests/SLElementVisibilityTest.m +++ b/Integration Tests/Tests/SLElementVisibilityTest.m @@ -23,13 +23,19 @@ #import "SLIntegrationTest.h" #import "SLUIAElement+Subclassing.h" +// So that Subliminal may continue to be built using Xcode 5/the iOS 7.1 SDK. +#ifndef kCFCoreFoundationVersionNumber_iOS_7_1 +#define kCFCoreFoundationVersionNumber_iOS_7_1 847.24 +#endif + /** Subliminal's implementation of -isVisible does not rely upon UIAutomation, because UIAElement.isVisible() has a number of bugs as exercised in -testViewIsNotVisibleIfItIsHiddenEvenInTableViewCell -testAccessibilityElementIsNotVisibleIfContainerIsHiddenEvenInTableViewCell -testViewIsVisibleIfItsCenterIsCoveredByClearRegion - -testViewIsNotVisibleIfCenterAndUpperLeftHandCornerAreCovered + -testViewIsNotVisibleIfCenterAndAnyCornerAreCovered + -testAccessibilityElementIsNotVisibleIfItsCenterIsCoveredByView Subliminal's implementation otherwise attempts to conform to UIAutomation's definition of visibility, as demonstrated by the below test cases. @@ -345,7 +351,11 @@ - (void)testAccessibilityElementIsNotVisibleIfItIsOffscreen { } - (void)testAccessibilityElementIsNotVisibleIfItsCenterIsCoveredByView { - SLAssertFalse([_testElement uiaIsVisible], @"UIAutomation should say that the element is not visible."); + if (kCFCoreFoundationVersionNumber <= kCFCoreFoundationVersionNumber_iOS_7_1) { + SLAssertFalse([_testElement uiaIsVisible], @"UIAutomation should say that the element is not visible."); + } else { + SLAssertTrue([_testElement uiaIsVisible], @"UIAutomation should say that the element is not visible, but it doesn't."); + } SLAssertFalse([_testElement isVisible], @"Subliminal should say that the element is not visible."); // the test view is the container of the test element From 5861aaa6f8cdba5178f22b80eb35e582b7aad3d7 Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Thu, 28 Aug 2014 18:22:22 -0700 Subject: [PATCH 10/11] Upgrade project settings for Xcode 6. --- Subliminal.xcodeproj/project.pbxproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Subliminal.xcodeproj/project.pbxproj b/Subliminal.xcodeproj/project.pbxproj index 25cc07f..cb21be7 100644 --- a/Subliminal.xcodeproj/project.pbxproj +++ b/Subliminal.xcodeproj/project.pbxproj @@ -1210,7 +1210,7 @@ isa = PBXProject; attributes = { LastTestingUpgradeCheck = 0510; - LastUpgradeCheck = 0500; + LastUpgradeCheck = 0600; ORGANIZATIONNAME = Inkling; }; buildConfigurationList = F0695D8516011515000B05D0 /* Build configuration list for PBXProject "Subliminal" */; @@ -1627,8 +1627,10 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -1662,8 +1664,10 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; From d99fef42529589373adc1948aede98aed0fbe9de Mon Sep 17 00:00:00 2001 From: Jeff Wear Date: Thu, 28 Aug 2014 19:12:58 -0700 Subject: [PATCH 11/11] Pick up the latest OCMock to resolve Xcode 6 warnings. --- Unit Tests/OCMock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unit Tests/OCMock b/Unit Tests/OCMock index 8804801..1f09bae 160000 --- a/Unit Tests/OCMock +++ b/Unit Tests/OCMock @@ -1 +1 @@ -Subproject commit 88048016539d3874192d6f0bd922500a5b0813d5 +Subproject commit 1f09baef54a43cb11ed9635a678537d18ea107dd