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
b00f1c45
Unverified
Commit
b00f1c45
authored
May 04, 2023
by
chunhtai
Committed by
GitHub
May 04, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding vmservice to get iOS app settings (#123156)
fixes
https://github.com/flutter/flutter/issues/120405
parent
529b919f
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
462 additions
and
189 deletions
+462
-189
build_ios.dart
packages/flutter_tools/lib/src/commands/build_ios.dart
+5
-5
intellij_validator.dart
...es/flutter_tools/lib/src/intellij/intellij_validator.dart
+2
-2
application_package.dart
packages/flutter_tools/lib/src/ios/application_package.dart
+1
-1
devices.dart
packages/flutter_tools/lib/src/ios/devices.dart
+1
-1
plist_parser.dart
packages/flutter_tools/lib/src/ios/plist_parser.dart
+8
-4
simulators.dart
packages/flutter_tools/lib/src/ios/simulators.dart
+1
-1
xcodeproj.dart
packages/flutter_tools/lib/src/ios/xcodeproj.dart
+23
-2
flutter_application_migration.dart
...b/src/macos/migrations/flutter_application_migration.dart
+1
-1
vmservice.dart
packages/flutter_tools/lib/src/vmservice.dart
+20
-0
xcode_project.dart
packages/flutter_tools/lib/src/xcode_project.dart
+128
-24
build_ipa_test.dart
...er_tools/test/commands.shard/hermetic/build_ipa_test.dart
+2
-2
macos_project_migration_test.dart
...est/general.shard/macos/macos_project_migration_test.dart
+4
-4
project_test.dart
packages/flutter_tools/test/general.shard/project_test.dart
+235
-115
resident_web_runner_test.dart
...er_tools/test/general.shard/resident_web_runner_test.dart
+4
-0
plist_parser_test.dart
...utter_tools/test/integration.shard/plist_parser_test.dart
+25
-25
fakes.dart
packages/flutter_tools/test/src/fakes.dart
+2
-2
No files found.
packages/flutter_tools/lib/src/commands/build_ios.dart
View file @
b00f1c45
...
@@ -376,11 +376,11 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
...
@@ -376,11 +376,11 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
final
Map
<
String
,
String
?>
xcodeProjectSettingsMap
=
<
String
,
String
?>{};
final
Map
<
String
,
String
?>
xcodeProjectSettingsMap
=
<
String
,
String
?>{};
xcodeProjectSettingsMap
[
'Version Number'
]
=
globals
.
plistParser
.
get
StringValueFromFile
(
plistPath
,
PlistParser
.
kCFBundleShortVersionStringKey
);
xcodeProjectSettingsMap
[
'Version Number'
]
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
plistPath
,
PlistParser
.
kCFBundleShortVersionStringKey
);
xcodeProjectSettingsMap
[
'Build Number'
]
=
globals
.
plistParser
.
get
StringValueFromFile
(
plistPath
,
PlistParser
.
kCFBundleVersionKey
);
xcodeProjectSettingsMap
[
'Build Number'
]
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
plistPath
,
PlistParser
.
kCFBundleVersionKey
);
xcodeProjectSettingsMap
[
'Display Name'
]
=
globals
.
plistParser
.
get
StringValueFromFile
(
plistPath
,
PlistParser
.
kCFBundleDisplayNameKey
);
xcodeProjectSettingsMap
[
'Display Name'
]
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
plistPath
,
PlistParser
.
kCFBundleDisplayNameKey
);
xcodeProjectSettingsMap
[
'Deployment Target'
]
=
globals
.
plistParser
.
get
StringValueFromFile
(
plistPath
,
PlistParser
.
kMinimumOSVersionKey
);
xcodeProjectSettingsMap
[
'Deployment Target'
]
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
plistPath
,
PlistParser
.
kMinimumOSVersionKey
);
xcodeProjectSettingsMap
[
'Bundle Identifier'
]
=
globals
.
plistParser
.
get
StringValueFromFile
(
plistPath
,
PlistParser
.
kCFBundleIdentifierKey
);
xcodeProjectSettingsMap
[
'Bundle Identifier'
]
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
plistPath
,
PlistParser
.
kCFBundleIdentifierKey
);
final
List
<
ValidationMessage
>
validationMessages
=
xcodeProjectSettingsMap
.
entries
.
map
((
MapEntry
<
String
,
String
?>
entry
)
{
final
List
<
ValidationMessage
>
validationMessages
=
xcodeProjectSettingsMap
.
entries
.
map
((
MapEntry
<
String
,
String
?>
entry
)
{
final
String
title
=
entry
.
key
;
final
String
title
=
entry
.
key
;
...
...
packages/flutter_tools/lib/src/intellij/intellij_validator.dart
View file @
b00f1c45
...
@@ -494,7 +494,7 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
...
@@ -494,7 +494,7 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
@override
@override
String
get
version
{
String
get
version
{
return
_version
??=
_plistParser
.
get
StringValueFromFile
(
return
_version
??=
_plistParser
.
get
ValueFromFile
<
String
>
(
plistFile
,
plistFile
,
PlistParser
.
kCFBundleShortVersionStringKey
,
PlistParser
.
kCFBundleShortVersionStringKey
,
)
??
'unknown'
;
)
??
'unknown'
;
...
@@ -508,7 +508,7 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
...
@@ -508,7 +508,7 @@ class IntelliJValidatorOnMac extends IntelliJValidator {
}
}
final
String
?
altLocation
=
_plistParser
final
String
?
altLocation
=
_plistParser
.
get
StringValueFromFile
(
plistFile
,
'JetBrainsToolboxApp'
);
.
get
ValueFromFile
<
String
>
(
plistFile
,
'JetBrainsToolboxApp'
);
if
(
altLocation
!=
null
)
{
if
(
altLocation
!=
null
)
{
_pluginsPath
=
'
$altLocation
.plugins'
;
_pluginsPath
=
'
$altLocation
.plugins'
;
...
...
packages/flutter_tools/lib/src/ios/application_package.dart
View file @
b00f1c45
...
@@ -58,7 +58,7 @@ abstract class IOSApp extends ApplicationPackage {
...
@@ -58,7 +58,7 @@ abstract class IOSApp extends ApplicationPackage {
globals
.
printError
(
'Invalid prebuilt iOS app. Does not contain Info.plist.'
);
globals
.
printError
(
'Invalid prebuilt iOS app. Does not contain Info.plist.'
);
return
null
;
return
null
;
}
}
final
String
?
id
=
globals
.
plistParser
.
get
StringValueFromFile
(
final
String
?
id
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
plistPath
,
plistPath
,
PlistParser
.
kCFBundleIdentifierKey
,
PlistParser
.
kCFBundleIdentifierKey
,
);
);
...
...
packages/flutter_tools/lib/src/ios/devices.dart
View file @
b00f1c45
...
@@ -451,7 +451,7 @@ class IOSDevice extends Device {
...
@@ -451,7 +451,7 @@ class IOSDevice extends Device {
_logger
.
printError
(
''
);
_logger
.
printError
(
''
);
return
LaunchResult
.
failed
();
return
LaunchResult
.
failed
();
}
}
packageId
=
buildResult
.
xcodeBuildExecution
?.
buildSettings
[
'PRODUCT_BUNDLE_IDENTIFIER'
];
packageId
=
buildResult
.
xcodeBuildExecution
?.
buildSettings
[
IosProject
.
kProductBundleIdKey
];
}
}
packageId
??=
package
.
id
;
packageId
??=
package
.
id
;
...
...
packages/flutter_tools/lib/src/ios/plist_parser.dart
View file @
b00f1c45
...
@@ -24,6 +24,7 @@ class PlistParser {
...
@@ -24,6 +24,7 @@ class PlistParser {
final
Logger
_logger
;
final
Logger
_logger
;
final
ProcessUtils
_processUtils
;
final
ProcessUtils
_processUtils
;
// info.pList keys
static
const
String
kCFBundleIdentifierKey
=
'CFBundleIdentifier'
;
static
const
String
kCFBundleIdentifierKey
=
'CFBundleIdentifier'
;
static
const
String
kCFBundleShortVersionStringKey
=
'CFBundleShortVersionString'
;
static
const
String
kCFBundleShortVersionStringKey
=
'CFBundleShortVersionString'
;
static
const
String
kCFBundleExecutableKey
=
'CFBundleExecutable'
;
static
const
String
kCFBundleExecutableKey
=
'CFBundleExecutable'
;
...
@@ -32,6 +33,9 @@ class PlistParser {
...
@@ -32,6 +33,9 @@ class PlistParser {
static
const
String
kMinimumOSVersionKey
=
'MinimumOSVersion'
;
static
const
String
kMinimumOSVersionKey
=
'MinimumOSVersion'
;
static
const
String
kNSPrincipalClassKey
=
'NSPrincipalClass'
;
static
const
String
kNSPrincipalClassKey
=
'NSPrincipalClass'
;
// entitlement file keys
static
const
String
kAssociatedDomainsKey
=
'com.apple.developer.associated-domains'
;
static
const
String
_plutilExecutable
=
'/usr/bin/plutil'
;
static
const
String
_plutilExecutable
=
'/usr/bin/plutil'
;
/// Returns the content, converted to XML, of the plist file located at
/// Returns the content, converted to XML, of the plist file located at
...
@@ -164,8 +168,8 @@ class PlistParser {
...
@@ -164,8 +168,8 @@ class PlistParser {
return
null
;
return
null
;
}
}
/// Parses the Plist file located at [plistFilePath] and returns the
string
/// Parses the Plist file located at [plistFilePath] and returns the
value
///
value
that's associated with the specified [key] within the property list.
/// that's associated with the specified [key] within the property list.
///
///
/// If [plistFilePath] points to a non-existent file or a file that's not a
/// If [plistFilePath] points to a non-existent file or a file that's not a
/// valid property list file, this will return null.
/// valid property list file, this will return null.
...
@@ -173,8 +177,8 @@ class PlistParser {
...
@@ -173,8 +177,8 @@ class PlistParser {
/// If [key] is not found in the property list, this will return null.
/// If [key] is not found in the property list, this will return null.
///
///
/// The [plistFilePath] and [key] arguments must not be null.
/// The [plistFilePath] and [key] arguments must not be null.
String
?
getStringValueFromFile
(
String
plistFilePath
,
String
key
)
{
T
?
getValueFromFile
<
T
>
(
String
plistFilePath
,
String
key
)
{
final
Map
<
String
,
dynamic
>
parsed
=
parseFile
(
plistFilePath
);
final
Map
<
String
,
dynamic
>
parsed
=
parseFile
(
plistFilePath
);
return
parsed
[
key
]
as
String
?;
return
parsed
[
key
]
as
T
?;
}
}
}
}
packages/flutter_tools/lib/src/ios/simulators.dart
View file @
b00f1c45
...
@@ -468,7 +468,7 @@ class IOSSimulator extends Device {
...
@@ -468,7 +468,7 @@ class IOSSimulator extends Device {
// parsing the xcodeproj or configuration files.
// parsing the xcodeproj or configuration files.
// See https://github.com/flutter/flutter/issues/31037 for more information.
// See https://github.com/flutter/flutter/issues/31037 for more information.
final
String
plistPath
=
globals
.
fs
.
path
.
join
(
package
.
simulatorBundlePath
,
'Info.plist'
);
final
String
plistPath
=
globals
.
fs
.
path
.
join
(
package
.
simulatorBundlePath
,
'Info.plist'
);
final
String
?
bundleIdentifier
=
globals
.
plistParser
.
get
StringValueFromFile
(
plistPath
,
PlistParser
.
kCFBundleIdentifierKey
);
final
String
?
bundleIdentifier
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
plistPath
,
PlistParser
.
kCFBundleIdentifierKey
);
if
(
bundleIdentifier
==
null
)
{
if
(
bundleIdentifier
==
null
)
{
globals
.
printError
(
'Invalid prebuilt iOS app. Info.plist does not contain bundle identifier'
);
globals
.
printError
(
'Invalid prebuilt iOS app. Info.plist does not contain bundle identifier'
);
return
LaunchResult
.
failed
();
return
LaunchResult
.
failed
();
...
...
packages/flutter_tools/lib/src/ios/xcodeproj.dart
View file @
b00f1c45
...
@@ -185,6 +185,7 @@ class XcodeProjectInterpreter {
...
@@ -185,6 +185,7 @@ class XcodeProjectInterpreter {
final
Status
status
=
_logger
.
startSpinner
();
final
Status
status
=
_logger
.
startSpinner
();
final
String
?
scheme
=
buildContext
.
scheme
;
final
String
?
scheme
=
buildContext
.
scheme
;
final
String
?
configuration
=
buildContext
.
configuration
;
final
String
?
configuration
=
buildContext
.
configuration
;
final
String
?
target
=
buildContext
.
target
;
final
String
?
deviceId
=
buildContext
.
deviceId
;
final
String
?
deviceId
=
buildContext
.
deviceId
;
final
List
<
String
>
showBuildSettingsCommand
=
<
String
>[
final
List
<
String
>
showBuildSettingsCommand
=
<
String
>[
...
xcrunCommand
(),
...
xcrunCommand
(),
...
@@ -195,6 +196,8 @@ class XcodeProjectInterpreter {
...
@@ -195,6 +196,8 @@ class XcodeProjectInterpreter {
...<
String
>[
'-scheme'
,
scheme
],
...<
String
>[
'-scheme'
,
scheme
],
if
(
configuration
!=
null
)
if
(
configuration
!=
null
)
...<
String
>[
'-configuration'
,
configuration
],
...<
String
>[
'-configuration'
,
configuration
],
if
(
target
!=
null
)
...<
String
>[
'-target'
,
target
],
if
(
buildContext
.
environmentType
==
EnvironmentType
.
simulator
)
if
(
buildContext
.
environmentType
==
EnvironmentType
.
simulator
)
...<
String
>[
'-sdk'
,
'iphonesimulator'
],
...<
String
>[
'-sdk'
,
'iphonesimulator'
],
'-destination'
,
'-destination'
,
...
@@ -380,6 +383,7 @@ class XcodeProjectBuildContext {
...
@@ -380,6 +383,7 @@ class XcodeProjectBuildContext {
this
.
configuration
,
this
.
configuration
,
this
.
environmentType
=
EnvironmentType
.
physical
,
this
.
environmentType
=
EnvironmentType
.
physical
,
this
.
deviceId
,
this
.
deviceId
,
this
.
target
,
this
.
isWatch
=
false
,
this
.
isWatch
=
false
,
});
});
...
@@ -387,10 +391,11 @@ class XcodeProjectBuildContext {
...
@@ -387,10 +391,11 @@ class XcodeProjectBuildContext {
final
String
?
configuration
;
final
String
?
configuration
;
final
EnvironmentType
environmentType
;
final
EnvironmentType
environmentType
;
final
String
?
deviceId
;
final
String
?
deviceId
;
final
String
?
target
;
final
bool
isWatch
;
final
bool
isWatch
;
@override
@override
int
get
hashCode
=>
Object
.
hash
(
scheme
,
configuration
,
environmentType
,
deviceId
);
int
get
hashCode
=>
Object
.
hash
(
scheme
,
configuration
,
environmentType
,
deviceId
,
target
);
@override
@override
bool
operator
==(
Object
other
)
{
bool
operator
==(
Object
other
)
{
...
@@ -402,10 +407,26 @@ class XcodeProjectBuildContext {
...
@@ -402,10 +407,26 @@ class XcodeProjectBuildContext {
other
.
configuration
==
configuration
&&
other
.
configuration
==
configuration
&&
other
.
deviceId
==
deviceId
&&
other
.
deviceId
==
deviceId
&&
other
.
environmentType
==
environmentType
&&
other
.
environmentType
==
environmentType
&&
other
.
isWatch
==
isWatch
;
other
.
isWatch
==
isWatch
&&
other
.
target
==
target
;
}
}
}
}
/// The settings that are relevant for setting up universal links
@immutable
class
XcodeUniversalLinkSettings
{
const
XcodeUniversalLinkSettings
({
this
.
bundleIdentifier
,
this
.
teamIdentifier
,
this
.
associatedDomains
=
const
<
String
>[],
});
final
String
?
bundleIdentifier
;
final
String
?
teamIdentifier
;
final
List
<
String
>
associatedDomains
;
}
/// Information about an Xcode project.
/// Information about an Xcode project.
///
///
/// Represents the output of `xcodebuild -list`.
/// Represents the output of `xcodebuild -list`.
...
...
packages/flutter_tools/lib/src/macos/migrations/flutter_application_migration.dart
View file @
b00f1c45
...
@@ -27,7 +27,7 @@ class FlutterApplicationMigration extends ProjectMigrator {
...
@@ -27,7 +27,7 @@ class FlutterApplicationMigration extends ProjectMigrator {
void
migrate
()
{
void
migrate
()
{
if
(
_infoPlistFile
.
existsSync
())
{
if
(
_infoPlistFile
.
existsSync
())
{
final
String
?
principalClass
=
final
String
?
principalClass
=
globals
.
plistParser
.
get
StringValueFromFile
(
_infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
);
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
_infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
);
if
(
principalClass
==
null
||
principalClass
==
'NSApplication'
)
{
if
(
principalClass
==
null
||
principalClass
==
'NSApplication'
)
{
// No NSPrincipalClass defined, or already converted. No migration
// No NSPrincipalClass defined, or already converted. No migration
// needed.
// needed.
...
...
packages/flutter_tools/lib/src/vmservice.dart
View file @
b00f1c45
...
@@ -41,6 +41,7 @@ const String kFlutterMemoryInfoServiceName = 'flutterMemoryInfo';
...
@@ -41,6 +41,7 @@ const String kFlutterMemoryInfoServiceName = 'flutterMemoryInfo';
const
String
kFlutterGetSkSLServiceName
=
'flutterGetSkSL'
;
const
String
kFlutterGetSkSLServiceName
=
'flutterGetSkSL'
;
const
String
kFlutterGetIOSBuildOptionsServiceName
=
'flutterGetIOSBuildOptions'
;
const
String
kFlutterGetIOSBuildOptionsServiceName
=
'flutterGetIOSBuildOptions'
;
const
String
kFlutterGetAndroidBuildVariantsServiceName
=
'flutterGetAndroidBuildVariants'
;
const
String
kFlutterGetAndroidBuildVariantsServiceName
=
'flutterGetAndroidBuildVariants'
;
const
String
kFlutterGetIOSDeeplinkSettingsServiceName
=
'flutterGetIOSDeeplinkSettings'
;
/// The error response code from an unrecoverable compilation failure.
/// The error response code from an unrecoverable compilation failure.
const
int
kIsolateReloadBarred
=
1005
;
const
int
kIsolateReloadBarred
=
1005
;
...
@@ -337,6 +338,25 @@ Future<vm_service.VmService> setUpVmService({
...
@@ -337,6 +338,25 @@ Future<vm_service.VmService> setUpVmService({
registrationRequests
.
add
(
registrationRequests
.
add
(
vmService
.
registerService
(
kFlutterGetAndroidBuildVariantsServiceName
,
kFlutterToolAlias
),
vmService
.
registerService
(
kFlutterGetAndroidBuildVariantsServiceName
,
kFlutterToolAlias
),
);
);
vmService
.
registerServiceCallback
(
kFlutterGetIOSDeeplinkSettingsServiceName
,
(
Map
<
String
,
Object
?>
params
)
async
{
final
XcodeUniversalLinkSettings
settings
=
await
flutterProject
.
ios
.
universalLinkSettings
(
configuration:
params
[
'configuration'
]!
as
String
,
scheme:
params
[
'scheme'
]!
as
String
,
target:
params
[
'target'
]!
as
String
,
);
return
<
String
,
Object
>{
'result'
:
<
String
,
Object
>{
kResultType:
kResultTypeSuccess
,
'bundleIdentifier'
:
settings
.
bundleIdentifier
??
''
,
'teamIdentifier'
:
settings
.
teamIdentifier
??
''
,
'associatedDomains'
:
settings
.
associatedDomains
,
},
};
});
registrationRequests
.
add
(
vmService
.
registerService
(
kFlutterGetIOSDeeplinkSettingsServiceName
,
'Flutter Tools'
),
);
}
}
if
(
printStructuredErrorLogMethod
!=
null
)
{
if
(
printStructuredErrorLogMethod
!=
null
)
{
...
...
packages/flutter_tools/lib/src/xcode_project.dart
View file @
b00f1c45
...
@@ -124,8 +124,16 @@ class IosProject extends XcodeBasedProject {
...
@@ -124,8 +124,16 @@ class IosProject extends XcodeBasedProject {
@override
@override
String
get
pluginConfigKey
=>
IOSPlugin
.
kConfigKey
;
String
get
pluginConfigKey
=>
IOSPlugin
.
kConfigKey
;
static
final
RegExp
_productBundleIdPattern
=
RegExp
(
r''
'^
\
s*PRODUCT_BUNDLE_IDENTIFIER
\
s*=
\
s*(["'
]?)(.*?)
\
1
;
\
s
*
$
''');
// build setting keys
static const String _productBundleIdVariable = r'
$
(
PRODUCT_BUNDLE_IDENTIFIER
)
';
static
const
String
kProductBundleIdKey
=
'PRODUCT_BUNDLE_IDENTIFIER'
;
static
const
String
kTeamIdKey
=
'DEVELOPMENT_TEAM'
;
static
const
String
kEntitlementFilePathKey
=
'CODE_SIGN_ENTITLEMENTS'
;
static
const
String
kHostAppBundleNameKey
=
'FULL_PRODUCT_NAME'
;
static
final
RegExp
_productBundleIdPattern
=
RegExp
(
'^
\\
s*
$kProductBundleIdKey
\\
s*=
\\
s*(["
\'
]?)(.*?)
\\
1;
\\
s*
\$
'
);
static
const
String
_kProductBundleIdVariable
=
'
\$
(
$kProductBundleIdKey
)'
;
static
final
RegExp
_associatedDomainPattern
=
RegExp
(
r'^applinks:(.*)'
);
Directory
get
ephemeralModuleDirectory
=>
parent
.
directory
.
childDirectory
(
'.ios'
);
Directory
get
ephemeralModuleDirectory
=>
parent
.
directory
.
childDirectory
(
'.ios'
);
Directory
get
_editableDirectory
=>
parent
.
directory
.
childDirectory
(
'ios'
);
Directory
get
_editableDirectory
=>
parent
.
directory
.
childDirectory
(
'ios'
);
...
@@ -203,24 +211,71 @@ class IosProject extends XcodeBasedProject {
...
@@ -203,24 +211,71 @@ class IosProject extends XcodeBasedProject {
return
parent
.
isModule
||
_editableDirectory
.
existsSync
();
return
parent
.
isModule
||
_editableDirectory
.
existsSync
();
}
}
Future
<
XcodeUniversalLinkSettings
>
universalLinkSettings
({
required
String
configuration
,
required
String
scheme
,
required
String
target
,
})
async
{
final
XcodeProjectBuildContext
context
=
XcodeProjectBuildContext
(
configuration:
configuration
,
scheme:
scheme
,
target:
target
,
);
return
XcodeUniversalLinkSettings
(
bundleIdentifier:
await
_productBundleIdentifierWithBuildContext
(
context
),
teamIdentifier:
await
_getTeamIdentifier
(
context
),
associatedDomains:
await
_getAssociatedDomains
(
context
),
);
}
/// The product bundle identifier of the host app, or null if not set or if
/// The product bundle identifier of the host app, or null if not set or if
/// iOS tooling needed to read it is not installed.
/// iOS tooling needed to read it is not installed.
Future
<
String
?>
productBundleIdentifier
(
BuildInfo
?
buildInfo
)
async
{
Future
<
String
?>
productBundleIdentifier
(
BuildInfo
?
buildInfo
)
async
{
if
(!
existsSync
())
{
if
(!
existsSync
())
{
return
null
;
return
null
;
}
}
return _productBundleIdentifier ??= await _parseProductBundleIdentifier(buildInfo);
XcodeProjectBuildContext
?
buildContext
;
final
XcodeProjectInfo
?
info
=
await
projectInfo
();
if
(
info
!=
null
)
{
final
String
?
scheme
=
info
.
schemeFor
(
buildInfo
);
if
(
scheme
==
null
)
{
info
.
reportFlavorNotFoundAndExit
();
}
final
String
?
configuration
=
info
.
buildConfigurationFor
(
buildInfo
,
scheme
,
);
buildContext
=
XcodeProjectBuildContext
(
configuration:
configuration
,
scheme:
scheme
,
);
}
return
_productBundleIdentifierWithBuildContext
(
buildContext
);
}
Future
<
String
?>
_productBundleIdentifierWithBuildContext
(
XcodeProjectBuildContext
?
buildContext
)
async
{
if
(!
existsSync
())
{
return
null
;
}
if
(
_productBundleIdentifiers
.
containsKey
(
buildContext
))
{
return
_productBundleIdentifiers
[
buildContext
];
}
return
_productBundleIdentifiers
[
buildContext
]
=
await
_parseProductBundleIdentifier
(
buildContext
);
}
}
String? _productBundleIdentifier;
Future<String?> _parseProductBundleIdentifier(BuildInfo? buildInfo) async {
final
Map
<
XcodeProjectBuildContext
?,
String
?>
_productBundleIdentifiers
=
<
XcodeProjectBuildContext
?,
String
?>{};
Future
<
String
?>
_parseProductBundleIdentifier
(
XcodeProjectBuildContext
?
buildContext
)
async
{
String
?
fromPlist
;
String
?
fromPlist
;
final
File
defaultInfoPlist
=
defaultHostInfoPlist
;
final
File
defaultInfoPlist
=
defaultHostInfoPlist
;
// Users can change the location of the Info.plist.
// Users can change the location of the Info.plist.
// Try parsing the default, first.
// Try parsing the default, first.
if
(
defaultInfoPlist
.
existsSync
())
{
if
(
defaultInfoPlist
.
existsSync
())
{
try
{
try
{
fromPlist = globals.plistParser.get
StringValueFromFile
(
fromPlist
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
defaultHostInfoPlist
.
path
,
defaultHostInfoPlist
.
path
,
PlistParser
.
kCFBundleIdentifierKey
,
PlistParser
.
kCFBundleIdentifierKey
,
);
);
...
@@ -232,13 +287,18 @@ class IosProject extends XcodeBasedProject {
...
@@ -232,13 +287,18 @@ class IosProject extends XcodeBasedProject {
return
fromPlist
;
return
fromPlist
;
}
}
}
}
final Map<String, String>? allBuildSettings = await buildSettingsForBuildInfo(buildInfo);
if
(
buildContext
==
null
)
{
// Getting build settings to evaluate info.Plist requires a context.
return
null
;
}
final
Map
<
String
,
String
>?
allBuildSettings
=
await
_buildSettingsForXcodeProjectBuildContext
(
buildContext
);
if
(
allBuildSettings
!=
null
)
{
if
(
allBuildSettings
!=
null
)
{
if
(
fromPlist
!=
null
)
{
if
(
fromPlist
!=
null
)
{
// Perform variable substitution using build settings.
// Perform variable substitution using build settings.
return
substituteXcodeVariables
(
fromPlist
,
allBuildSettings
);
return
substituteXcodeVariables
(
fromPlist
,
allBuildSettings
);
}
}
return allBuildSettings[
'
PRODUCT_BUNDLE_IDENTIFIER
'
];
return
allBuildSettings
[
kProductBundleIdKey
];
}
}
// On non-macOS platforms, parse the first PRODUCT_BUNDLE_IDENTIFIER from
// On non-macOS platforms, parse the first PRODUCT_BUNDLE_IDENTIFIER from
...
@@ -248,13 +308,48 @@ class IosProject extends XcodeBasedProject {
...
@@ -248,13 +308,48 @@ class IosProject extends XcodeBasedProject {
// only used for display purposes and to regenerate organization names, so
// only used for display purposes and to regenerate organization names, so
// best-effort is probably fine.
// best-effort is probably fine.
final
String
?
fromPbxproj
=
firstMatchInFile
(
xcodeProjectInfoFile
,
_productBundleIdPattern
)?.
group
(
2
);
final
String
?
fromPbxproj
=
firstMatchInFile
(
xcodeProjectInfoFile
,
_productBundleIdPattern
)?.
group
(
2
);
if (fromPbxproj != null && (fromPlist == null || fromPlist == _
p
roductBundleIdVariable)) {
if
(
fromPbxproj
!=
null
&&
(
fromPlist
==
null
||
fromPlist
==
_
kP
roductBundleIdVariable
))
{
return
fromPbxproj
;
return
fromPbxproj
;
}
}
return
null
;
}
Future
<
String
?>
_getTeamIdentifier
(
XcodeProjectBuildContext
buildContext
)
async
{
final
Map
<
String
,
String
>?
buildSettings
=
await
_buildSettingsForXcodeProjectBuildContext
(
buildContext
);
if
(
buildSettings
!=
null
)
{
return
buildSettings
[
kTeamIdKey
];
}
return
null
;
return
null
;
}
}
Future
<
List
<
String
>>
_getAssociatedDomains
(
XcodeProjectBuildContext
buildContext
)
async
{
final
Map
<
String
,
String
>?
buildSettings
=
await
_buildSettingsForXcodeProjectBuildContext
(
buildContext
);
if
(
buildSettings
!=
null
)
{
final
String
?
entitlementPath
=
buildSettings
[
kEntitlementFilePathKey
];
if
(
entitlementPath
!=
null
)
{
final
File
entitlement
=
hostAppRoot
.
childFile
(
entitlementPath
);
if
(
entitlement
.
existsSync
())
{
final
List
<
String
>?
domains
=
globals
.
plistParser
.
getValueFromFile
<
List
<
Object
>>(
entitlement
.
path
,
PlistParser
.
kAssociatedDomainsKey
,
)?.
cast
<
String
>();
if
(
domains
!=
null
)
{
final
List
<
String
>
result
=
<
String
>[];
for
(
final
String
domain
in
domains
)
{
final
RegExpMatch
?
match
=
_associatedDomainPattern
.
firstMatch
(
domain
);
if
(
match
!=
null
)
{
result
.
add
(
match
.
group
(
1
)!);
}
}
return
result
;
}
}
}
}
return
const
<
String
>[];
}
/// The bundle name of the host app, `My App.app`.
/// The bundle name of the host app, `My App.app`.
Future
<
String
?>
hostAppBundleName
(
BuildInfo
?
buildInfo
)
async
{
Future
<
String
?>
hostAppBundleName
(
BuildInfo
?
buildInfo
)
async
{
if
(!
existsSync
())
{
if
(!
existsSync
())
{
...
@@ -273,11 +368,11 @@ class IosProject extends XcodeBasedProject {
...
@@ -273,11 +368,11 @@ class IosProject extends XcodeBasedProject {
if
(
globals
.
xcodeProjectInterpreter
?.
isInstalled
??
false
)
{
if
(
globals
.
xcodeProjectInterpreter
?.
isInstalled
??
false
)
{
final
Map
<
String
,
String
>?
xcodeBuildSettings
=
await
buildSettingsForBuildInfo
(
buildInfo
);
final
Map
<
String
,
String
>?
xcodeBuildSettings
=
await
buildSettingsForBuildInfo
(
buildInfo
);
if
(
xcodeBuildSettings
!=
null
)
{
if
(
xcodeBuildSettings
!=
null
)
{
productName
=
xcodeBuildSettings
[
'FULL_PRODUCT_NAME'
];
productName
=
xcodeBuildSettings
[
kHostAppBundleNameKey
];
}
}
}
}
if
(
productName
==
null
)
{
if
(
productName
==
null
)
{
globals
.
printTrace
(
'
FULL_PRODUCT_NAME
not present, defaulting to
$hostAppProjectName
'
);
globals
.
printTrace
(
'
$kHostAppBundleNameKey
not present, defaulting to
$hostAppProjectName
'
);
}
}
return
productName
??
'
${XcodeBasedProject._defaultHostAppName}
.app'
;
return
productName
??
'
${XcodeBasedProject._defaultHostAppName}
.app'
;
}
}
...
@@ -287,9 +382,11 @@ class IosProject extends XcodeBasedProject {
...
@@ -287,9 +382,11 @@ class IosProject extends XcodeBasedProject {
/// Returns null, if iOS tooling is unavailable.
/// Returns null, if iOS tooling is unavailable.
Future
<
Map
<
String
,
String
>?>
buildSettingsForBuildInfo
(
Future
<
Map
<
String
,
String
>?>
buildSettingsForBuildInfo
(
BuildInfo
?
buildInfo
,
{
BuildInfo
?
buildInfo
,
{
String
?
scheme
,
String
?
configuration
,
String
?
target
,
EnvironmentType
environmentType
=
EnvironmentType
.
physical
,
EnvironmentType
environmentType
=
EnvironmentType
.
physical
,
String
?
deviceId
,
String
?
deviceId
,
String
?
scheme
,
bool
isWatch
=
false
,
bool
isWatch
=
false
,
})
async
{
})
async
{
if
(!
existsSync
())
{
if
(!
existsSync
())
{
...
@@ -300,24 +397,31 @@ class IosProject extends XcodeBasedProject {
...
@@ -300,24 +397,31 @@ class IosProject extends XcodeBasedProject {
return
null
;
return
null
;
}
}
scheme
??=
info
.
schemeFor
(
buildInfo
);
if
(
scheme
==
null
)
{
if
(
scheme
==
null
)
{
scheme
=
info
.
schemeFor
(
buildInfo
);
info
.
reportFlavorNotFoundAndExit
();
if
(
scheme
==
null
)
{
info
.
reportFlavorNotFoundAndExit
();
}
}
}
final
String
?
configuration
=
(
await
projectInfo
())?.
buildConfigurationFor
(
configuration
??
=
(
await
projectInfo
())?.
buildConfigurationFor
(
buildInfo
,
buildInfo
,
scheme
,
scheme
,
);
);
final
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
return
_buildSettingsForXcodeProjectBuildContext
(
environmentType:
environmentType
,
XcodeProjectBuildContext
(
scheme:
scheme
,
environmentType:
environmentType
,
configuration:
configuration
,
scheme:
scheme
,
deviceId:
deviceId
,
configuration:
configuration
,
isWatch:
isWatch
,
target:
target
,
deviceId:
deviceId
,
isWatch:
isWatch
,
),
);
);
}
Future
<
Map
<
String
,
String
>?>
_buildSettingsForXcodeProjectBuildContext
(
XcodeProjectBuildContext
buildContext
)
async
{
if
(!
existsSync
())
{
return
null
;
}
final
Map
<
String
,
String
>?
currentBuildSettings
=
_buildSettingsByBuildContext
[
buildContext
];
final
Map
<
String
,
String
>?
currentBuildSettings
=
_buildSettingsByBuildContext
[
buildContext
];
if
(
currentBuildSettings
==
null
)
{
if
(
currentBuildSettings
==
null
)
{
final
Map
<
String
,
String
>?
calculatedBuildSettings
=
await
_xcodeProjectBuildSettings
(
buildContext
);
final
Map
<
String
,
String
>?
calculatedBuildSettings
=
await
_xcodeProjectBuildSettings
(
buildContext
);
...
@@ -381,7 +485,7 @@ class IosProject extends XcodeBasedProject {
...
@@ -381,7 +485,7 @@ class IosProject extends XcodeBasedProject {
// In older versions of Xcode, if the target was a watchOS companion app,
// In older versions of Xcode, if the target was a watchOS companion app,
// the Info.plist file of the target contained the key WKCompanionAppBundleIdentifier.
// the Info.plist file of the target contained the key WKCompanionAppBundleIdentifier.
if
(
infoFile
.
existsSync
())
{
if
(
infoFile
.
existsSync
())
{
final
String
?
fromPlist
=
globals
.
plistParser
.
get
StringValueFromFile
(
infoFile
.
path
,
'WKCompanionAppBundleIdentifier'
);
final
String
?
fromPlist
=
globals
.
plistParser
.
get
ValueFromFile
<
String
>
(
infoFile
.
path
,
'WKCompanionAppBundleIdentifier'
);
if
(
bundleIdentifier
==
fromPlist
)
{
if
(
bundleIdentifier
==
fromPlist
)
{
return
true
;
return
true
;
}
}
...
...
packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart
View file @
b00f1c45
...
@@ -62,8 +62,8 @@ class FakePlistUtils extends Fake implements PlistParser {
...
@@ -62,8 +62,8 @@ class FakePlistUtils extends Fake implements PlistParser {
final
Map
<
String
,
Map
<
String
,
Object
>>
fileContents
=
<
String
,
Map
<
String
,
Object
>>{};
final
Map
<
String
,
Map
<
String
,
Object
>>
fileContents
=
<
String
,
Map
<
String
,
Object
>>{};
@override
@override
String
?
getStringValueFromFile
(
String
plistFilePath
,
String
key
)
{
T
?
getValueFromFile
<
T
>
(
String
plistFilePath
,
String
key
)
{
return
fileContents
[
plistFilePath
]![
key
]
as
String
?;
return
fileContents
[
plistFilePath
]![
key
]
as
T
?;
}
}
}
}
...
...
packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart
View file @
b00f1c45
...
@@ -329,7 +329,7 @@ platform :osx, '10.14'
...
@@ -329,7 +329,7 @@ platform :osx, '10.14'
);
);
infoPlistFile
.
writeAsStringSync
(
'contents'
);
// Just so it exists: parser is a fake.
infoPlistFile
.
writeAsStringSync
(
'contents'
);
// Just so it exists: parser is a fake.
macOSProjectMigration
.
migrate
();
macOSProjectMigration
.
migrate
();
expect
(
fakePlistParser
.
get
StringValueFromFile
(
infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
),
isNull
);
expect
(
fakePlistParser
.
get
ValueFromFile
<
String
>
(
infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
),
isNull
);
expect
(
testLogger
.
statusText
,
isEmpty
);
expect
(
testLogger
.
statusText
,
isEmpty
);
});
});
...
@@ -341,7 +341,7 @@ platform :osx, '10.14'
...
@@ -341,7 +341,7 @@ platform :osx, '10.14'
);
);
infoPlistFile
.
writeAsStringSync
(
'contents'
);
// Just so it exists: parser is a fake.
infoPlistFile
.
writeAsStringSync
(
'contents'
);
// Just so it exists: parser is a fake.
macOSProjectMigration
.
migrate
();
macOSProjectMigration
.
migrate
();
expect
(
fakePlistParser
.
get
StringValueFromFile
(
infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
),
'NSApplication'
);
expect
(
fakePlistParser
.
get
ValueFromFile
<
String
>
(
infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
),
'NSApplication'
);
expect
(
testLogger
.
statusText
,
isEmpty
);
expect
(
testLogger
.
statusText
,
isEmpty
);
});
});
...
@@ -353,7 +353,7 @@ platform :osx, '10.14'
...
@@ -353,7 +353,7 @@ platform :osx, '10.14'
);
);
infoPlistFile
.
writeAsStringSync
(
'contents'
);
// Just so it exists: parser is a fake.
infoPlistFile
.
writeAsStringSync
(
'contents'
);
// Just so it exists: parser is a fake.
macOSProjectMigration
.
migrate
();
macOSProjectMigration
.
migrate
();
expect
(
fakePlistParser
.
get
StringValueFromFile
(
infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
),
'NSApplication'
);
expect
(
fakePlistParser
.
get
ValueFromFile
<
String
>
(
infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
),
'NSApplication'
);
// Only print once.
// Only print once.
expect
(
'Updating
${infoPlistFile.basename}
to use NSApplication instead of FlutterApplication.'
.
allMatches
(
testLogger
.
statusText
).
length
,
1
);
expect
(
'Updating
${infoPlistFile.basename}
to use NSApplication instead of FlutterApplication.'
.
allMatches
(
testLogger
.
statusText
).
length
,
1
);
});
});
...
@@ -367,7 +367,7 @@ platform :osx, '10.14'
...
@@ -367,7 +367,7 @@ platform :osx, '10.14'
);
);
infoPlistFile
.
writeAsStringSync
(
'contents'
);
// Just so it exists: parser is a fake.
infoPlistFile
.
writeAsStringSync
(
'contents'
);
// Just so it exists: parser is a fake.
macOSProjectMigration
.
migrate
();
macOSProjectMigration
.
migrate
();
expect
(
fakePlistParser
.
get
StringValueFromFile
(
infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
),
differentApp
);
expect
(
fakePlistParser
.
get
ValueFromFile
<
String
>
(
infoPlistFile
.
path
,
PlistParser
.
kNSPrincipalClassKey
),
differentApp
);
expect
(
testLogger
.
traceText
,
isEmpty
);
expect
(
testLogger
.
traceText
,
isEmpty
);
});
});
});
});
...
...
packages/flutter_tools/test/general.shard/project_test.dart
View file @
b00f1c45
...
@@ -693,7 +693,7 @@ apply plugin: 'kotlin-android'
...
@@ -693,7 +693,7 @@ apply plugin: 'kotlin-android'
});
});
});
});
group
(
'
product bundle identifier
'
,
()
{
group
(
'
With mocked context
'
,
()
{
late
MemoryFileSystem
fs
;
late
MemoryFileSystem
fs
;
late
FakePlistParser
testPlistUtils
;
late
FakePlistParser
testPlistUtils
;
late
FakeXcodeProjectInterpreter
xcodeProjectInterpreter
;
late
FakeXcodeProjectInterpreter
xcodeProjectInterpreter
;
...
@@ -718,140 +718,260 @@ apply plugin: 'kotlin-android'
...
@@ -718,140 +718,260 @@ apply plugin: 'kotlin-android'
});
});
}
}
testWithMocks
(
'null, if no build settings or plist entries'
,
()
async
{
group
(
'universal link'
,
()
{
final
FlutterProject
project
=
await
someProject
();
testWithMocks
(
'build with flavor'
,
()
async
{
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
isNull
);
final
FlutterProject
project
=
await
someProject
();
});
project
.
ios
.
xcodeProject
.
createSync
();
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
const
String
entitlementFilePath
=
'myEntitlement.Entitlement'
;
project
.
ios
.
hostAppRoot
.
childFile
(
entitlementFilePath
).
createSync
(
recursive:
true
);
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
target:
'Runner'
,
scheme:
'Debug'
,
configuration:
'config'
,
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
IosProject
.
kTeamIdKey
:
'ABC'
,
IosProject
.
kEntitlementFilePathKey
:
entitlementFilePath
,
'SUFFIX'
:
'suffix'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
testPlistUtils
.
setProperty
(
PlistParser
.
kCFBundleIdentifierKey
,
r'$(PRODUCT_BUNDLE_IDENTIFIER).$(SUFFIX)'
);
testPlistUtils
.
setProperty
(
PlistParser
.
kAssociatedDomainsKey
,
<
String
>[
'applinks:example.com'
,
'applinks:example2.com'
,
],
);
final
XcodeUniversalLinkSettings
settings
=
await
project
.
ios
.
universalLinkSettings
(
target:
'Runner'
,
scheme:
'Debug'
,
configuration:
'config'
,
);
expect
(
settings
.
associatedDomains
,
unorderedEquals
(
<
String
>[
'example.com'
,
'example2.com'
,
],
),
);
expect
(
settings
.
teamIdentifier
,
'ABC'
);
expect
(
settings
.
bundleIdentifier
,
'io.flutter.someProject.suffix'
);
});
testWithMocks
(
'from build settings, if no plist'
,
()
async
{
testWithMocks
(
'can handle entitlement file in nested directory structure.'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
xcodeProject
.
createSync
();
project
.
ios
.
xcodeProject
.
createSync
();
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Runner'
);
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
const
String
entitlementFilePath
=
'nested/somewhere/myEntitlement.Entitlement'
;
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
project
.
ios
.
hostAppRoot
.
childFile
(
entitlementFilePath
).
createSync
(
recursive:
true
);
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
target:
'Runner'
,
scheme:
'Debug'
,
configuration:
'config'
,
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
IosProject
.
kTeamIdKey
:
'ABC'
,
IosProject
.
kEntitlementFilePathKey
:
entitlementFilePath
,
'SUFFIX'
:
'suffix'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
testPlistUtils
.
setProperty
(
PlistParser
.
kCFBundleIdentifierKey
,
r'$(PRODUCT_BUNDLE_IDENTIFIER).$(SUFFIX)'
);
testPlistUtils
.
setProperty
(
PlistParser
.
kAssociatedDomainsKey
,
<
String
>[
'applinks:example.com'
,
'applinks:example2.com'
,
],
);
final
XcodeUniversalLinkSettings
settings
=
await
project
.
ios
.
universalLinkSettings
(
target:
'Runner'
,
scheme:
'Debug'
,
configuration:
'config'
,
);
expect
(
settings
.
associatedDomains
,
unorderedEquals
(
<
String
>[
'example.com'
,
'example2.com'
,
],
),
);
expect
(
settings
.
teamIdentifier
,
'ABC'
);
expect
(
settings
.
bundleIdentifier
,
'io.flutter.someProject.suffix'
);
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
testWithMocks
(
'return empty when no entitlement'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
xcodeProject
.
createSync
();
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
target:
'Runner'
,
scheme:
'Debug'
,
configuration:
'config'
,
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
IosProject
.
kTeamIdKey
:
'ABC'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
testPlistUtils
.
setProperty
(
PlistParser
.
kCFBundleIdentifierKey
,
r'$(PRODUCT_BUNDLE_IDENTIFIER)'
);
final
XcodeUniversalLinkSettings
settings
=
await
project
.
ios
.
universalLinkSettings
(
target:
'Runner'
,
scheme:
'Debug'
,
configuration:
'config'
,
);
expect
(
settings
.
teamIdentifier
,
'ABC'
);
expect
(
settings
.
bundleIdentifier
,
'io.flutter.someProject'
);
});
});
});
testWithMocks
(
'from project file, if no plist or build settings'
,
()
async
{
group
(
'product bundle identifier'
,
()
{
final
FlutterProject
project
=
await
someProject
();
testWithMocks
(
'null, if no build settings or plist entries'
,
()
async
{
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
final
FlutterProject
project
=
await
someProject
();
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
isNull
);
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
return
projectFileWithBundleId
(
'io.flutter.someProject'
);
});
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
});
testWithMocks
(
'from plist, if no variables'
,
()
async
{
testWithMocks
(
'from build settings, if no plist'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
project
.
ios
.
xcodeProject
.
createSync
();
testPlistUtils
.
setProperty
(
'CFBundleIdentifier'
,
'io.flutter.someProject'
);
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Runner'
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
});
<
String
,
String
>{
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
});
testWithMocks
(
'from build settings and plist, if default variable'
,
()
async
{
testWithMocks
(
'from project file, if no plist or build settings'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
xcodeProject
.
createSync
();
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Runner'
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
testPlistUtils
.
setProperty
(
'CFBundleIdentifier'
,
r'$(PRODUCT_BUNDLE_IDENTIFIER)'
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
});
return
projectFileWithBundleId
(
'io.flutter.someProject'
);
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
});
testWithMocks
(
'from build settings and plist, by substitution'
,
()
async
{
testWithMocks
(
'from plist, if no variables'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
xcodeProject
.
createSync
();
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
testPlistUtils
.
setProperty
(
'CFBundleIdentifier'
,
'io.flutter.someProject'
);
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Runner'
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
});
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
'SUFFIX'
:
'suffix'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
testPlistUtils
.
setProperty
(
'CFBundleIdentifier'
,
r'$(PRODUCT_BUNDLE_IDENTIFIER).$(SUFFIX)'
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject.suffix'
);
testWithMocks
(
'from build settings and plist, if default variable'
,
()
async
{
});
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
xcodeProject
.
createSync
();
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Runner'
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
testPlistUtils
.
setProperty
(
'CFBundleIdentifier'
,
r'$(PRODUCT_BUNDLE_IDENTIFIER)'
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
});
testWithMocks
(
'Always pass parsing org on ios project with flavors'
,
()
async
{
testWithMocks
(
'from build settings and plist, by substitution'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
project
.
ios
.
xcodeProject
.
createSync
();
return
projectFileWithBundleId
(
'io.flutter.someProject'
,
qualifier:
"'"
);
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Runner'
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
'SUFFIX'
:
'suffix'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
testPlistUtils
.
setProperty
(
'CFBundleIdentifier'
,
r'$(PRODUCT_BUNDLE_IDENTIFIER).$(SUFFIX)'
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject.suffix'
);
});
});
project
.
ios
.
xcodeProject
.
createSync
();
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'free'
,
'paid'
],
logger
);
expect
(
await
project
.
organizationNames
,
<
String
>[]);
testWithMocks
(
'Always pass parsing org on ios project with flavors'
,
()
async
{
});
final
FlutterProject
project
=
await
someProject
();
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
return
projectFileWithBundleId
(
'io.flutter.someProject'
,
qualifier:
"'"
);
});
project
.
ios
.
xcodeProject
.
createSync
();
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'free'
,
'paid'
],
logger
);
testWithMocks
(
'fails with no flavor and defined schemes'
,
()
async
{
expect
(
await
project
.
organizationNames
,
<
String
>[]);
final
FlutterProject
project
=
await
someProject
();
});
project
.
ios
.
xcodeProject
.
createSync
();
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'free'
,
'paid'
],
logger
);
await
expectToolExitLater
(
testWithMocks
(
'fails with no flavor and defined schemes'
,
()
async
{
project
.
ios
.
productBundleIdentifier
(
null
),
final
FlutterProject
project
=
await
someProject
();
contains
(
'You must specify a --flavor option to select one of the available schemes.'
)
project
.
ios
.
xcodeProject
.
createSync
();
);
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'free'
,
'paid'
],
logger
);
});
testWithMocks
(
'handles case insensitive flavor'
,
()
async
{
await
expectToolExitLater
(
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
productBundleIdentifier
(
null
),
project
.
ios
.
xcodeProject
.
createSync
();
contains
(
'You must specify a --flavor option to select one of the available schemes.'
),
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Free'
);
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
});
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Free'
],
logger
);
const
BuildInfo
buildInfo
=
BuildInfo
(
BuildMode
.
debug
,
'free'
,
treeShakeIcons:
false
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
buildInfo
),
'io.flutter.someProject'
);
testWithMocks
(
'handles case insensitive flavor'
,
()
async
{
});
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
xcodeProject
.
createSync
();
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Free'
);
xcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
};
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Free'
],
logger
);
const
BuildInfo
buildInfo
=
BuildInfo
(
BuildMode
.
debug
,
'free'
,
treeShakeIcons:
false
);
expect
(
await
project
.
ios
.
productBundleIdentifier
(
buildInfo
),
'io.flutter.someProject'
);
});
testWithMocks
(
'fails with flavor and default schemes'
,
()
async
{
testWithMocks
(
'fails with flavor and default schemes'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
xcodeProject
.
createSync
();
project
.
ios
.
xcodeProject
.
createSync
();
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
const
BuildInfo
buildInfo
=
BuildInfo
(
BuildMode
.
debug
,
'free'
,
treeShakeIcons:
false
);
const
BuildInfo
buildInfo
=
BuildInfo
(
BuildMode
.
debug
,
'free'
,
treeShakeIcons:
false
);
await
expectToolExitLater
(
await
expectToolExitLater
(
project
.
ios
.
productBundleIdentifier
(
buildInfo
),
project
.
ios
.
productBundleIdentifier
(
buildInfo
),
contains
(
'The Xcode project does not define custom schemes. You cannot use the --flavor option.'
)
contains
(
'The Xcode project does not define custom schemes. You cannot use the --flavor option.'
),
);
);
});
});
testWithMocks
(
'empty surrounded by quotes'
,
()
async
{
testWithMocks
(
'empty surrounded by quotes'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
return
projectFileWithBundleId
(
''
,
qualifier:
'"'
);
return
projectFileWithBundleId
(
''
,
qualifier:
'"'
);
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
''
);
});
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
''
);
});
testWithMocks
(
'surrounded by double quotes'
,
()
async
{
testWithMocks
(
'surrounded by double quotes'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
return
projectFileWithBundleId
(
'io.flutter.someProject'
,
qualifier:
'"'
);
return
projectFileWithBundleId
(
'io.flutter.someProject'
,
qualifier:
'"'
);
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
});
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
});
testWithMocks
(
'surrounded by single quotes'
,
()
async
{
testWithMocks
(
'surrounded by single quotes'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
final
FlutterProject
project
=
await
someProject
();
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
xcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[],
<
String
>[],
<
String
>[
'Runner'
],
logger
);
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
return
projectFileWithBundleId
(
'io.flutter.someProject'
,
qualifier:
"'"
);
return
projectFileWithBundleId
(
'io.flutter.someProject'
,
qualifier:
"'"
);
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
});
});
expect
(
await
project
.
ios
.
productBundleIdentifier
(
null
),
'io.flutter.someProject'
);
});
});
});
});
...
@@ -999,7 +1119,7 @@ apply plugin: 'kotlin-android'
...
@@ -999,7 +1119,7 @@ apply plugin: 'kotlin-android'
setUp
(()
{
setUp
(()
{
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Runner'
);
const
XcodeProjectBuildContext
buildContext
=
XcodeProjectBuildContext
(
scheme:
'Runner'
);
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
};
};
mockXcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[
'Runner'
,
'WatchTarget'
],
<
String
>[],
<
String
>[
'Runner'
,
'WatchScheme'
],
logger
);
mockXcodeProjectInterpreter
.
xcodeProjectInfo
=
XcodeProjectInfo
(<
String
>[
'Runner'
,
'WatchTarget'
],
<
String
>[],
<
String
>[
'Runner'
,
'WatchScheme'
],
logger
);
});
});
...
@@ -1093,7 +1213,7 @@ apply plugin: 'kotlin-android'
...
@@ -1093,7 +1213,7 @@ apply plugin: 'kotlin-android'
deviceId:
'123'
,
deviceId:
'123'
,
);
);
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
};
};
project
.
ios
.
hostAppRoot
.
childDirectory
(
'WatchTarget'
).
childFile
(
'Info.plist'
).
createSync
(
recursive:
true
);
project
.
ios
.
hostAppRoot
.
childDirectory
(
'WatchTarget'
).
childFile
(
'Info.plist'
).
createSync
(
recursive:
true
);
testPlistParser
.
setProperty
(
'WKCompanionAppBundleIdentifier'
,
r'$(PRODUCT_BUNDLE_IDENTIFIER)'
);
testPlistParser
.
setProperty
(
'WKCompanionAppBundleIdentifier'
,
r'$(PRODUCT_BUNDLE_IDENTIFIER)'
);
...
@@ -1127,7 +1247,7 @@ apply plugin: 'kotlin-android'
...
@@ -1127,7 +1247,7 @@ apply plugin: 'kotlin-android'
deviceId:
'123'
,
deviceId:
'123'
,
);
);
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
};
};
const
XcodeProjectBuildContext
watchBuildContext
=
XcodeProjectBuildContext
(
const
XcodeProjectBuildContext
watchBuildContext
=
XcodeProjectBuildContext
(
...
@@ -1167,7 +1287,7 @@ apply plugin: 'kotlin-android'
...
@@ -1167,7 +1287,7 @@ apply plugin: 'kotlin-android'
deviceId:
'123'
deviceId:
'123'
);
);
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
buildContext
]
=
<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
};
};
const
XcodeProjectBuildContext
watchBuildContext
=
XcodeProjectBuildContext
(
const
XcodeProjectBuildContext
watchBuildContext
=
XcodeProjectBuildContext
(
...
@@ -1176,7 +1296,7 @@ apply plugin: 'kotlin-android'
...
@@ -1176,7 +1296,7 @@ apply plugin: 'kotlin-android'
isWatch:
true
,
isWatch:
true
,
);
);
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
watchBuildContext
]
=
<
String
,
String
>{
mockXcodeProjectInterpreter
.
buildSettingsByBuildContext
[
watchBuildContext
]
=
<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
IosProject
.
kProductBundleIdKey
:
'io.flutter.someProject'
,
'INFOPLIST_KEY_WKCompanionAppBundleIdentifier'
:
r'$(PRODUCT_BUNDLE_IDENTIFIER)'
,
'INFOPLIST_KEY_WKCompanionAppBundleIdentifier'
:
r'$(PRODUCT_BUNDLE_IDENTIFIER)'
,
};
};
...
...
packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
View file @
b00f1c45
...
@@ -82,6 +82,10 @@ const List<VmServiceExpectation> kAttachIsolateExpectations =
...
@@ -82,6 +82,10 @@ const List<VmServiceExpectation> kAttachIsolateExpectations =
'service'
:
kFlutterGetAndroidBuildVariantsServiceName
,
'service'
:
kFlutterGetAndroidBuildVariantsServiceName
,
'alias'
:
kFlutterToolAlias
,
'alias'
:
kFlutterToolAlias
,
}),
}),
FakeVmServiceRequest
(
method:
'registerService'
,
args:
<
String
,
Object
>{
'service'
:
kFlutterGetIOSDeeplinkSettingsServiceName
,
'alias'
:
'Flutter Tools'
,
}),
FakeVmServiceRequest
(
FakeVmServiceRequest
(
method:
'streamListen'
,
method:
'streamListen'
,
args:
<
String
,
Object
>{
args:
<
String
,
Object
>{
...
...
packages/flutter_tools/test/integration.shard/plist_parser_test.dart
View file @
b00f1c45
...
@@ -74,52 +74,52 @@ void main() {
...
@@ -74,52 +74,52 @@ void main() {
file
.
deleteSync
();
file
.
deleteSync
();
});
});
testWithoutContext
(
'PlistParser.get
StringValueFromFile
works with an XML file'
,
()
{
testWithoutContext
(
'PlistParser.get
ValueFromFile<String>
works with an XML file'
,
()
{
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
StringValueFromFile
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.get
StringValueFromFile
works with a binary file'
,
()
{
testWithoutContext
(
'PlistParser.get
ValueFromFile<String>
works with a binary file'
,
()
{
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistBinary
));
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistBinary
));
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
StringValueFromFile
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.get
StringValueFromFile
works with a JSON file'
,
()
{
testWithoutContext
(
'PlistParser.get
ValueFromFile<String>
works with a JSON file'
,
()
{
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistJson
));
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistJson
));
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
StringValueFromFile
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.get
StringValueFromFile
returns null for a non-existent plist file'
,
()
{
testWithoutContext
(
'PlistParser.get
ValueFromFile<String>
returns null for a non-existent plist file'
,
()
{
expect
(
parser
.
get
StringValueFromFile
(
'missing.plist'
,
'CFBundleIdentifier'
),
null
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
'missing.plist'
,
'CFBundleIdentifier'
),
null
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.get
StringValueFromFile
returns null for a non-existent key within a plist'
,
()
{
testWithoutContext
(
'PlistParser.get
ValueFromFile<String>
returns null for a non-existent key within a plist'
,
()
{
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'BadKey'
),
null
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'BadKey'
),
null
);
expect
(
parser
.
get
StringValueFromFile
(
file
.
absolute
.
path
,
'BadKey'
),
null
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
absolute
.
path
,
'BadKey'
),
null
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.get
StringValueFromFile
returns null for a malformed plist file'
,
()
{
testWithoutContext
(
'PlistParser.get
ValueFromFile<String>
returns null for a malformed plist file'
,
()
{
file
.
writeAsBytesSync
(
const
<
int
>[
1
,
2
,
3
,
4
,
5
,
6
]);
file
.
writeAsBytesSync
(
const
<
int
>[
1
,
2
,
3
,
4
,
5
,
6
]);
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFBundleIdentifier'
),
null
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFBundleIdentifier'
),
null
);
expect
(
logger
.
statusText
,
contains
(
'Property List error: Unexpected character
\
x01 at line 1 / '
expect
(
logger
.
statusText
,
contains
(
'Property List error: Unexpected character
\
x01 at line 1 / '
'JSON error: JSON text did not start with array or object and option to allow fragments not '
'JSON error: JSON text did not start with array or object and option to allow fragments not '
'set. around line 1, column 0.
\n
'
));
'set. around line 1, column 0.
\n
'
));
...
@@ -127,11 +127,11 @@ void main() {
...
@@ -127,11 +127,11 @@ void main() {
' Command: /usr/bin/plutil -convert xml1 -o -
${file.absolute.path}
\n
'
);
' Command: /usr/bin/plutil -convert xml1 -o -
${file.absolute.path}
\n
'
);
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.get
StringValueFromFile
throws when /usr/bin/plutil is not found'
,
()
async
{
testWithoutContext
(
'PlistParser.get
ValueFromFile<String>
throws when /usr/bin/plutil is not found'
,
()
async
{
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
expect
(
expect
(
()
=>
parser
.
get
StringValueFromFile
(
file
.
path
,
'unused'
),
()
=>
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'unused'
),
throwsA
(
isA
<
FileNotFoundException
>()),
throwsA
(
isA
<
FileNotFoundException
>()),
);
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
...
@@ -141,21 +141,21 @@ void main() {
...
@@ -141,21 +141,21 @@ void main() {
testWithoutContext
(
'PlistParser.replaceKey can replace a key'
,
()
async
{
testWithoutContext
(
'PlistParser.replaceKey can replace a key'
,
()
async
{
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
replaceKey
(
file
.
path
,
key:
'CFBundleIdentifier'
,
value:
'dev.flutter.fake'
),
isTrue
);
expect
(
parser
.
replaceKey
(
file
.
path
,
key:
'CFBundleIdentifier'
,
value:
'dev.flutter.fake'
),
isTrue
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFBundleIdentifier'
),
equals
(
'dev.flutter.fake'
));
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFBundleIdentifier'
),
equals
(
'dev.flutter.fake'
));
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.replaceKey can create a new key'
,
()
async
{
testWithoutContext
(
'PlistParser.replaceKey can create a new key'
,
()
async
{
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistXml
));
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFNewKey'
),
isNull
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFNewKey'
),
isNull
);
expect
(
parser
.
replaceKey
(
file
.
path
,
key:
'CFNewKey'
,
value:
'dev.flutter.fake'
),
isTrue
);
expect
(
parser
.
replaceKey
(
file
.
path
,
key:
'CFNewKey'
,
value:
'dev.flutter.fake'
),
isTrue
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFNewKey'
),
equals
(
'dev.flutter.fake'
));
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFNewKey'
),
equals
(
'dev.flutter.fake'
));
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.replaceKey can delete a key'
,
()
async
{
testWithoutContext
(
'PlistParser.replaceKey can delete a key'
,
()
async
{
...
@@ -164,7 +164,7 @@ void main() {
...
@@ -164,7 +164,7 @@ void main() {
expect
(
parser
.
replaceKey
(
file
.
path
,
key:
'CFBundleIdentifier'
),
isTrue
);
expect
(
parser
.
replaceKey
(
file
.
path
,
key:
'CFBundleIdentifier'
),
isTrue
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
parser
.
get
StringValueFromFile
(
file
.
path
,
'CFBundleIdentifier'
),
isNull
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
path
,
'CFBundleIdentifier'
),
isNull
);
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
testWithoutContext
(
'PlistParser.replaceKey throws when /usr/bin/plutil is not found'
,
()
async
{
testWithoutContext
(
'PlistParser.replaceKey throws when /usr/bin/plutil is not found'
,
()
async
{
...
@@ -192,9 +192,9 @@ void main() {
...
@@ -192,9 +192,9 @@ void main() {
testWithoutContext
(
'PlistParser.replaceKey works with a JSON file'
,
()
{
testWithoutContext
(
'PlistParser.replaceKey works with a JSON file'
,
()
{
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistJson
));
file
.
writeAsBytesSync
(
base64
.
decode
(
base64PlistJson
));
expect
(
parser
.
get
StringValueFromFile
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'io.flutter.flutter.app'
);
expect
(
parser
.
replaceKey
(
file
.
path
,
key:
'CFBundleIdentifier'
,
value:
'dev.flutter.fake'
),
isTrue
);
expect
(
parser
.
replaceKey
(
file
.
path
,
key:
'CFBundleIdentifier'
,
value:
'dev.flutter.fake'
),
isTrue
);
expect
(
parser
.
get
StringValueFromFile
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'dev.flutter.fake'
);
expect
(
parser
.
get
ValueFromFile
<
String
>
(
file
.
absolute
.
path
,
'CFBundleIdentifier'
),
'dev.flutter.fake'
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
statusText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
expect
(
logger
.
errorText
,
isEmpty
);
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
},
skip:
!
platform
.
isMacOS
);
// [intended] requires macos tool chain.
...
...
packages/flutter_tools/test/src/fakes.dart
View file @
b00f1c45
...
@@ -296,8 +296,8 @@ class FakePlistParser implements PlistParser {
...
@@ -296,8 +296,8 @@ class FakePlistParser implements PlistParser {
}
}
@override
@override
String
?
getStringValueFromFile
(
String
plistFilePath
,
String
key
)
{
T
?
getValueFromFile
<
T
>
(
String
plistFilePath
,
String
key
)
{
return
_underlyingValues
[
key
]
as
String
?;
return
_underlyingValues
[
key
]
as
T
?;
}
}
@override
@override
...
...
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