Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
704fb4cb
Unverified
Commit
704fb4cb
authored
Feb 25, 2020
by
Christopher Fujino
Committed by
GitHub
Feb 25, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove usage of ideviceinstaller in favor of ios-deploy (#50772)
parent
2078cc4d
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
997 additions
and
280 deletions
+997
-280
adb.dart
dev/devicelab/lib/framework/adb.dart
+0
-2
cache.dart
packages/flutter_tools/lib/src/cache.dart
+0
-2
install.dart
packages/flutter_tools/lib/src/commands/install.dart
+9
-4
context_runner.dart
packages/flutter_tools/lib/src/context_runner.dart
+8
-2
globals.dart
packages/flutter_tools/lib/src/globals.dart
+2
-0
devices.dart
packages/flutter_tools/lib/src/ios/devices.dart
+52
-115
ios_deploy.dart
packages/flutter_tools/lib/src/ios/ios_deploy.dart
+187
-0
mac.dart
packages/flutter_tools/lib/src/ios/mac.dart
+0
-1
xcode.dart
packages/flutter_tools/lib/src/macos/xcode.dart
+5
-0
devices_test.dart
...es/flutter_tools/test/general.shard/ios/devices_test.dart
+615
-154
ios_deploy_test.dart
...flutter_tools/test/general.shard/ios/ios_deploy_test.dart
+119
-0
No files found.
dev/devicelab/lib/framework/adb.dart
View file @
704fb4cb
...
...
@@ -498,9 +498,7 @@ class IosDeviceDiscovery implements DeviceDiscovery {
'usbmuxd'
,
'libplist'
,
'openssl'
,
'ideviceinstaller'
,
'ios-deploy'
,
'libzip'
,
].
map
((
String
packageName
)
=>
path
.
join
(
getArtifactPath
(),
packageName
)).
join
(
':'
);
return
<
String
,
String
>{
'DYLD_LIBRARY_PATH'
:
libPath
};
}
...
...
packages/flutter_tools/lib/src/cache.dart
View file @
704fb4cb
...
...
@@ -1261,9 +1261,7 @@ class IosUsbArtifacts extends CachedArtifact {
'usbmuxd'
,
'libplist'
,
'openssl'
,
'ideviceinstaller'
,
'ios-deploy'
,
'libzip'
,
];
// For unknown reasons, users are getting into bad states where libimobiledevice is
...
...
packages/flutter_tools/lib/src/commands/install.dart
View file @
704fb4cb
...
...
@@ -6,6 +6,7 @@ import 'dart:async';
import
'../application_package.dart'
;
import
'../base/common.dart'
;
import
'../base/io.dart'
;
import
'../cache.dart'
;
import
'../device.dart'
;
import
'../globals.dart'
as
globals
;
...
...
@@ -54,11 +55,15 @@ Future<bool> installApp(Device device, ApplicationPackage package, { bool uninst
return
false
;
}
if
(
uninstall
&&
await
device
.
isAppInstalled
(
package
))
{
globals
.
printStatus
(
'Uninstalling old version...'
);
if
(!
await
device
.
uninstallApp
(
package
))
{
globals
.
printError
(
'Warning: uninstalling old version failed'
);
try
{
if
(
uninstall
&&
await
device
.
isAppInstalled
(
package
))
{
globals
.
printStatus
(
'Uninstalling old version...'
);
if
(!
await
device
.
uninstallApp
(
package
))
{
globals
.
printError
(
'Warning: uninstalling old version failed'
);
}
}
}
on
ProcessException
catch
(
e
)
{
globals
.
printError
(
'Error accessing device
${device.id}
:
\n
${e.message}
'
);
}
return
device
.
installApp
(
package
);
...
...
packages/flutter_tools/lib/src/context_runner.dart
View file @
704fb4cb
...
...
@@ -35,7 +35,7 @@ import 'fuchsia/fuchsia_device.dart' show FuchsiaDeviceTools;
import
'fuchsia/fuchsia_sdk.dart'
show
FuchsiaSdk
,
FuchsiaArtifacts
;
import
'fuchsia/fuchsia_workflow.dart'
show
FuchsiaWorkflow
;
import
'globals.dart'
as
globals
;
import
'ios/
devices.dart'
show
IOSDeploy
;
import
'ios/
ios_deploy.dart'
;
import
'ios/ios_workflow.dart'
;
import
'ios/mac.dart'
;
import
'ios/simulators.dart'
;
...
...
@@ -125,7 +125,13 @@ Future<T> runInContext<T>(
GradleUtils:
()
=>
GradleUtils
(),
HotRunnerConfig:
()
=>
HotRunnerConfig
(),
IMobileDevice:
()
=>
IMobileDevice
(),
IOSDeploy:
()
=>
const
IOSDeploy
(),
IOSDeploy:
()
=>
IOSDeploy
(
artifacts:
globals
.
artifacts
,
cache:
globals
.
cache
,
logger:
globals
.
logger
,
platform:
globals
.
platform
,
processManager:
globals
.
processManager
,
),
IOSSimulatorUtils:
()
=>
IOSSimulatorUtils
(),
IOSWorkflow:
()
=>
const
IOSWorkflow
(),
KernelCompilerFactory:
()
=>
const
KernelCompilerFactory
(),
...
...
packages/flutter_tools/lib/src/globals.dart
View file @
704fb4cb
...
...
@@ -20,6 +20,7 @@ import 'base/os.dart';
import
'base/terminal.dart'
;
import
'base/user_messages.dart'
;
import
'cache.dart'
;
import
'ios/ios_deploy.dart'
;
import
'ios/mac.dart'
;
import
'macos/xcode.dart'
;
import
'persistent_tool_state.dart'
;
...
...
@@ -62,6 +63,7 @@ AndroidStudio get androidStudio => context.get<AndroidStudio>();
AndroidSdk
get
androidSdk
=>
context
.
get
<
AndroidSdk
>();
FlutterVersion
get
flutterVersion
=>
context
.
get
<
FlutterVersion
>();
IMobileDevice
get
iMobileDevice
=>
context
.
get
<
IMobileDevice
>();
IOSDeploy
get
iosDeploy
=>
context
.
get
<
IOSDeploy
>();
UserMessages
get
userMessages
=>
context
.
get
<
UserMessages
>();
Xcode
get
xcode
=>
context
.
get
<
Xcode
>();
...
...
packages/flutter_tools/lib/src/ios/devices.dart
View file @
704fb4cb
...
...
@@ -11,7 +11,6 @@ import 'package:platform/platform.dart';
import
'../application_package.dart'
;
import
'../artifacts.dart'
;
import
'../base/common.dart'
;
import
'../base/context.dart'
;
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/logger.dart'
;
...
...
@@ -25,85 +24,11 @@ import '../mdns_discovery.dart';
import
'../project.dart'
;
import
'../protocol_discovery.dart'
;
import
'../vmservice.dart'
;
import
'code_signing.dart'
;
import
'fallback_discovery.dart'
;
import
'ios_deploy.dart'
;
import
'ios_workflow.dart'
;
import
'mac.dart'
;
class
IOSDeploy
{
const
IOSDeploy
();
static
IOSDeploy
get
instance
=>
context
.
get
<
IOSDeploy
>();
/// Installs and runs the specified app bundle using ios-deploy, then returns
/// the exit code.
Future
<
int
>
runApp
({
@required
String
deviceId
,
@required
String
bundlePath
,
@required
List
<
String
>
launchArguments
,
})
async
{
final
String
iosDeployPath
=
globals
.
artifacts
.
getArtifactPath
(
Artifact
.
iosDeploy
,
platform:
TargetPlatform
.
ios
);
final
List
<
String
>
launchCommand
=
<
String
>[
iosDeployPath
,
'--id'
,
deviceId
,
'--bundle'
,
bundlePath
,
'--no-wifi'
,
'--justlaunch'
,
if
(
launchArguments
.
isNotEmpty
)
...<
String
>[
'--args'
,
launchArguments
.
join
(
' '
),
],
];
// Push /usr/bin to the front of PATH to pick up default system python, package 'six'.
//
// ios-deploy transitively depends on LLDB.framework, which invokes a
// Python script that uses package 'six'. LLDB.framework relies on the
// python at the front of the path, which may not include package 'six'.
// Ensure that we pick up the system install of python, which does include
// it.
final
Map
<
String
,
String
>
iosDeployEnv
=
Map
<
String
,
String
>.
from
(
globals
.
platform
.
environment
);
iosDeployEnv
[
'PATH'
]
=
'/usr/bin:
${iosDeployEnv['PATH']}
'
;
iosDeployEnv
.
addEntries
(<
MapEntry
<
String
,
String
>>[
globals
.
cache
.
dyLdLibEntry
]);
return
await
processUtils
.
stream
(
launchCommand
,
mapFunction:
_monitorInstallationFailure
,
trace:
true
,
environment:
iosDeployEnv
,
);
}
// Maps stdout line stream. Must return original line.
String
_monitorInstallationFailure
(
String
stdout
)
{
// Installation issues.
if
(
stdout
.
contains
(
'Error 0xe8008015'
)
||
stdout
.
contains
(
'Error 0xe8000067'
))
{
globals
.
printError
(
noProvisioningProfileInstruction
,
emphasis:
true
);
// Launch issues.
}
else
if
(
stdout
.
contains
(
'e80000e2'
))
{
globals
.
printError
(
'''
═══════════════════════════════════════════════════════════════════════════════════
Your device is locked. Unlock your device first before running.
═══════════════════════════════════════════════════════════════════════════════════'''
,
emphasis:
true
);
}
else
if
(
stdout
.
contains
(
'Error 0xe8000022'
))
{
globals
.
printError
(
'''
═══════════════════════════════════════════════════════════════════════════════════
Error launching app. Try launching from within Xcode via:
open ios/Runner.xcworkspace
Your Xcode version may be too old for your iOS version.
═══════════════════════════════════════════════════════════════════════════════════'''
,
emphasis:
true
);
}
return
stdout
;
}
}
class
IOSDevices
extends
PollingDeviceDiscovery
{
IOSDevices
()
:
super
(
'iOS devices'
);
...
...
@@ -122,35 +47,38 @@ class IOSDevices extends PollingDeviceDiscovery {
class
IOSDevice
extends
Device
{
IOSDevice
(
String
id
,
{
@required
FileSystem
fileSystem
,
@required
this
.
name
,
@required
this
.
cpuArchitecture
,
@required
String
sdkVersion
,
@required
Platform
platform
,
@required
Artifacts
artifacts
,
@required
IOSDeploy
iosDeploy
,
})
:
_sdkVersion
=
sdkVersion
,
_iosDeploy
=
iosDeploy
,
_fileSystem
=
fileSystem
,
super
(
id
,
category:
Category
.
mobile
,
platformType:
PlatformType
.
ios
,
ephemeral:
true
,
)
{
if
(!
globals
.
platform
.
isMacOS
)
{
if
(!
platform
.
isMacOS
)
{
assert
(
false
,
'Control of iOS devices or simulators only supported on Mac OS.'
);
return
;
}
_installerPath
=
globals
.
artifacts
.
getArtifactPath
(
Artifact
.
ideviceinstaller
,
platform:
TargetPlatform
.
ios
,
);
_iproxyPath
=
globals
.
artifacts
.
getArtifactPath
(
_iproxyPath
=
artifacts
.
getArtifactPath
(
Artifact
.
iproxy
,
platform:
TargetPlatform
.
ios
,
);
}
String
_installerPath
;
String
_iproxyPath
;
final
String
_sdkVersion
;
final
IOSDeploy
_iosDeploy
;
final
FileSystem
_fileSystem
;
/// May be 0 if version cannot be parsed.
int
get
majorSdkVersion
{
...
...
@@ -200,19 +128,17 @@ class IOSDevice extends Device {
@override
Future
<
bool
>
isAppInstalled
(
IOSApp
app
)
async
{
RunResult
apps
;
bool
result
;
try
{
apps
=
await
processUtils
.
run
(
<
String
>[
_installerPath
,
'--list-apps'
],
throwOnError:
true
,
environment:
Map
<
String
,
String
>.
fromEntries
(
<
MapEntry
<
String
,
String
>>[
globals
.
cache
.
dyLdLibEntry
],
),
result
=
await
_iosDeploy
.
isAppInstalled
(
bundleId:
app
.
id
,
deviceId:
id
,
);
}
on
ProcessException
{
}
on
ProcessException
catch
(
e
)
{
globals
.
printError
(
e
.
message
);
return
false
;
}
return
RegExp
(
app
.
id
,
multiLine:
true
).
hasMatch
(
apps
.
stdout
)
;
return
result
;
}
@override
...
...
@@ -220,42 +146,50 @@ class IOSDevice extends Device {
@override
Future
<
bool
>
installApp
(
IOSApp
app
)
async
{
final
Directory
bundle
=
globals
.
fs
.
directory
(
app
.
deviceBundlePath
);
final
Directory
bundle
=
_fileSystem
.
directory
(
app
.
deviceBundlePath
);
if
(!
bundle
.
existsSync
())
{
globals
.
printError
(
'Could not find application bundle at
${bundle.path}
; have you run "flutter build ios"?'
);
return
false
;
}
int
installationResult
;
try
{
await
processUtils
.
run
(
<
String
>[
_installerPath
,
'-i'
,
app
.
deviceBundlePath
],
throwOnError:
true
,
environment:
Map
<
String
,
String
>.
fromEntries
(
<
MapEntry
<
String
,
String
>>[
globals
.
cache
.
dyLdLibEntry
],
),
installationResult
=
await
_iosDeploy
.
installApp
(
deviceId:
id
,
bundlePath:
bundle
.
path
,
launchArguments:
<
String
>[],
);
return
true
;
}
on
ProcessException
catch
(
error
)
{
globals
.
printError
(
error
.
message
);
}
on
ProcessException
catch
(
e
)
{
globals
.
printError
(
e
.
message
);
return
false
;
}
if
(
installationResult
!=
0
)
{
globals
.
printError
(
'Could not install
${bundle.path}
on
$id
.'
);
globals
.
printError
(
'Try launching Xcode and selecting "Product > Run" to fix the problem:'
);
globals
.
printError
(
' open ios/Runner.xcworkspace'
);
globals
.
printError
(
''
);
return
false
;
}
return
true
;
}
@override
Future
<
bool
>
uninstallApp
(
IOSApp
app
)
async
{
int
uninstallationResult
;
try
{
await
processUtils
.
run
(
<
String
>[
_installerPath
,
'-U'
,
app
.
id
],
throwOnError:
true
,
environment:
Map
<
String
,
String
>.
fromEntries
(
<
MapEntry
<
String
,
String
>>[
globals
.
cache
.
dyLdLibEntry
],
),
uninstallationResult
=
await
_iosDeploy
.
uninstallApp
(
deviceId:
id
,
bundleId:
app
.
id
,
);
return
true
;
}
on
ProcessException
catch
(
error
)
{
globals
.
printError
(
error
.
message
);
}
on
ProcessException
catch
(
e
)
{
globals
.
printError
(
e
.
message
);
return
false
;
}
if
(
uninstallationResult
!=
0
)
{
globals
.
printError
(
'Could not uninstall
${app.id}
on
$id
.'
);
return
false
;
}
return
true
;
}
@override
...
...
@@ -301,7 +235,7 @@ class IOSDevice extends Device {
packageId
??=
package
.
id
;
// Step 2: Check that the application exists at the specified path.
final
Directory
bundle
=
globals
.
fs
.
directory
(
package
.
deviceBundlePath
);
final
Directory
bundle
=
_fileSystem
.
directory
(
package
.
deviceBundlePath
);
if
(!
bundle
.
existsSync
())
{
globals
.
printError
(
'Could not find the built application bundle at
${bundle.path}
.'
);
return
LaunchResult
.
failed
();
...
...
@@ -359,13 +293,13 @@ class IOSDevice extends Device {
ipv6:
ipv6
,
);
}
final
int
installationResult
=
await
IOSDeploy
.
instance
.
runApp
(
final
int
installationResult
=
await
_iosDeploy
.
runApp
(
deviceId:
id
,
bundlePath:
bundle
.
path
,
launchArguments:
launchArguments
,
);
if
(
installationResult
!=
0
)
{
globals
.
printError
(
'Could not
install
${bundle.path}
on
$id
.'
);
globals
.
printError
(
'Could not
run
${bundle.path}
on
$id
.'
);
globals
.
printError
(
'Try launching Xcode and selecting "Product > Run" to fix the problem:'
);
globals
.
printError
(
' open ios/Runner.xcworkspace'
);
globals
.
printError
(
''
);
...
...
@@ -395,6 +329,9 @@ class IOSDevice extends Device {
return
LaunchResult
.
failed
();
}
return
LaunchResult
.
succeeded
(
observatoryUri:
localUri
);
}
on
ProcessException
catch
(
e
)
{
globals
.
printError
(
e
.
message
);
return
LaunchResult
.
failed
();
}
finally
{
installStatus
.
stop
();
}
...
...
@@ -450,7 +387,7 @@ class IOSDevice extends Device {
@override
Future
<
void
>
dispose
()
async
{
_logReaders
.
forEach
((
IOSApp
application
,
DeviceLogReader
logReader
)
{
_logReaders
?
.
forEach
((
IOSApp
application
,
DeviceLogReader
logReader
)
{
logReader
.
dispose
();
});
await
_portForwarder
?.
dispose
();
...
...
packages/flutter_tools/lib/src/ios/ios_deploy.dart
0 → 100644
View file @
704fb4cb
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:meta/meta.dart'
;
import
'package:platform/platform.dart'
;
import
'package:process/process.dart'
;
import
'../artifacts.dart'
;
import
'../base/logger.dart'
;
import
'../base/process.dart'
;
import
'../build_info.dart'
;
import
'../cache.dart'
;
import
'code_signing.dart'
;
// Error message patterns from ios-deploy output
const
String
noProvisioningProfileErrorOne
=
'Error 0xe8008015'
;
const
String
noProvisioningProfileErrorTwo
=
'Error 0xe8000067'
;
const
String
deviceLockedError
=
'e80000e2'
;
const
String
unknownAppLaunchError
=
'Error 0xe8000022'
;
class
IOSDeploy
{
IOSDeploy
({
@required
Artifacts
artifacts
,
@required
Cache
cache
,
@required
Logger
logger
,
@required
Platform
platform
,
@required
ProcessManager
processManager
,
})
:
_platform
=
platform
,
_cache
=
cache
,
_processUtils
=
ProcessUtils
(
processManager:
processManager
,
logger:
logger
),
_logger
=
logger
,
_binaryPath
=
artifacts
.
getArtifactPath
(
Artifact
.
iosDeploy
,
platform:
TargetPlatform
.
ios
);
final
Cache
_cache
;
final
String
_binaryPath
;
final
Logger
_logger
;
final
Platform
_platform
;
final
ProcessUtils
_processUtils
;
Map
<
String
,
String
>
get
iosDeployEnv
{
// Push /usr/bin to the front of PATH to pick up default system python, package 'six'.
//
// ios-deploy transitively depends on LLDB.framework, which invokes a
// Python script that uses package 'six'. LLDB.framework relies on the
// python at the front of the path, which may not include package 'six'.
// Ensure that we pick up the system install of python, which includes it.
final
Map
<
String
,
String
>
environment
=
Map
<
String
,
String
>.
from
(
_platform
.
environment
);
environment
[
'PATH'
]
=
'/usr/bin:
${environment['PATH']}
'
;
environment
.
addEntries
(<
MapEntry
<
String
,
String
>>[
_cache
.
dyLdLibEntry
]);
return
environment
;
}
/// Uninstalls the specified app bundle.
///
/// Uses ios-deploy and returns the exit code.
Future
<
int
>
uninstallApp
({
@required
String
deviceId
,
@required
String
bundleId
,
})
async
{
final
List
<
String
>
launchCommand
=
<
String
>[
_binaryPath
,
'--id'
,
deviceId
,
'--uninstall_only'
,
'--bundle_id'
,
bundleId
,
];
return
_processUtils
.
stream
(
launchCommand
,
mapFunction:
_monitorFailure
,
trace:
true
,
environment:
iosDeployEnv
,
);
}
/// Installs the specified app bundle.
///
/// Uses ios-deploy and returns the exit code.
Future
<
int
>
installApp
({
@required
String
deviceId
,
@required
String
bundlePath
,
@required
List
<
String
>
launchArguments
,
})
async
{
final
List
<
String
>
launchCommand
=
<
String
>[
_binaryPath
,
'--id'
,
deviceId
,
'--bundle'
,
bundlePath
,
'--no-wifi'
,
if
(
launchArguments
.
isNotEmpty
)
...<
String
>[
'--args'
,
launchArguments
.
join
(
' '
),
],
];
return
_processUtils
.
stream
(
launchCommand
,
mapFunction:
_monitorFailure
,
trace:
true
,
environment:
iosDeployEnv
,
);
}
/// Installs and then runs the specified app bundle.
///
/// Uses ios-deploy and returns the exit code.
Future
<
int
>
runApp
({
@required
String
deviceId
,
@required
String
bundlePath
,
@required
List
<
String
>
launchArguments
,
})
async
{
final
List
<
String
>
launchCommand
=
<
String
>[
_binaryPath
,
'--id'
,
deviceId
,
'--bundle'
,
bundlePath
,
'--no-wifi'
,
'--justlaunch'
,
if
(
launchArguments
.
isNotEmpty
)
...<
String
>[
'--args'
,
launchArguments
.
join
(
' '
),
],
];
return
_processUtils
.
stream
(
launchCommand
,
mapFunction:
_monitorFailure
,
trace:
true
,
environment:
iosDeployEnv
,
);
}
Future
<
bool
>
isAppInstalled
({
@required
String
bundleId
,
@required
String
deviceId
,
})
async
{
final
List
<
String
>
launchCommand
=
<
String
>[
_binaryPath
,
'--id'
,
deviceId
,
'--exists'
,
'--bundle_id'
,
bundleId
,
];
final
RunResult
result
=
await
_processUtils
.
run
(
launchCommand
,
environment:
iosDeployEnv
,
);
if
(
result
.
exitCode
!=
0
)
{
return
false
;
}
return
result
.
stdout
.
contains
(
bundleId
);
}
// Maps stdout line stream. Must return original line.
String
_monitorFailure
(
String
stdout
)
{
// Installation issues.
if
(
stdout
.
contains
(
noProvisioningProfileErrorOne
)
||
stdout
.
contains
(
noProvisioningProfileErrorTwo
))
{
_logger
.
printError
(
noProvisioningProfileInstruction
,
emphasis:
true
);
// Launch issues.
}
else
if
(
stdout
.
contains
(
deviceLockedError
))
{
_logger
.
printError
(
'''
═══════════════════════════════════════════════════════════════════════════════════
Your device is locked. Unlock your device first before running.
═══════════════════════════════════════════════════════════════════════════════════'''
,
emphasis:
true
);
}
else
if
(
stdout
.
contains
(
unknownAppLaunchError
))
{
_logger
.
printError
(
'''
═══════════════════════════════════════════════════════════════════════════════════
Error launching app. Try launching from within Xcode via:
open ios/Runner.xcworkspace
Your Xcode version may be too old for your iOS version.
═══════════════════════════════════════════════════════════════════════════════════'''
,
emphasis:
true
);
}
return
stdout
;
}
}
packages/flutter_tools/lib/src/ios/mac.dart
View file @
704fb4cb
...
...
@@ -91,7 +91,6 @@ Future<XcodeBuildResult> buildXcodeProject({
return
XcodeBuildResult
(
success:
false
);
}
final
XcodeProjectInfo
projectInfo
=
await
xcodeProjectInterpreter
.
getInfo
(
app
.
project
.
hostAppRoot
.
path
);
if
(!
projectInfo
.
targets
.
contains
(
'Runner'
))
{
globals
.
printError
(
'The Xcode project does not define target "Runner" which is needed by Flutter tooling.'
);
...
...
packages/flutter_tools/lib/src/macos/xcode.dart
View file @
704fb4cb
...
...
@@ -15,6 +15,7 @@ import '../base/logger.dart';
import
'../base/process.dart'
;
import
'../build_info.dart'
;
import
'../convert.dart'
;
import
'../globals.dart'
as
globals
;
import
'../ios/devices.dart'
;
import
'../ios/xcodeproj.dart'
;
import
'../reporting/reporting.dart'
;
...
...
@@ -349,6 +350,10 @@ class XCDevice {
name:
device
[
'name'
]
as
String
,
cpuArchitecture:
_cpuArchitecture
(
deviceProperties
),
sdkVersion:
_sdkVersion
(
deviceProperties
),
artifacts:
globals
.
artifacts
,
fileSystem:
globals
.
fs
,
iosDeploy:
globals
.
iosDeploy
,
platform:
globals
.
platform
,
));
}
return
devices
;
...
...
packages/flutter_tools/test/general.shard/ios/devices_test.dart
View file @
704fb4cb
...
...
@@ -12,6 +12,7 @@ import 'package:flutter_tools/src/application_package.dart';
import
'package:flutter_tools/src/artifacts.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/cache.dart'
;
import
'package:flutter_tools/src/commands/create.dart'
;
...
...
@@ -19,6 +20,7 @@ import 'package:flutter_tools/src/device.dart';
import
'package:flutter_tools/src/doctor.dart'
;
import
'package:flutter_tools/src/ios/devices.dart'
;
import
'package:flutter_tools/src/ios/mac.dart'
;
import
'package:flutter_tools/src/ios/ios_deploy.dart'
;
import
'package:flutter_tools/src/ios/ios_workflow.dart'
;
import
'package:flutter_tools/src/macos/xcode.dart'
;
import
'package:flutter_tools/src/mdns_discovery.dart'
;
...
...
@@ -40,19 +42,23 @@ class MockIOSApp extends Mock implements IOSApp {}
class
MockApplicationPackage
extends
Mock
implements
ApplicationPackage
{}
class
MockArtifacts
extends
Mock
implements
Artifacts
{}
class
MockCache
extends
Mock
implements
Cache
{}
class
MockDevicePortForwarder
extends
Mock
implements
DevicePortForwarder
{}
class
MockDirectory
extends
Mock
implements
Directory
{}
class
MockFile
extends
Mock
implements
File
{}
class
MockFileSystem
extends
Mock
implements
FileSystem
{}
class
MockForwardedPort
extends
Mock
implements
ForwardedPort
{}
class
MockIMobileDevice
extends
Mock
implements
IMobileDevice
{}
class
MockIOSDeploy
extends
Mock
implements
IOSDeploy
{}
class
Mock
DevicePortForwarder
extends
Mock
implements
DevicePortForward
er
{}
class
Mock
Logger
extends
Mock
implements
Logg
er
{}
class
MockMDnsObservatoryDiscovery
extends
Mock
implements
MDnsObservatoryDiscovery
{}
class
MockMDnsObservatoryDiscoveryResult
extends
Mock
implements
MDnsObservatoryDiscoveryResult
{}
class
MockXcode
extends
Mock
implements
Xcode
{}
class
MockFile
extends
Mock
implements
File
{}
class
MockPlatform
extends
Mock
implements
Platform
{}
class
MockPortForwarder
extends
Mock
implements
DevicePortForwarder
{}
// src/mocks.dart imports `MockProcessManager` which implements some methods, this is a full mock
class
FullMockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockUsage
extends
Mock
implements
Usage
{}
class
MockXcdevice
extends
Mock
implements
XCDevice
{}
class
MockXcode
extends
Mock
implements
Xcode
{}
void
main
(
)
{
final
FakePlatform
macPlatform
=
FakePlatform
.
fromPlatform
(
const
LocalPlatform
());
...
...
@@ -64,34 +70,187 @@ void main() {
group
(
'IOSDevice'
,
()
{
final
List
<
Platform
>
unsupportedPlatforms
=
<
Platform
>[
linuxPlatform
,
windowsPlatform
];
Artifacts
mockArtifacts
;
MockCache
mockCache
;
MockLogger
mockLogger
;
IOSDeploy
iosDeploy
;
FileSystem
mockFileSystem
;
testUsingContext
(
'successfully instantiates on Mac OS'
,
()
{
IOSDevice
(
'device-123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
macPlatform
,
setUp
(()
{
mockArtifacts
=
MockArtifacts
();
mockCache
=
MockCache
();
const
MapEntry
<
String
,
String
>
dyLdLibEntry
=
MapEntry
<
String
,
String
>(
'DYLD_LIBRARY_PATH'
,
'/path/to/libs'
);
when
(
mockCache
.
dyLdLibEntry
).
thenReturn
(
dyLdLibEntry
);
mockFileSystem
=
MockFileSystem
();
mockLogger
=
MockLogger
();
iosDeploy
=
IOSDeploy
(
artifacts:
mockArtifacts
,
cache:
mockCache
,
logger:
mockLogger
,
platform:
macPlatform
,
processManager:
FakeProcessManager
.
any
(),
);
});
testUsingContext
(
'parses major version'
,
()
{
expect
(
IOSDevice
(
'device-123'
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'1.0.0'
).
majorSdkVersion
,
1
);
expect
(
IOSDevice
(
'device-123'
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'13.1.1'
).
majorSdkVersion
,
13
);
expect
(
IOSDevice
(
'device-123'
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'10'
).
majorSdkVersion
,
10
);
expect
(
IOSDevice
(
'device-123'
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'0'
).
majorSdkVersion
,
0
);
expect
(
IOSDevice
(
'device-123'
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'bogus'
).
majorSdkVersion
,
0
);
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
macPlatform
,
testWithoutContext
(
'successfully instantiates on Mac OS'
,
()
{
IOSDevice
(
'device-123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
});
testWithoutContext
(
'parses major version'
,
()
{
expect
(
IOSDevice
(
'device-123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'1.0.0'
).
majorSdkVersion
,
1
);
expect
(
IOSDevice
(
'device-123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'13.1.1'
).
majorSdkVersion
,
13
);
expect
(
IOSDevice
(
'device-123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'10'
).
majorSdkVersion
,
10
);
expect
(
IOSDevice
(
'device-123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'0'
).
majorSdkVersion
,
0
);
expect
(
IOSDevice
(
'device-123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
cpuArchitecture:
DarwinArch
.
arm64
,
sdkVersion:
'bogus'
).
majorSdkVersion
,
0
);
});
for
(
final
Platform
platform
in
unsupportedPlatforms
)
{
test
Using
Context
(
'throws UnsupportedError exception if instantiated on
${platform.operatingSystem}
'
,
()
{
test
Without
Context
(
'throws UnsupportedError exception if instantiated on
${platform.operatingSystem}
'
,
()
{
expect
(
()
{
IOSDevice
(
'device-123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
},
()
{
IOSDevice
(
'device-123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
platform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
},
throwsAssertionError
,
);
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
platform
,
});
}
group
(
'ios-deploy wrappers'
,
()
{
const
String
appId
=
'789'
;
IOSDevice
device
;
IOSDeploy
iosDeploy
;
FullMockProcessManager
mockProcessManager
;
setUp
(()
{
mockProcessManager
=
FullMockProcessManager
();
iosDeploy
=
IOSDeploy
(
artifacts:
mockArtifacts
,
cache:
mockCache
,
logger:
mockLogger
,
platform:
macPlatform
,
processManager:
mockProcessManager
,
);
device
=
IOSDevice
(
'device-123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
});
testUsingContext
(
'isAppInstalled() catches ProcessException from ios-deploy'
,
()
async
{
final
MockIOSApp
mockApp
=
MockIOSApp
();
when
(
mockApp
.
id
).
thenReturn
(
appId
);
when
(
mockProcessManager
.
run
(
any
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
)).
thenThrow
(
const
ProcessException
(
'ios-deploy'
,
<
String
>[]));
final
bool
result
=
await
device
.
isAppInstalled
(
mockApp
);
expect
(
result
,
false
);
});
testUsingContext
(
'installApp() catches ProcessException from ios-deploy'
,
()
async
{
const
String
bundlePath
=
'/path/to/bundle'
;
final
MockIOSApp
mockApp
=
MockIOSApp
();
when
(
mockApp
.
id
).
thenReturn
(
appId
);
when
(
mockApp
.
deviceBundlePath
).
thenReturn
(
bundlePath
);
final
MockDirectory
mockDirectory
=
MockDirectory
();
when
(
mockFileSystem
.
directory
(
bundlePath
)).
thenReturn
(
mockDirectory
);
when
(
mockDirectory
.
existsSync
()).
thenReturn
(
true
);
when
(
mockProcessManager
.
start
(
any
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
)).
thenThrow
(
const
ProcessException
(
'ios-deploy'
,
<
String
>[]));
final
bool
result
=
await
device
.
installApp
(
mockApp
);
expect
(
result
,
false
);
});
testUsingContext
(
'uninstallApp() catches ProcessException from ios-deploy'
,
()
async
{
final
MockIOSApp
mockApp
=
MockIOSApp
();
when
(
mockApp
.
id
).
thenReturn
(
appId
);
when
(
mockProcessManager
.
start
(
any
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
)).
thenThrow
(
const
ProcessException
(
'ios-deploy'
,
<
String
>[]));
final
bool
result
=
await
device
.
uninstallApp
(
mockApp
);
expect
(
result
,
false
);
});
});
group
(
'.dispose()'
,
()
{
IOSDevice
device
;
MockIOSApp
appPackage1
;
...
...
@@ -103,6 +262,11 @@ void main() {
MockProcess
mockProcess3
;
IOSDevicePortForwarder
portForwarder
;
ForwardedPort
forwardedPort
;
Artifacts
mockArtifacts
;
MockCache
mockCache
;
MockLogger
mockLogger
;
IOSDeploy
iosDeploy
;
FileSystem
mockFileSystem
;
IOSDevicePortForwarder
createPortForwarder
(
ForwardedPort
forwardedPort
,
...
...
@@ -130,10 +294,29 @@ void main() {
mockProcess2
=
MockProcess
();
mockProcess3
=
MockProcess
();
forwardedPort
=
ForwardedPort
.
withContext
(
123
,
456
,
mockProcess3
);
mockArtifacts
=
MockArtifacts
();
mockCache
=
MockCache
();
mockFileSystem
=
MockFileSystem
();
iosDeploy
=
IOSDeploy
(
artifacts:
mockArtifacts
,
cache:
mockCache
,
logger:
mockLogger
,
platform:
macPlatform
,
processManager:
FakeProcessManager
.
any
(),
);
});
testUsingContext
(
' kills all log readers & port forwarders'
,
()
async
{
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
testWithoutContext
(
'kills all log readers & port forwarders'
,
()
async
{
device
=
IOSDevice
(
'123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
logReader1
=
createLogReader
(
device
,
appPackage1
,
mockProcess1
);
logReader2
=
createLogReader
(
device
,
appPackage2
,
mockProcess2
);
portForwarder
=
createPortForwarder
(
forwardedPort
,
device
);
...
...
@@ -146,8 +329,6 @@ void main() {
verify
(
mockProcess1
.
kill
());
verify
(
mockProcess2
.
kill
());
verify
(
mockProcess3
.
kill
());
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
macPlatform
,
});
});
...
...
@@ -156,6 +337,7 @@ void main() {
MockArtifacts
mockArtifacts
;
MockCache
mockCache
;
MockFileSystem
mockFileSystem
;
MockPlatform
mockPlatform
;
MockProcessManager
mockProcessManager
;
MockDeviceLogReader
mockLogReader
;
MockMDnsObservatoryDiscovery
mockMDnsObservatoryDiscovery
;
...
...
@@ -188,6 +370,8 @@ void main() {
mockCache
=
MockCache
();
when
(
mockCache
.
dyLdLibEntry
).
thenReturn
(
libraryEntry
);
mockFileSystem
=
MockFileSystem
();
mockPlatform
=
MockPlatform
();
when
(
mockPlatform
.
isMacOS
).
thenReturn
(
true
);
mockMDnsObservatoryDiscovery
=
MockMDnsObservatoryDiscovery
();
mockProcessManager
=
MockProcessManager
();
mockLogReader
=
MockDeviceLogReader
();
...
...
@@ -254,17 +438,43 @@ void main() {
});
testUsingContext
(
'disposing device disposes the portForwarder'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
'123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
device
.
portForwarder
=
mockPortForwarder
;
device
.
setLogReader
(
mockApp
,
mockLogReader
);
await
device
.
dispose
();
verify
(
mockPortForwarder
.
dispose
()).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
macPlatform
,
});
testUsingContext
(
' succeeds in debug mode via mDNS'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
testUsingContext
(
'succeeds in debug mode via mDNS'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
mockIosDeploy
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
when
(
mockIosDeploy
.
installApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
<
String
>[],
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
when
(
mockIosDeploy
.
runApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
anyNamed
(
'launchArguments'
),
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
device
.
portForwarder
=
mockPortForwarder
;
device
.
setLogReader
(
mockApp
,
mockLogReader
);
final
Uri
uri
=
Uri
(
...
...
@@ -298,10 +508,19 @@ void main() {
// By default, the .forward() method will try every port between 1024
// and 65535; this test verifies we are killing iproxy processes when
// we timeout on a port
testUsingContext
(
'
.forward() will kill iproxy processes before invoking a second'
,
()
async
{
testUsingContext
(
'.forward() will kill iproxy processes before invoking a second'
,
()
async
{
const
String
deviceId
=
'123'
;
const
int
devicePort
=
456
;
final
IOSDevice
device
=
IOSDevice
(
deviceId
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
deviceId
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
iosDeploy
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
final
IOSDevicePortForwarder
portForwarder
=
IOSDevicePortForwarder
(
device
);
bool
firstRun
=
true
;
final
MockProcess
successProcess
=
MockProcess
(
...
...
@@ -334,8 +553,25 @@ void main() {
Usage:
()
=>
mockUsage
,
});
testUsingContext
(
' succeeds in debug mode when mDNS fails by falling back to manual protocol discovery'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
testUsingContext
(
'succeeds in debug mode when mDNS fails by falling back to manual protocol discovery'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
mockIosDeploy
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
when
(
mockIosDeploy
.
installApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
<
String
>[])
).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
when
(
mockIosDeploy
.
runApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
anyNamed
(
'launchArguments'
),
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
device
.
portForwarder
=
mockPortForwarder
;
device
.
setLogReader
(
mockApp
,
mockLogReader
);
// Now that the reader is used, start writing messages to it.
...
...
@@ -351,10 +587,10 @@ void main() {
debuggingOptions:
DebuggingOptions
.
enabled
(
const
BuildInfo
(
BuildMode
.
debug
,
null
,
treeShakeIcons:
false
)),
platformArgs:
<
String
,
dynamic
>{},
);
verify
(
mockUsage
.
sendEvent
(
'ios-handshake'
,
'mdns-failure'
)).
called
(
1
);
verify
(
mockUsage
.
sendEvent
(
'ios-handshake'
,
'fallback-success'
)).
called
(
1
);
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isTrue
);
verify
(
mockUsage
.
sendEvent
(
'ios-handshake'
,
'mdns-failure'
)).
called
(
1
);
verify
(
mockUsage
.
sendEvent
(
'ios-handshake'
,
'fallback-success'
)).
called
(
1
);
expect
(
await
device
.
stopApp
(
mockApp
),
isFalse
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
...
...
@@ -366,8 +602,27 @@ void main() {
Usage:
()
=>
mockUsage
,
});
testUsingContext
(
' fails in debug mode when mDNS fails and when Observatory URI is malformed'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
testUsingContext
(
'fails in debug mode when mDNS fails and when Observatory URI is malformed'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
mockIosDeploy
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
when
(
mockIosDeploy
.
installApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
<
String
>[],
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
when
(
mockIosDeploy
.
runApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
anyNamed
(
'launchArguments'
),
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
device
.
portForwarder
=
mockPortForwarder
;
device
.
setLogReader
(
mockApp
,
mockLogReader
);
...
...
@@ -384,6 +639,8 @@ void main() {
debuggingOptions:
DebuggingOptions
.
enabled
(
const
BuildInfo
(
BuildMode
.
debug
,
null
,
treeShakeIcons:
false
)),
platformArgs:
<
String
,
dynamic
>{},
);
expect
(
launchResult
.
started
,
isFalse
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
verify
(
mockUsage
.
sendEvent
(
'ios-handshake'
,
'failure'
,
...
...
@@ -392,8 +649,6 @@ void main() {
)).
called
(
1
);
verify
(
mockUsage
.
sendEvent
(
'ios-handshake'
,
'mdns-failure'
)).
called
(
1
);
verify
(
mockUsage
.
sendEvent
(
'ios-handshake'
,
'fallback-failure'
)).
called
(
1
);
expect
(
launchResult
.
started
,
isFalse
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
Cache:
()
=>
mockCache
,
...
...
@@ -405,25 +660,57 @@ void main() {
});
testUsingContext
(
'succeeds in release mode'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
fileSystem:
mockFileSystem
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
platform:
mockPlatform
,
artifacts:
mockArtifacts
,
iosDeploy:
mockIosDeploy
,
);
when
(
mockIosDeploy
.
installApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
<
String
>[],
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
when
(
mockIosDeploy
.
runApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
anyNamed
(
'launchArguments'
),
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
final
LaunchResult
launchResult
=
await
device
.
startApp
(
mockApp
,
prebuiltApplication:
true
,
debuggingOptions:
DebuggingOptions
.
disabled
(
const
BuildInfo
(
BuildMode
.
release
,
null
,
treeShakeIcons:
false
)),
platformArgs:
<
String
,
dynamic
>{},
);
verify
(
mockIosDeploy
.
installApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
<
String
>[],
));
verify
(
mockIosDeploy
.
runApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
anyNamed
(
'launchArguments'
),
));
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
expect
(
await
device
.
stopApp
(
mockApp
),
isFalse
);
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
Cache:
()
=>
mockCache
,
FileSystem:
()
=>
mockFileSystem
,
Platform:
()
=>
macPlatform
,
ProcessManager:
()
=>
mockProcessManager
,
});
testUsingContext
(
'succeeds with --cache-sksl'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
mockIosDeploy
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
device
.
setLogReader
(
mockApp
,
mockLogReader
);
final
Uri
uri
=
Uri
(
scheme:
'http'
,
...
...
@@ -443,6 +730,11 @@ void main() {
args
=
inv
.
namedArguments
[
const
Symbol
(
'launchArguments'
)]
as
List
<
String
>;
return
Future
<
int
>.
value
(
0
);
});
when
(
mockIosDeploy
.
installApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
anyNamed
(
'launchArguments'
),
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
final
LaunchResult
launchResult
=
await
device
.
startApp
(
mockApp
,
prebuiltApplication:
true
,
...
...
@@ -467,7 +759,16 @@ void main() {
});
testUsingContext
(
'succeeds with --device-vmservice-port'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
artifacts:
mockArtifacts
,
fileSystem:
mockFileSystem
,
platform:
macPlatform
,
iosDeploy:
mockIosDeploy
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
device
.
setLogReader
(
mockApp
,
mockLogReader
);
final
Uri
uri
=
Uri
(
scheme:
'http'
,
...
...
@@ -488,6 +789,11 @@ void main() {
return
Future
<
int
>.
value
(
0
);
});
when
(
mockIosDeploy
.
installApp
(
deviceId:
device
.
id
,
bundlePath:
anyNamed
(
'bundlePath'
),
launchArguments:
anyNamed
(
'launchArguments'
),
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
int
>.
value
(
0
));
final
LaunchResult
launchResult
=
await
device
.
startApp
(
mockApp
,
prebuiltApplication:
true
,
debuggingOptions:
DebuggingOptions
.
enabled
(
...
...
@@ -581,7 +887,16 @@ void main() {
final
IOSApp
app
=
await
AbsoluteBuildableIOSApp
.
fromProject
(
FlutterProject
.
fromDirectory
(
projectDir
).
ios
);
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
artifacts:
mockArtifacts
,
fileSystem:
globals
.
fs
,
platform:
macPlatform
,
iosDeploy:
mockIosDeploy
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
// Pre-create the expected build products.
targetBuildDir
.
createSync
(
recursive:
true
);
...
...
@@ -611,7 +926,6 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
DoctorValidatorsProvider:
()
=>
FakeIosDoctorProvider
(),
IMobileDevice:
()
=>
mockIMobileDevice
,
IOSDeploy:
()
=>
mockIosDeploy
,
Platform:
()
=>
macPlatform
,
ProcessManager:
()
=>
mockProcessManager
,
});
...
...
@@ -658,102 +972,154 @@ void main() {
});
group
(
'Process calls'
,
()
{
const
String
bundlePath
=
'/path/to/bundle'
;
FileSystem
fs
;
MockDirectory
directory
;
MockIOSApp
mockApp
;
MockArtifacts
mockArtifacts
;
MockCache
mockCache
;
MockFileSystem
mockFileSystem
;
MockProcessManager
mockProcessManager
;
const
String
installerPath
=
'/path/to/ideviceinstaller'
;
MockLogger
mockLogger
;
MockPlatform
mockPlatform
;
FullMockProcessManager
mockProcessManager
;
const
String
iosDeployPath
=
'/path/to/ios-deploy'
;
const
String
appId
=
'789'
;
const
MapEntry
<
String
,
String
>
libraryEntry
=
MapEntry
<
String
,
String
>(
'DYLD_LIBRARY_PATH'
,
'/path/to/libraries'
,
);
final
Map
<
String
,
String
>
env
=
Map
<
String
,
String
>.
fromEntries
(
<
MapEntry
<
String
,
String
>>[
libraryEntry
]
);
IOSDeploy
iosDeploy
;
setUp
(()
{
mockFileSystem
=
MockFileSystem
();
directory
=
MockDirectory
();
when
(
mockFileSystem
.
directory
(
bundlePath
)).
thenReturn
(
directory
);
mockApp
=
MockIOSApp
();
when
(
mockApp
.
id
).
thenReturn
(
appId
);
when
(
mockApp
.
deviceBundlePath
).
thenReturn
(
bundlePath
);
when
(
directory
.
existsSync
()).
thenReturn
(
true
);
when
(
directory
.
path
).
thenReturn
(
bundlePath
);
mockArtifacts
=
MockArtifacts
();
mockCache
=
MockCache
();
mockLogger
=
MockLogger
();
mockPlatform
=
MockPlatform
();
when
(
mockPlatform
.
environment
).
thenReturn
(<
String
,
String
>{});
when
(
mockPlatform
.
isMacOS
).
thenReturn
(
true
);
mockProcessManager
=
FullMockProcessManager
();
when
(
mockArtifacts
.
getArtifactPath
(
Artifact
.
iosDeploy
,
platform:
anyNamed
(
'platform'
),
),
).
thenReturn
(
iosDeployPath
);
iosDeploy
=
IOSDeploy
(
artifacts:
mockArtifacts
,
cache:
mockCache
,
logger:
mockLogger
,
platform:
mockPlatform
,
processManager:
mockProcessManager
,
);
when
(
mockCache
.
dyLdLibEntry
).
thenReturn
(
libraryEntry
);
mockFileSystem
=
MockFileSystem
();
final
MemoryFileSystem
memoryFileSystem
=
MemoryFileSystem
();
when
(
mockFileSystem
.
currentDirectory
)
.
thenReturn
(
memoryFileSystem
.
currentDirectory
);
mockProcessManager
=
MockProcessManager
();
when
(
mockArtifacts
.
getArtifactPath
(
Artifact
.
ideviceinstaller
,
platform:
anyNamed
(
'platform'
),
),
).
thenReturn
(
installerPath
);
});
testUsingContext
(
'installApp() invokes process with correct environment'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
const
String
bundlePath
=
'/path/to/bundle'
;
final
List
<
String
>
args
=
<
String
>[
installerPath
,
'-i'
,
bundlePath
];
when
(
mockApp
.
deviceBundlePath
).
thenReturn
(
bundlePath
);
final
MockDirectory
directory
=
MockDirectory
();
testWithoutContext
(
'installApp() calls ios-deploy'
,
()
async
{
when
(
mockFileSystem
.
directory
(
bundlePath
)).
thenReturn
(
directory
);
when
(
directory
.
existsSync
()).
thenReturn
(
true
);
when
(
mockProcessManager
.
run
(
args
,
environment:
env
))
.
thenAnswer
(
(
_
)
=>
Future
<
ProcessResult
>.
value
(
ProcessResult
(
1
,
0
,
''
,
''
))
);
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
fileSystem:
mockFileSystem
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
platform:
mockPlatform
,
artifacts:
mockArtifacts
,
iosDeploy:
iosDeploy
,
);
final
List
<
String
>
args
=
<
String
>[
iosDeployPath
,
'--id'
,
device
.
id
,
'--bundle'
,
bundlePath
,
'--no-wifi'
,
];
when
(
mockProcessManager
.
start
(
any
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
))).
thenAnswer
((
Invocation
invocation
)
{
return
Future
<
Process
>.
value
(
createMockProcess
());
});
await
device
.
installApp
(
mockApp
);
verify
(
mockProcessManager
.
run
(
args
,
environment:
env
));
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
Cache:
()
=>
mockCache
,
FileSystem:
()
=>
mockFileSystem
,
Platform:
()
=>
macPlatform
,
ProcessManager:
()
=>
mockProcessManager
,
});
testUsingContext
(
'isAppInstalled() invokes process with correct environment'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
List
<
String
>
args
=
<
String
>[
installerPath
,
'--list-apps'
];
when
(
mockProcessManager
.
run
(
args
,
environment:
env
))
.
thenAnswer
(
(
_
)
=>
Future
<
ProcessResult
>.
value
(
ProcessResult
(
1
,
0
,
''
,
''
))
);
when
(
mockApp
.
id
).
thenReturn
(
appId
);
await
device
.
isAppInstalled
(
mockApp
);
verify
(
mockProcessManager
.
run
(
args
,
environment:
env
));
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
Cache:
()
=>
mockCache
,
Platform:
()
=>
macPlatform
,
ProcessManager:
()
=>
mockProcessManager
,
final
List
<
String
>
invocationArguments
=
verify
(
mockProcessManager
.
start
(
captureAny
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
)).
captured
.
first
as
List
<
String
>;
expect
(
invocationArguments
,
args
);
});
testUsingContext
(
'uninstallApp() invokes process with correct environment'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
List
<
String
>
args
=
<
String
>[
installerPath
,
'-U'
,
appId
];
when
(
mockApp
.
id
).
thenReturn
(
appId
);
when
(
mockProcessManager
.
run
(
args
,
environment:
env
))
.
thenAnswer
(
(
_
)
=>
Future
<
ProcessResult
>.
value
(
ProcessResult
(
1
,
0
,
''
,
''
))
);
testWithoutContext
(
'uninstallApp() calls ios-deploy'
,
()
async
{
final
IOSDevice
device
=
IOSDevice
(
'123'
,
name:
'iPhone 1'
,
fileSystem:
fs
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
platform:
mockPlatform
,
artifacts:
mockArtifacts
,
iosDeploy:
iosDeploy
,
);
final
List
<
String
>
args
=
<
String
>[
iosDeployPath
,
'--id'
,
device
.
id
,
'--uninstall_only'
,
'--bundle_id'
,
appId
,
];
when
(
mockProcessManager
.
start
(
args
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
))).
thenAnswer
((
Invocation
invocation
)
{
return
Future
<
Process
>.
value
(
createMockProcess
());
});
await
device
.
uninstallApp
(
mockApp
);
verify
(
mockProcessManager
.
run
(
args
,
environment:
env
));
},
overrides:
<
Type
,
Generator
>{
Artifacts:
()
=>
mockArtifacts
,
Cache:
()
=>
mockCache
,
Platform:
()
=>
macPlatform
,
ProcessManager:
()
=>
mockProcessManager
,
final
List
<
String
>
invocationArguments
=
verify
(
mockProcessManager
.
start
(
captureAny
,
workingDirectory:
anyNamed
(
'workingDirectory'
)
,
environment:
anyNamed
(
'environment'
)
,
)).
captured
.
first
as
List
<
String
>;
expect
(
invocationArguments
,
args
);
});
});
});
group
(
'getAttachedDevices'
,
()
{
MockXcdevice
mockXcdevice
;
MockArtifacts
mockArtifacts
;
MockCache
mockCache
;
MockFileSystem
mockFileSystem
;
MockLogger
mockLogger
;
FullMockProcessManager
mockProcessManager
;
IOSDeploy
iosDeploy
;
setUp
(()
{
mockXcdevice
=
MockXcdevice
();
mockArtifacts
=
MockArtifacts
();
mockCache
=
MockCache
();
mockLogger
=
MockLogger
();
mockFileSystem
=
MockFileSystem
();
mockProcessManager
=
FullMockProcessManager
();
iosDeploy
=
IOSDeploy
(
artifacts:
mockArtifacts
,
cache:
mockCache
,
logger:
mockLogger
,
platform:
macPlatform
,
processManager:
mockProcessManager
,
);
});
final
List
<
Platform
>
unsupportedPlatforms
=
<
Platform
>[
linuxPlatform
,
windowsPlatform
];
...
...
@@ -767,17 +1133,25 @@ void main() {
});
}
test
Using
Context
(
'returns attached devices'
,
()
async
{
test
Without
Context
(
'returns attached devices'
,
()
async
{
when
(
mockXcdevice
.
isInstalled
).
thenReturn
(
true
);
final
IOSDevice
device
=
IOSDevice
(
'd83d5bc53967baa0ee18626ba87b6254b2ab5418'
,
name:
'Paired iPhone'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
'd83d5bc53967baa0ee18626ba87b6254b2ab5418'
,
name:
'Paired iPhone'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
artifacts:
mockArtifacts
,
iosDeploy:
iosDeploy
,
platform:
macPlatform
,
fileSystem:
mockFileSystem
,
);
when
(
mockXcdevice
.
getAvailableTetheredIOSDevices
())
.
thenAnswer
((
Invocation
invocation
)
=>
Future
<
List
<
IOSDevice
>>.
value
(<
IOSDevice
>[
device
]));
final
List
<
IOSDevice
>
devices
=
await
IOSDevice
.
getAttachedDevices
(
macPlatform
,
mockXcdevice
);
expect
(
devices
,
hasLength
(
1
));
expect
(
identical
(
devices
.
first
,
device
),
isTrue
);
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
macPlatform
,
});
});
...
...
@@ -820,13 +1194,32 @@ void main() {
expect
(
decoded
,
r'I \M-b\M^O syslog!'
);
});
});
group
(
'logging'
,
()
{
MockIMobileDevice
mockIMobileDevice
;
MockIosProject
mockIosProject
;
MockArtifacts
mockArtifacts
;
MockCache
mockCache
;
MockFileSystem
mockFileSystem
;
MockLogger
mockLogger
;
FullMockProcessManager
mockProcessManager
;
IOSDeploy
iosDeploy
;
setUp
(()
{
mockIMobileDevice
=
MockIMobileDevice
();
mockIosProject
=
MockIosProject
();
mockArtifacts
=
MockArtifacts
();
mockCache
=
MockCache
();
mockLogger
=
MockLogger
();
mockFileSystem
=
MockFileSystem
();
mockProcessManager
=
FullMockProcessManager
();
iosDeploy
=
IOSDeploy
(
artifacts:
mockArtifacts
,
cache:
mockCache
,
logger:
mockLogger
,
platform:
macPlatform
,
processManager:
mockProcessManager
,
);
});
testUsingContext
(
'suppresses non-Flutter lines from output'
,
()
async
{
...
...
@@ -843,7 +1236,16 @@ Runner(UIKit)[297] <Notice>: E is for enpitsu"
return
Future
<
Process
>.
value
(
mockProcess
);
});
final
IOSDevice
device
=
IOSDevice
(
'123456'
,
name:
'iPhone 1'
,
sdkVersion:
'10.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
'123456'
,
name:
'iPhone 1'
,
sdkVersion:
'10.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
artifacts:
mockArtifacts
,
iosDeploy:
iosDeploy
,
platform:
macPlatform
,
fileSystem:
mockFileSystem
,
);
final
DeviceLogReader
logReader
=
device
.
getLogReader
(
app:
await
BuildableIOSApp
.
fromProject
(
mockIosProject
),
);
...
...
@@ -869,7 +1271,16 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
return
Future
<
Process
>.
value
(
mockProcess
);
});
final
IOSDevice
device
=
IOSDevice
(
'123456'
,
name:
'iPhone 1'
,
sdkVersion:
'10.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
final
IOSDevice
device
=
IOSDevice
(
'123456'
,
name:
'iPhone 1'
,
sdkVersion:
'10.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
artifacts:
mockArtifacts
,
iosDeploy:
iosDeploy
,
platform:
macPlatform
,
fileSystem:
mockFileSystem
,
);
final
DeviceLogReader
logReader
=
device
.
getLogReader
(
app:
await
BuildableIOSApp
.
fromProject
(
mockIosProject
),
);
...
...
@@ -887,47 +1298,97 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
Platform:
()
=>
macPlatform
,
});
});
testUsingContext
(
'IOSDevice.isSupportedForProject is true on module project'
,
()
async
{
globals
.
fs
.
file
(
'pubspec.yaml'
)
..
createSync
()
..
writeAsStringSync
(
r''
'
name: example
flutter:
module: {}
'''
);
globals
.
fs
.
file
(
'.packages'
).
createSync
();
final
FlutterProject
flutterProject
=
FlutterProject
.
current
();
expect
(
IOSDevice
(
'test'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
).
isSupportedForProject
(
flutterProject
),
true
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
macPlatform
,
});
testUsingContext
(
'IOSDevice.isSupportedForProject is true with editable host app'
,
()
async
{
globals
.
fs
.
file
(
'pubspec.yaml'
).
createSync
();
globals
.
fs
.
file
(
'.packages'
).
createSync
();
globals
.
fs
.
directory
(
'ios'
).
createSync
();
final
FlutterProject
flutterProject
=
FlutterProject
.
current
();
expect
(
IOSDevice
(
'test'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
).
isSupportedForProject
(
flutterProject
),
true
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
macPlatform
,
});
testUsingContext
(
'IOSDevice.isSupportedForProject is false with no host app and no module'
,
()
async
{
globals
.
fs
.
file
(
'pubspec.yaml'
).
createSync
();
globals
.
fs
.
file
(
'.packages'
).
createSync
();
final
FlutterProject
flutterProject
=
FlutterProject
.
current
();
group
(
'isSupportedForProject'
,
()
{
Artifacts
mockArtifacts
;
MockCache
mockCache
;
MockLogger
mockLogger
;
IOSDeploy
iosDeploy
;
setUp
(()
{
mockArtifacts
=
MockArtifacts
();
mockCache
=
MockCache
();
iosDeploy
=
IOSDeploy
(
artifacts:
mockArtifacts
,
cache:
mockCache
,
logger:
mockLogger
,
platform:
macPlatform
,
processManager:
FakeProcessManager
.
any
(),
);
});
expect
(
IOSDevice
(
'test'
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
).
isSupportedForProject
(
flutterProject
),
false
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
macPlatform
,
testUsingContext
(
'is true on module project'
,
()
async
{
globals
.
fs
.
file
(
'pubspec.yaml'
)
..
createSync
()
..
writeAsStringSync
(
r''
'
name: example
flutter:
module: {}
'''
);
globals
.
fs
.
file
(
'.packages'
).
createSync
();
final
FlutterProject
flutterProject
=
FlutterProject
.
current
();
final
IOSDevice
device
=
IOSDevice
(
'test'
,
artifacts:
mockArtifacts
,
fileSystem:
globals
.
fs
,
iosDeploy:
iosDeploy
,
platform:
globals
.
platform
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
);
expect
(
device
.
isSupportedForProject
(
flutterProject
),
true
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
macPlatform
,
});
testUsingContext
(
'is true with editable host app'
,
()
async
{
globals
.
fs
.
file
(
'pubspec.yaml'
).
createSync
();
globals
.
fs
.
file
(
'.packages'
).
createSync
();
globals
.
fs
.
directory
(
'ios'
).
createSync
();
final
FlutterProject
flutterProject
=
FlutterProject
.
current
();
final
IOSDevice
device
=
IOSDevice
(
'test'
,
artifacts:
mockArtifacts
,
fileSystem:
globals
.
fs
,
iosDeploy:
iosDeploy
,
platform:
globals
.
platform
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
expect
(
device
.
isSupportedForProject
(
flutterProject
),
true
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
macPlatform
,
});
testUsingContext
(
'is false with no host app and no module'
,
()
async
{
globals
.
fs
.
file
(
'pubspec.yaml'
).
createSync
();
globals
.
fs
.
file
(
'.packages'
).
createSync
();
final
FlutterProject
flutterProject
=
FlutterProject
.
current
();
final
IOSDevice
device
=
IOSDevice
(
'test'
,
artifacts:
mockArtifacts
,
fileSystem:
globals
.
fs
,
iosDeploy:
iosDeploy
,
platform:
globals
.
platform
,
name:
'iPhone 1'
,
sdkVersion:
'13.3'
,
cpuArchitecture:
DarwinArch
.
arm64
,
);
expect
(
device
.
isSupportedForProject
(
flutterProject
),
false
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Platform:
()
=>
macPlatform
,
});
});
}
...
...
packages/flutter_tools/test/general.shard/ios/ios_deploy_test.dart
0 → 100644
View file @
704fb4cb
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:io'
show
Process
;
import
'package:flutter_tools/src/artifacts.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/cache.dart'
;
import
'package:flutter_tools/src/ios/ios_deploy.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:platform/platform.dart'
;
import
'package:process/process.dart'
;
import
'../../src/common.dart'
;
import
'../../src/mocks.dart'
;
class
MockArtifacts
extends
Mock
implements
Artifacts
{}
class
MockCache
extends
Mock
implements
Cache
{}
class
MockLogger
extends
Mock
implements
Logger
{}
class
MockPlatform
extends
Mock
implements
Platform
{}
class
MockProcess
extends
Mock
implements
Process
{}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
void
main
(
)
{
group
(
'IOSDeploy()'
,
()
{
Artifacts
mockArtifacts
;
Cache
mockCache
;
IOSDeploy
iosDeploy
;
Logger
mockLogger
;
Platform
mockPlatform
;
ProcessManager
mockProcessManager
;
const
String
iosDeployPath
=
'/path/to/ios-deploy'
;
const
String
deviceId
=
'123'
;
const
String
bundleId
=
'com.example.app'
;
setUp
(()
{
mockArtifacts
=
MockArtifacts
();
when
(
mockArtifacts
.
getArtifactPath
(
Artifact
.
iosDeploy
,
platform:
TargetPlatform
.
ios
))
.
thenReturn
(
iosDeployPath
);
mockCache
=
MockCache
();
const
MapEntry
<
String
,
String
>
mapEntry
=
MapEntry
<
String
,
String
>(
'DYLD_LIBRARY_PATH'
,
'/path/to/libs'
);
when
(
mockCache
.
dyLdLibEntry
).
thenReturn
(
mapEntry
);
mockLogger
=
MockLogger
();
mockPlatform
=
MockPlatform
();
when
(
mockPlatform
.
environment
).
thenReturn
(<
String
,
String
>{
'PATH'
:
'/usr/local/bin:/usr/bin'
,
});
mockProcessManager
=
MockProcessManager
();
iosDeploy
=
IOSDeploy
(
artifacts:
mockArtifacts
,
cache:
mockCache
,
logger:
mockLogger
,
platform:
mockPlatform
,
processManager:
mockProcessManager
,
);
});
testWithoutContext
(
'iosDeployEnv returns path with /usr/bin first'
,
()
{
final
Map
<
String
,
String
>
env
=
iosDeploy
.
iosDeployEnv
;
expect
(
env
[
'PATH'
].
startsWith
(
'/usr/bin'
),
true
);
});
testWithoutContext
(
'uninstallApp() calls ios-deploy with correct arguments and returns 0 on success'
,
()
async
{
final
List
<
String
>
args
=
<
String
>[
iosDeployPath
,
'--id'
,
deviceId
,
'--uninstall_only'
,
'--bundle_id'
,
bundleId
,
];
when
(
mockProcessManager
.
start
(
args
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
Process
>.
value
(
createMockProcess
(
exitCode:
0
)));
final
int
exitCode
=
await
iosDeploy
.
uninstallApp
(
deviceId:
deviceId
,
bundleId:
bundleId
,
);
verify
(
mockProcessManager
.
start
(
args
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
));
expect
(
exitCode
,
0
);
});
testWithoutContext
(
'uninstallApp() returns non-zero exit code when ios-deploy does the same'
,
()
async
{
final
List
<
String
>
args
=
<
String
>[
iosDeployPath
,
'--id'
,
deviceId
,
'--uninstall_only'
,
'--bundle_id'
,
bundleId
,
];
when
(
mockProcessManager
.
start
(
args
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
)).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
Process
>.
value
(
createMockProcess
(
exitCode:
1
)));
final
int
exitCode
=
await
iosDeploy
.
uninstallApp
(
deviceId:
deviceId
,
bundleId:
bundleId
,
);
verify
(
mockProcessManager
.
start
(
args
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
));
expect
(
exitCode
,
1
);
});
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment