Add commandHasTerminal parameter + apple usage event + sendException events for package:unified_analytics (#138806)

Relates to tracker issue:
- https://github.com/flutter/flutter/issues/128251

This PR includes 3 major updates:
- Adding the `commandHasTerminal` parameter for `Event.flutterCommandResult`
  - In `packages/flutter_tools/lib/src/runner/flutter_command.dart`
- Adding the new event for `sendException` from package:usage to be `Event.exception` (this event can be used by all dash tools)
  - In `packages/flutter_tools/lib/runner.dart`
- Migrating the generic `UsageEvent` which was only used for Apple related workflows for iOS and macOS. I did an initial analysis in this [sheet](https://docs.google.com/spreadsheets/d/11KJLkHXFpECMX7tw-trNkYSr5MHDG15XNGv6TgLjfQs/edit?resourcekey=0-j4qdvsOEEg3wQW79YlY1-g#gid=0) to identify all the call sites
  - Found in several files, highlighted in the sheet above
This commit is contained in:
Elias Yishak 2023-11-22 07:25:10 -05:00 committed by GitHub
parent 67a602d722
commit 48187028c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 298 additions and 14 deletions

View File

@ -7,6 +7,7 @@ import 'dart:async';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:intl/intl.dart' as intl; import 'package:intl/intl.dart' as intl;
import 'package:intl/intl_standalone.dart' as intl_standalone; import 'package:intl/intl_standalone.dart' as intl_standalone;
import 'package:unified_analytics/unified_analytics.dart';
import 'src/base/async_guard.dart'; import 'src/base/async_guard.dart';
import 'src/base/common.dart'; import 'src/base/common.dart';
@ -186,6 +187,7 @@ Future<int> _handleToolError(
// Report to both [Usage] and [CrashReportSender]. // Report to both [Usage] and [CrashReportSender].
globals.flutterUsage.sendException(error); globals.flutterUsage.sendException(error);
globals.analytics.send(Event.exception(exception: error.runtimeType.toString()));
await asyncGuard(() async { await asyncGuard(() async {
final CrashReportSender crashReportSender = CrashReportSender( final CrashReportSender crashReportSender = CrashReportSender(
usage: globals.flutterUsage, usage: globals.flutterUsage,

View File

@ -8,6 +8,7 @@ import 'package:crypto/crypto.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:pool/pool.dart'; import 'package:pool/pool.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/error_handling_io.dart'; import '../base/error_handling_io.dart';
@ -335,6 +336,7 @@ class Environment {
required ProcessManager processManager, required ProcessManager processManager,
required Platform platform, required Platform platform,
required Usage usage, required Usage usage,
required Analytics analytics,
String? engineVersion, String? engineVersion,
required bool generateDartPluginRegistry, required bool generateDartPluginRegistry,
Directory? buildDir, Directory? buildDir,
@ -376,6 +378,7 @@ class Environment {
processManager: processManager, processManager: processManager,
platform: platform, platform: platform,
usage: usage, usage: usage,
analytics: analytics,
engineVersion: engineVersion, engineVersion: engineVersion,
inputs: inputs, inputs: inputs,
generateDartPluginRegistry: generateDartPluginRegistry, generateDartPluginRegistry: generateDartPluginRegistry,
@ -397,6 +400,7 @@ class Environment {
String? engineVersion, String? engineVersion,
Platform? platform, Platform? platform,
Usage? usage, Usage? usage,
Analytics? analytics,
bool generateDartPluginRegistry = false, bool generateDartPluginRegistry = false,
required FileSystem fileSystem, required FileSystem fileSystem,
required Logger logger, required Logger logger,
@ -417,6 +421,7 @@ class Environment {
processManager: processManager, processManager: processManager,
platform: platform ?? FakePlatform(), platform: platform ?? FakePlatform(),
usage: usage ?? TestUsage(), usage: usage ?? TestUsage(),
analytics: analytics ?? NoOpAnalytics(),
engineVersion: engineVersion, engineVersion: engineVersion,
generateDartPluginRegistry: generateDartPluginRegistry, generateDartPluginRegistry: generateDartPluginRegistry,
); );
@ -436,6 +441,7 @@ class Environment {
required this.fileSystem, required this.fileSystem,
required this.artifacts, required this.artifacts,
required this.usage, required this.usage,
required this.analytics,
this.engineVersion, this.engineVersion,
required this.inputs, required this.inputs,
required this.generateDartPluginRegistry, required this.generateDartPluginRegistry,
@ -518,6 +524,8 @@ class Environment {
final Usage usage; final Usage usage;
final Analytics analytics;
/// The version of the current engine, or `null` if built with a local engine. /// The version of the current engine, or `null` if built with a local engine.
final String? engineVersion; final String? engineVersion;

View File

@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../artifacts.dart'; import '../../artifacts.dart';
import '../../base/build.dart'; import '../../base/build.dart';
@ -640,6 +641,11 @@ class ReleaseIosApplicationBundle extends _IosAssetBundleWithDSYM {
label: buildSuccess ? 'success' : 'fail', label: buildSuccess ? 'success' : 'fail',
flutterUsage: environment.usage, flutterUsage: environment.usage,
).send(); ).send();
environment.analytics.send(Event.appleUsageEvent(
workflow: 'assemble',
parameter: 'ios-archive',
result: buildSuccess ? 'success' : 'fail',
));
} }
} }
} }

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:unified_analytics/unified_analytics.dart';
import '../../artifacts.dart'; import '../../artifacts.dart';
import '../../base/build.dart'; import '../../base/build.dart';
import '../../base/file_system.dart'; import '../../base/file_system.dart';
@ -628,6 +630,11 @@ class ReleaseMacOSBundleFlutterAssets extends MacOSBundleFlutterAssets {
label: buildSuccess ? 'success' : 'fail', label: buildSuccess ? 'success' : 'fail',
flutterUsage: environment.usage, flutterUsage: environment.usage,
).send(); ).send();
environment.analytics.send(Event.appleUsageEvent(
workflow: 'assemble',
parameter: 'macos-archive',
result: buildSuccess ? 'success' : 'fail',
));
} }
} }
} }

View File

@ -72,6 +72,7 @@ class BundleBuilder {
logger: globals.logger, logger: globals.logger,
processManager: globals.processManager, processManager: globals.processManager,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
platform: globals.platform, platform: globals.platform,
generateDartPluginRegistry: true, generateDartPluginRegistry: true,
); );

View File

@ -233,6 +233,7 @@ class AssembleCommand extends FlutterCommand {
logger: globals.logger, logger: globals.logger,
processManager: globals.processManager, processManager: globals.processManager,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
platform: globals.platform, platform: globals.platform,
engineVersion: artifacts.isLocalEngine engineVersion: artifacts.isLocalEngine
? null ? null

View File

@ -461,6 +461,7 @@ end
processManager: globals.processManager, processManager: globals.processManager,
platform: globals.platform, platform: globals.platform,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
engineVersion: globals.artifacts!.isLocalEngine engineVersion: globals.artifacts!.isLocalEngine
? null ? null
: globals.flutterVersion.engineRevision, : globals.flutterVersion.engineRevision,

View File

@ -226,6 +226,7 @@ end
processManager: globals.processManager, processManager: globals.processManager,
platform: globals.platform, platform: globals.platform,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
engineVersion: globals.artifacts!.isLocalEngine ? null : globals.flutterVersion.engineRevision, engineVersion: globals.artifacts!.isLocalEngine ? null : globals.flutterVersion.engineRevision,
generateDartPluginRegistry: true, generateDartPluginRegistry: true,
); );

View File

@ -534,6 +534,7 @@ abstract class CreateBase extends FlutterCommand {
processManager: globals.processManager, processManager: globals.processManager,
platform: globals.platform, platform: globals.platform,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
projectDir: project.directory, projectDir: project.directory,
generateDartPluginRegistry: true, generateDartPluginRegistry: true,
); );

View File

@ -298,6 +298,7 @@ class PackagesGetCommand extends FlutterCommand {
processManager: globals.processManager, processManager: globals.processManager,
platform: globals.platform, platform: globals.platform,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
projectDir: rootProject.directory, projectDir: rootProject.directory,
generateDartPluginRegistry: true, generateDartPluginRegistry: true,
); );
@ -318,6 +319,7 @@ class PackagesGetCommand extends FlutterCommand {
processManager: globals.processManager, processManager: globals.processManager,
platform: globals.platform, platform: globals.platform,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
projectDir: rootProject.directory, projectDir: rootProject.directory,
generateDartPluginRegistry: true, generateDartPluginRegistry: true,
); );

View File

@ -168,6 +168,7 @@ Future<T> runInContext<T>(
platform: globals.platform, platform: globals.platform,
xcodeProjectInterpreter: globals.xcodeProjectInterpreter!, xcodeProjectInterpreter: globals.xcodeProjectInterpreter!,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
), ),
CocoaPodsValidator: () => CocoaPodsValidator( CocoaPodsValidator: () => CocoaPodsValidator(
globals.cocoaPods!, globals.cocoaPods!,
@ -300,6 +301,7 @@ Future<T> runInContext<T>(
MDnsVmServiceDiscovery: () => MDnsVmServiceDiscovery( MDnsVmServiceDiscovery: () => MDnsVmServiceDiscovery(
logger: globals.logger, logger: globals.logger,
flutterUsage: globals.flutterUsage, flutterUsage: globals.flutterUsage,
analytics: globals.analytics,
), ),
OperatingSystemUtils: () => OperatingSystemUtils( OperatingSystemUtils: () => OperatingSystemUtils(
fileSystem: globals.fs, fileSystem: globals.fs,
@ -382,6 +384,7 @@ Future<T> runInContext<T>(
dyLdLibEntry: globals.cache.dyLdLibEntry, dyLdLibEntry: globals.cache.dyLdLibEntry,
), ),
fileSystem: globals.fs, fileSystem: globals.fs,
analytics: globals.analytics,
), ),
XcodeProjectInterpreter: () => XcodeProjectInterpreter( XcodeProjectInterpreter: () => XcodeProjectInterpreter(
logger: globals.logger, logger: globals.logger,

View File

@ -143,7 +143,7 @@ Future<XcodeBuildResult> buildXcodeProject({
} }
final List<ProjectMigrator> migrators = <ProjectMigrator>[ final List<ProjectMigrator> migrators = <ProjectMigrator>[
RemoveFrameworkLinkAndEmbeddingMigration(app.project, globals.logger, globals.flutterUsage), RemoveFrameworkLinkAndEmbeddingMigration(app.project, globals.logger, globals.flutterUsage, globals.analytics),
XcodeBuildSystemMigration(app.project, globals.logger), XcodeBuildSystemMigration(app.project, globals.logger),
ProjectBaseConfigurationMigration(app.project, globals.logger), ProjectBaseConfigurationMigration(app.project, globals.logger),
ProjectBuildLocationMigration(app.project, globals.logger), ProjectBuildLocationMigration(app.project, globals.logger),

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:unified_analytics/unified_analytics.dart';
import '../../base/common.dart'; import '../../base/common.dart';
import '../../base/file_system.dart'; import '../../base/file_system.dart';
import '../../base/project_migrator.dart'; import '../../base/project_migrator.dart';
@ -16,11 +18,14 @@ class RemoveFrameworkLinkAndEmbeddingMigration extends ProjectMigrator {
IosProject project, IosProject project,
super.logger, super.logger,
Usage usage, Usage usage,
Analytics analytics,
) : _xcodeProjectInfoFile = project.xcodeProjectInfoFile, ) : _xcodeProjectInfoFile = project.xcodeProjectInfoFile,
_usage = usage; _usage = usage,
_analytics = analytics;
final File _xcodeProjectInfoFile; final File _xcodeProjectInfoFile;
final Usage _usage; final Usage _usage;
final Analytics _analytics;
@override @override
void migrate() { void migrate() {
@ -91,6 +96,11 @@ class RemoveFrameworkLinkAndEmbeddingMigration extends ProjectMigrator {
if (line.contains('/* App.framework ') || line.contains('/* Flutter.framework ')) { if (line.contains('/* App.framework ') || line.contains('/* Flutter.framework ')) {
// Print scary message. // Print scary message.
UsageEvent('ios-migration', 'remove-frameworks', label: 'failure', flutterUsage: _usage).send(); UsageEvent('ios-migration', 'remove-frameworks', label: 'failure', flutterUsage: _usage).send();
_analytics.send(Event.appleUsageEvent(
workflow: 'ios-migration',
parameter: 'remove-frameworks',
result: 'failure',
));
throwToolExit('Your Xcode project requires migration. See https://flutter.dev/docs/development/ios-project-migration for details.'); throwToolExit('Your Xcode project requires migration. See https://flutter.dev/docs/development/ios-project-migration for details.');
} }

View File

@ -71,6 +71,7 @@ Future<void> buildMacOS({
flutterProject.macos, flutterProject.macos,
globals.logger, globals.logger,
globals.flutterUsage, globals.flutterUsage,
globals.analytics,
), ),
MacOSDeploymentTargetMigration(flutterProject.macos, globals.logger), MacOSDeploymentTargetMigration(flutterProject.macos, globals.logger),
XcodeProjectObjectVersionMigration(flutterProject.macos, globals.logger), XcodeProjectObjectVersionMigration(flutterProject.macos, globals.logger),

View File

@ -4,6 +4,7 @@
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/error_handling_io.dart'; import '../base/error_handling_io.dart';
@ -93,11 +94,13 @@ class CocoaPods {
required Logger logger, required Logger logger,
required Platform platform, required Platform platform,
required Usage usage, required Usage usage,
required Analytics analytics,
}) : _fileSystem = fileSystem, }) : _fileSystem = fileSystem,
_processManager = processManager, _processManager = processManager,
_xcodeProjectInterpreter = xcodeProjectInterpreter, _xcodeProjectInterpreter = xcodeProjectInterpreter,
_logger = logger, _logger = logger,
_usage = usage, _usage = usage,
_analytics = analytics,
_processUtils = ProcessUtils(processManager: processManager, logger: logger), _processUtils = ProcessUtils(processManager: processManager, logger: logger),
_operatingSystemUtils = OperatingSystemUtils( _operatingSystemUtils = OperatingSystemUtils(
fileSystem: fileSystem, fileSystem: fileSystem,
@ -113,6 +116,7 @@ class CocoaPods {
final XcodeProjectInterpreter _xcodeProjectInterpreter; final XcodeProjectInterpreter _xcodeProjectInterpreter;
final Logger _logger; final Logger _logger;
final Usage _usage; final Usage _usage;
final Analytics _analytics;
Future<String?>? _versionText; Future<String?>? _versionText;
@ -384,6 +388,10 @@ class CocoaPods {
'arm-ffi', 'arm-ffi',
flutterUsage: _usage, flutterUsage: _usage,
).send(); ).send();
_analytics.send(Event.appleUsageEvent(
workflow: 'pod-install-failure',
parameter: 'arm-ffi',
));
_logger.printError( _logger.printError(
'Error: To set up CocoaPods for ARM macOS, run:\n' 'Error: To set up CocoaPods for ARM macOS, run:\n'
' sudo gem uninstall ffi && sudo gem install ffi -- --enable-libffi-alloc\n', ' sudo gem uninstall ffi && sudo gem install ffi -- --enable-libffi-alloc\n',

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:unified_analytics/unified_analytics.dart';
import '../../base/common.dart'; import '../../base/common.dart';
import '../../base/file_system.dart'; import '../../base/file_system.dart';
import '../../base/project_migrator.dart'; import '../../base/project_migrator.dart';
@ -14,11 +16,14 @@ class RemoveMacOSFrameworkLinkAndEmbeddingMigration extends ProjectMigrator {
MacOSProject project, MacOSProject project,
super.logger, super.logger,
Usage usage, Usage usage,
Analytics analytics,
) : _xcodeProjectInfoFile = project.xcodeProjectInfoFile, ) : _xcodeProjectInfoFile = project.xcodeProjectInfoFile,
_usage = usage; _usage = usage,
_analytics = analytics;
final File _xcodeProjectInfoFile; final File _xcodeProjectInfoFile;
final Usage _usage; final Usage _usage;
final Analytics _analytics;
@override @override
void migrate() { void migrate() {
@ -89,6 +94,11 @@ class RemoveMacOSFrameworkLinkAndEmbeddingMigration extends ProjectMigrator {
UsageEvent('macos-migration', 'remove-frameworks', UsageEvent('macos-migration', 'remove-frameworks',
label: 'failure', flutterUsage: _usage) label: 'failure', flutterUsage: _usage)
.send(); .send();
_analytics.send(Event.appleUsageEvent(
workflow: 'macos-migration',
parameter: 'remove-frameworks',
result: 'failure',
));
throwToolExit( throwToolExit(
'Your Xcode project requires migration.'); 'Your Xcode project requires migration.');
} }

View File

@ -6,6 +6,7 @@ import 'dart:async';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
@ -69,6 +70,7 @@ class XCDevice {
required Platform platform, required Platform platform,
required IProxy iproxy, required IProxy iproxy,
required FileSystem fileSystem, required FileSystem fileSystem,
required Analytics analytics,
@visibleForTesting @visibleForTesting
IOSCoreDeviceControl? coreDeviceControl, IOSCoreDeviceControl? coreDeviceControl,
XcodeDebug? xcodeDebug, XcodeDebug? xcodeDebug,
@ -100,7 +102,8 @@ class XCDevice {
fileSystem: fileSystem, fileSystem: fileSystem,
), ),
_iProxy = iproxy, _iProxy = iproxy,
_xcode = xcode { _xcode = xcode,
_analytics = analytics {
_setupDeviceIdentifierByEventStream(); _setupDeviceIdentifierByEventStream();
} }
@ -120,6 +123,7 @@ class XCDevice {
final IProxy _iProxy; final IProxy _iProxy;
final IOSCoreDeviceControl _coreDeviceControl; final IOSCoreDeviceControl _coreDeviceControl;
final XcodeDebug _xcodeDebug; final XcodeDebug _xcodeDebug;
final Analytics _analytics;
List<Object>? _cachedListResults; List<Object>? _cachedListResults;
@ -546,6 +550,8 @@ class XCDevice {
if (errorMessage != null) { if (errorMessage != null) {
if (errorMessage.contains('not paired')) { if (errorMessage.contains('not paired')) {
UsageEvent('device', 'ios-trust-failure', flutterUsage: globals.flutterUsage).send(); UsageEvent('device', 'ios-trust-failure', flutterUsage: globals.flutterUsage).send();
_analytics.send(Event.appleUsageEvent(workflow: 'device', parameter: 'ios-trust-failure'));
} }
_logger.printTrace(errorMessage); _logger.printTrace(errorMessage);
} }

View File

@ -6,6 +6,7 @@ import 'dart:async';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:multicast_dns/multicast_dns.dart'; import 'package:multicast_dns/multicast_dns.dart';
import 'package:unified_analytics/unified_analytics.dart';
import 'base/common.dart'; import 'base/common.dart';
import 'base/context.dart'; import 'base/context.dart';
@ -26,10 +27,12 @@ class MDnsVmServiceDiscovery {
MDnsClient? preliminaryMDnsClient, MDnsClient? preliminaryMDnsClient,
required Logger logger, required Logger logger,
required Usage flutterUsage, required Usage flutterUsage,
required Analytics analytics,
}) : _client = mdnsClient ?? MDnsClient(), }) : _client = mdnsClient ?? MDnsClient(),
_preliminaryClient = preliminaryMDnsClient, _preliminaryClient = preliminaryMDnsClient,
_logger = logger, _logger = logger,
_flutterUsage = flutterUsage; _flutterUsage = flutterUsage,
_analytics = analytics;
final MDnsClient _client; final MDnsClient _client;
@ -39,6 +42,7 @@ class MDnsVmServiceDiscovery {
final Logger _logger; final Logger _logger;
final Usage _flutterUsage; final Usage _flutterUsage;
final Analytics _analytics;
@visibleForTesting @visibleForTesting
static const String dartVmServiceName = '_dartVmService._tcp.local'; static const String dartVmServiceName = '_dartVmService._tcp.local';
@ -504,6 +508,7 @@ class MDnsVmServiceDiscovery {
switch (targetPlatform) { switch (targetPlatform) {
case TargetPlatform.ios: case TargetPlatform.ios:
UsageEvent('ios-mdns', 'no-ipv4-link-local', flutterUsage: _flutterUsage).send(); UsageEvent('ios-mdns', 'no-ipv4-link-local', flutterUsage: _flutterUsage).send();
_analytics.send(Event.appleUsageEvent(workflow: 'ios-mdns', parameter: 'no-ipv4-link-local'));
_logger.printError( _logger.printError(
'The mDNS query for an attached iOS device failed. It may ' 'The mDNS query for an attached iOS device failed. It may '
'be necessary to disable the "Personal Hotspot" on the device, and ' 'be necessary to disable the "Personal Hotspot" on the device, and '

View File

@ -1254,6 +1254,7 @@ abstract class ResidentRunner extends ResidentHandlers {
processManager: globals.processManager, processManager: globals.processManager,
platform: globals.platform, platform: globals.platform,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
projectDir: globals.fs.currentDirectory, projectDir: globals.fs.currentDirectory,
generateDartPluginRegistry: generateDartPluginRegistry, generateDartPluginRegistry: generateDartPluginRegistry,
defines: <String, String>{ defines: <String, String>{

View File

@ -1621,6 +1621,7 @@ abstract class FlutterCommand extends Command<void> {
commandPath: commandPath, commandPath: commandPath,
result: commandResult.toString(), result: commandResult.toString(),
maxRss: maxRss, maxRss: maxRss,
commandHasTerminal: globals.stdio.hasTerminal,
)); ));
// Send timing. // Send timing.
@ -1706,6 +1707,7 @@ Run 'flutter -h' (or 'flutter <command> -h') for available flutter commands and
processManager: globals.processManager, processManager: globals.processManager,
platform: globals.platform, platform: globals.platform,
usage: globals.flutterUsage, usage: globals.flutterUsage,
analytics: globals.analytics,
projectDir: project.directory, projectDir: project.directory,
generateDartPluginRegistry: true, generateDartPluginRegistry: true,
); );

View File

@ -110,6 +110,7 @@ class WebBuilder {
processManager: _processManager, processManager: _processManager,
platform: globals.platform, platform: globals.platform,
usage: _flutterUsage, usage: _flutterUsage,
analytics: _analytics,
cacheDir: globals.cache.getRoot(), cacheDir: globals.cache.getRoot(),
engineVersion: globals.artifacts!.isLocalEngine ? null : _flutterVersion.engineRevision, engineVersion: globals.artifacts!.isLocalEngine ? null : _flutterVersion.engineRevision,
flutterRootDir: _fileSystem.directory(Cache.flutterRoot), flutterRootDir: _fileSystem.directory(Cache.flutterRoot),

View File

@ -21,7 +21,7 @@ dependencies:
http: 0.13.6 http: 0.13.6
intl: 0.18.1 intl: 0.18.1
meta: 1.11.0 meta: 1.11.0
multicast_dns: 0.3.2+4 multicast_dns: 0.3.2+5
mustache_template: 2.0.0 mustache_template: 2.0.0
package_config: 2.1.0 package_config: 2.1.0
process: 5.0.1 process: 5.0.1
@ -48,7 +48,7 @@ dependencies:
http_multi_server: 3.2.1 http_multi_server: 3.2.1
convert: 3.1.1 convert: 3.1.1
async: 2.11.0 async: 2.11.0
unified_analytics: 5.4.0 unified_analytics: 5.5.0
cli_config: 0.1.2 cli_config: 0.1.2
graphs: 2.3.1 graphs: 2.3.1
@ -91,13 +91,14 @@ dependencies:
source_map_stack_trace: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" source_map_stack_trace: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_maps: 0.10.12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" source_maps: 0.10.12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_span: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" source_span: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
sse: 4.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" sse: 4.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
string_scanner: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" string_scanner: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
sync_http: 0.3.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" sync_http: 0.3.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
term_glyph: 1.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" term_glyph: 1.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
typed_data: 1.3.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
vm_service_interface: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vm_service_interface: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
watcher: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
web: 0.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
yaml_edit: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml_edit: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
dev_dependencies: dev_dependencies:
@ -114,4 +115,4 @@ dartdoc:
# Exclude this package from the hosted API docs. # Exclude this package from the hosted API docs.
nodoc: true nodoc: true
# PUBSPEC CHECKSUM: 5011 # PUBSPEC CHECKSUM: e59e

View File

@ -162,6 +162,7 @@ void main() {
preliminaryMDnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}), preliminaryMDnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}),
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
), ),
}); });
@ -225,6 +226,7 @@ void main() {
preliminaryMDnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}), preliminaryMDnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}),
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
), ),
Signals: () => FakeSignals(), Signals: () => FakeSignals(),
}); });
@ -294,6 +296,7 @@ void main() {
preliminaryMDnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}), preliminaryMDnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}),
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
), ),
ProcessManager: () => FakeProcessManager.empty(), ProcessManager: () => FakeProcessManager.empty(),
}); });
@ -363,6 +366,7 @@ void main() {
), ),
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
), ),
}); });
@ -433,6 +437,7 @@ void main() {
), ),
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
), ),
}); });
@ -507,6 +512,7 @@ void main() {
), ),
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
), ),
}); });
@ -581,6 +587,7 @@ void main() {
), ),
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
), ),
}); });

View File

@ -13,10 +13,12 @@ import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/ios.dart'; import 'package:flutter_tools/src/build_system/targets/ios.dart';
import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../../src/common.dart'; import '../../../src/common.dart';
import '../../../src/context.dart'; import '../../../src/context.dart';
import '../../../src/fake_process_manager.dart'; import '../../../src/fake_process_manager.dart';
import '../../../src/fakes.dart';
final Platform macPlatform = FakePlatform(operatingSystem: 'macos', environment: <String, String>{}); final Platform macPlatform = FakePlatform(operatingSystem: 'macos', environment: <String, String>{});
@ -45,6 +47,7 @@ void main() {
late Artifacts artifacts; late Artifacts artifacts;
late BufferLogger logger; late BufferLogger logger;
late TestUsage usage; late TestUsage usage;
late FakeAnalytics fakeAnalytics;
setUp(() { setUp(() {
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
@ -52,6 +55,10 @@ void main() {
logger = BufferLogger.test(); logger = BufferLogger.test();
artifacts = Artifacts.test(); artifacts = Artifacts.test();
usage = TestUsage(); usage = TestUsage();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
environment = Environment.test( environment = Environment.test(
fileSystem.currentDirectory, fileSystem.currentDirectory,
defines: <String, String>{ defines: <String, String>{
@ -64,6 +71,7 @@ void main() {
fileSystem: fileSystem, fileSystem: fileSystem,
engineVersion: '2', engineVersion: '2',
usage: usage, usage: usage,
analytics: fakeAnalytics,
); );
}); });
@ -386,6 +394,7 @@ void main() {
expect(assetDirectory.childFile('vm_snapshot_data'), isNot(exists)); expect(assetDirectory.childFile('vm_snapshot_data'), isNot(exists));
expect(assetDirectory.childFile('isolate_snapshot_data'), isNot(exists)); expect(assetDirectory.childFile('isolate_snapshot_data'), isNot(exists));
expect(usage.events, isEmpty); expect(usage.events, isEmpty);
expect(fakeAnalytics.sentEvents, isEmpty);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => processManager, ProcessManager: () => processManager,
@ -425,6 +434,11 @@ void main() {
await const ReleaseIosApplicationBundle().build(environment); await const ReleaseIosApplicationBundle().build(environment);
expect(usage.events, contains(const TestUsageEvent('assemble', 'ios-archive', label: 'success'))); expect(usage.events, contains(const TestUsageEvent('assemble', 'ios-archive', label: 'success')));
expect(fakeAnalytics.sentEvents, contains(Event.appleUsageEvent(
workflow: 'assemble',
parameter: 'ios-archive',
result: 'success',
)));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => processManager, ProcessManager: () => processManager,
@ -439,6 +453,11 @@ void main() {
await expectLater(() => const ReleaseIosApplicationBundle().build(environment), await expectLater(() => const ReleaseIosApplicationBundle().build(environment),
throwsA(const TypeMatcher<FileSystemException>())); throwsA(const TypeMatcher<FileSystemException>()));
expect(usage.events, contains(const TestUsageEvent('assemble', 'ios-archive', label: 'fail'))); expect(usage.events, contains(const TestUsageEvent('assemble', 'ios-archive', label: 'fail')));
expect(fakeAnalytics.sentEvents, contains(Event.appleUsageEvent(
workflow: 'assemble',
parameter: 'ios-archive',
result: 'fail',
)));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => processManager, ProcessManager: () => processManager,

View File

@ -12,10 +12,12 @@ import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/macos.dart'; import 'package:flutter_tools/src/build_system/targets/macos.dart';
import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../../src/common.dart'; import '../../../src/common.dart';
import '../../../src/context.dart'; import '../../../src/context.dart';
import '../../../src/fake_process_manager.dart'; import '../../../src/fake_process_manager.dart';
import '../../../src/fakes.dart';
void main() { void main() {
late Environment environment; late Environment environment;
@ -29,6 +31,7 @@ void main() {
late FakeCommand lipoInfoFatCommand; late FakeCommand lipoInfoFatCommand;
late FakeCommand lipoVerifyX86_64Command; late FakeCommand lipoVerifyX86_64Command;
late TestUsage usage; late TestUsage usage;
late FakeAnalytics fakeAnalytics;
setUp(() { setUp(() {
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
@ -36,6 +39,10 @@ void main() {
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
logger = BufferLogger.test(); logger = BufferLogger.test();
usage = TestUsage(); usage = TestUsage();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
environment = Environment.test( environment = Environment.test(
fileSystem.currentDirectory, fileSystem.currentDirectory,
defines: <String, String>{ defines: <String, String>{
@ -50,6 +57,7 @@ void main() {
fileSystem: fileSystem, fileSystem: fileSystem,
engineVersion: '2', engineVersion: '2',
usage: usage, usage: usage,
analytics: fakeAnalytics,
); );
binary = environment.outputDir binary = environment.outputDir
@ -398,6 +406,13 @@ void main() {
await const ReleaseMacOSBundleFlutterAssets().build(environment); await const ReleaseMacOSBundleFlutterAssets().build(environment);
expect(usage.events, contains(const TestUsageEvent('assemble', 'macos-archive', label: 'success'))); expect(usage.events, contains(const TestUsageEvent('assemble', 'macos-archive', label: 'success')));
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'assemble',
parameter: 'macos-archive',
result: 'success',
),
));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => processManager, ProcessManager: () => processManager,
@ -411,6 +426,13 @@ void main() {
await expectLater(() => const ReleaseMacOSBundleFlutterAssets().build(environment), await expectLater(() => const ReleaseMacOSBundleFlutterAssets().build(environment),
throwsA(const TypeMatcher<FileSystemException>())); throwsA(const TypeMatcher<FileSystemException>()));
expect(usage.events, contains(const TestUsageEvent('assemble', 'macos-archive', label: 'fail'))); expect(usage.events, contains(const TestUsageEvent('assemble', 'macos-archive', label: 'fail')));
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'assemble',
parameter: 'macos-archive',
result: 'fail',
),
));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => processManager, ProcessManager: () => processManager,

View File

@ -23,16 +23,25 @@ import 'package:flutter_tools/src/migrations/xcode_thin_binary_build_phase_input
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/xcode_project.dart'; import 'package:flutter_tools/src/xcode_project.dart';
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/fake_process_manager.dart'; import '../../src/fake_process_manager.dart';
import '../../src/fakes.dart';
void main () { void main () {
group('iOS migration', () { group('iOS migration', () {
late TestUsage testUsage; late TestUsage testUsage;
late FakeAnalytics fakeAnalytics;
setUp(() { setUp(() {
testUsage = TestUsage(); testUsage = TestUsage();
final MemoryFileSystem fs = MemoryFileSystem.test();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fs,
fakeFlutterVersion: FakeFlutterVersion(),
);
}); });
testWithoutContext('migrators succeed', () { testWithoutContext('migrators succeed', () {
@ -59,10 +68,12 @@ void main () {
final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration( final RemoveFrameworkLinkAndEmbeddingMigration iosProjectMigration = RemoveFrameworkLinkAndEmbeddingMigration(
project, project,
testLogger, testLogger,
testUsage testUsage,
fakeAnalytics,
); );
iosProjectMigration.migrate(); iosProjectMigration.migrate();
expect(testUsage.events, isEmpty); expect(testUsage.events, isEmpty);
expect(fakeAnalytics.sentEvents, isEmpty);
expect(xcodeProjectInfoFile.existsSync(), isFalse); expect(xcodeProjectInfoFile.existsSync(), isFalse);
@ -79,9 +90,11 @@ void main () {
project, project,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
iosProjectMigration.migrate(); iosProjectMigration.migrate();
expect(testUsage.events, isEmpty); expect(testUsage.events, isEmpty);
expect(fakeAnalytics.sentEvents, isEmpty);
expect(xcodeProjectInfoFile.lastModifiedSync(), projectLastModified); expect(xcodeProjectInfoFile.lastModifiedSync(), projectLastModified);
expect(xcodeProjectInfoFile.readAsStringSync(), contents); expect(xcodeProjectInfoFile.readAsStringSync(), contents);
@ -99,6 +112,7 @@ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.
project, project,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
iosProjectMigration.migrate(); iosProjectMigration.migrate();
expect(xcodeProjectInfoFile.readAsStringSync(), contents); expect(xcodeProjectInfoFile.readAsStringSync(), contents);
@ -126,9 +140,11 @@ keep this 2
project, project,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
iosProjectMigration.migrate(); iosProjectMigration.migrate();
expect(testUsage.events, isEmpty); expect(testUsage.events, isEmpty);
expect(fakeAnalytics.sentEvents, isEmpty);
expect(xcodeProjectInfoFile.readAsStringSync(), r''' expect(xcodeProjectInfoFile.readAsStringSync(), r'''
keep this 1 keep this 1
@ -147,12 +163,20 @@ keep this 2
project, project,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration')); expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration'));
expect(testUsage.events, contains( expect(testUsage.events, contains(
const TestUsageEvent('ios-migration', 'remove-frameworks', label: 'failure'), const TestUsageEvent('ios-migration', 'remove-frameworks', label: 'failure'),
)); ));
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'ios-migration',
parameter: 'remove-frameworks',
result: 'failure',
)
));
}); });
testWithoutContext('migration fails with leftover Flutter.framework reference', () { testWithoutContext('migration fails with leftover Flutter.framework reference', () {
@ -164,11 +188,19 @@ keep this 2
project, project,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration')); expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration'));
expect(testUsage.events, contains( expect(testUsage.events, contains(
const TestUsageEvent('ios-migration', 'remove-frameworks', label: 'failure'), const TestUsageEvent('ios-migration', 'remove-frameworks', label: 'failure'),
)); ));
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'ios-migration',
parameter: 'remove-frameworks',
result: 'failure',
)
));
}); });
testWithoutContext('migration fails without Xcode installed', () { testWithoutContext('migration fails without Xcode installed', () {
@ -180,11 +212,19 @@ keep this 2
project, project,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration')); expect(iosProjectMigration.migrate, throwsToolExit(message: 'Your Xcode project requires migration'));
expect(testUsage.events, contains( expect(testUsage.events, contains(
const TestUsageEvent('ios-migration', 'remove-frameworks', label: 'failure'), const TestUsageEvent('ios-migration', 'remove-frameworks', label: 'failure'),
)); ));
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'ios-migration',
parameter: 'remove-frameworks',
result: 'failure',
)
));
}); });
}); });

View File

@ -15,10 +15,12 @@ import 'package:flutter_tools/src/macos/cocoapods.dart';
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
import '../../src/fake_process_manager.dart'; import '../../src/fake_process_manager.dart';
import '../../src/fakes.dart';
enum _StdioStream { enum _StdioStream {
stdout, stdout,
@ -31,6 +33,7 @@ void main() {
late CocoaPods cocoaPodsUnderTest; late CocoaPods cocoaPodsUnderTest;
late BufferLogger logger; late BufferLogger logger;
late TestUsage usage; late TestUsage usage;
late FakeAnalytics fakeAnalytics;
void pretendPodVersionFails() { void pretendPodVersionFails() {
fakeProcessManager.addCommand( fakeProcessManager.addCommand(
@ -72,6 +75,10 @@ void main() {
fakeProcessManager = FakeProcessManager.empty(); fakeProcessManager = FakeProcessManager.empty();
logger = BufferLogger.test(); logger = BufferLogger.test();
usage = TestUsage(); usage = TestUsage();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
cocoaPodsUnderTest = CocoaPods( cocoaPodsUnderTest = CocoaPods(
fileSystem: fileSystem, fileSystem: fileSystem,
processManager: fakeProcessManager, processManager: fakeProcessManager,
@ -79,6 +86,7 @@ void main() {
platform: FakePlatform(operatingSystem: 'macos'), platform: FakePlatform(operatingSystem: 'macos'),
xcodeProjectInterpreter: FakeXcodeProjectInterpreter(), xcodeProjectInterpreter: FakeXcodeProjectInterpreter(),
usage: usage, usage: usage,
analytics: fakeAnalytics,
); );
fileSystem.file(fileSystem.path.join( fileSystem.file(fileSystem.path.join(
Cache.flutterRoot!, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-objc', Cache.flutterRoot!, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-objc',
@ -197,6 +205,7 @@ void main() {
platform: FakePlatform(operatingSystem: 'macos'), platform: FakePlatform(operatingSystem: 'macos'),
xcodeProjectInterpreter: fakeXcodeProjectInterpreter, xcodeProjectInterpreter: fakeXcodeProjectInterpreter,
usage: usage, usage: usage,
analytics: fakeAnalytics,
); );
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.directory('project')); final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.directory('project'));
@ -232,6 +241,7 @@ void main() {
platform: FakePlatform(operatingSystem: 'macos'), platform: FakePlatform(operatingSystem: 'macos'),
xcodeProjectInterpreter: FakeXcodeProjectInterpreter(isInstalled: false), xcodeProjectInterpreter: FakeXcodeProjectInterpreter(isInstalled: false),
usage: usage, usage: usage,
analytics: fakeAnalytics,
); );
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.directory('project')); final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.directory('project'));
@ -545,6 +555,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
contains('enable-libffi-alloc'), contains('enable-libffi-alloc'),
); );
expect(usage.events, contains(const TestUsageEvent('pod-install-failure', 'arm-ffi'))); expect(usage.events, contains(const TestUsageEvent('pod-install-failure', 'arm-ffi')));
expect(fakeAnalytics.sentEvents, contains(Event.appleUsageEvent(workflow: 'pod-install-failure', parameter: 'arm-ffi')));
}); });
} }
testToolExitsWithCocoapodsMessage(_StdioStream.stdout); testToolExitsWithCocoapodsMessage(_StdioStream.stdout);
@ -779,6 +790,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
platform: FakePlatform(operatingSystem: 'macos'), platform: FakePlatform(operatingSystem: 'macos'),
xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: fakeProcessManager, version: Version(14, 3, 0)), xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: fakeProcessManager, version: Version(14, 3, 0)),
usage: usage, usage: usage,
analytics: fakeAnalytics,
); );
final bool didInstall = await cocoaPodsUnderTestXcode143.processPods( final bool didInstall = await cocoaPodsUnderTestXcode143.processPods(

View File

@ -12,6 +12,7 @@ import 'package:flutter_tools/src/macos/migrations/remove_macos_framework_link_a
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
@ -20,6 +21,7 @@ import '../../src/fakes.dart';
void main() { void main() {
group('remove link and embed migration', () { group('remove link and embed migration', () {
late TestUsage testUsage; late TestUsage testUsage;
late FakeAnalytics fakeAnalytics;
late MemoryFileSystem memoryFileSystem; late MemoryFileSystem memoryFileSystem;
late BufferLogger testLogger; late BufferLogger testLogger;
late FakeMacOSProject macOSProject; late FakeMacOSProject macOSProject;
@ -28,6 +30,10 @@ void main() {
setUp(() { setUp(() {
testUsage = TestUsage(); testUsage = TestUsage();
memoryFileSystem = MemoryFileSystem.test(); memoryFileSystem = MemoryFileSystem.test();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: memoryFileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
xcodeProjectInfoFile = memoryFileSystem.file('project.pbxproj'); xcodeProjectInfoFile = memoryFileSystem.file('project.pbxproj');
testLogger = BufferLogger.test(); testLogger = BufferLogger.test();
macOSProject = FakeMacOSProject(); macOSProject = FakeMacOSProject();
@ -40,9 +46,11 @@ void main() {
macOSProject, macOSProject,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
macosProjectMigration.migrate(); macosProjectMigration.migrate();
expect(testUsage.events, isEmpty); expect(testUsage.events, isEmpty);
expect(fakeAnalytics.sentEvents, isEmpty);
expect(xcodeProjectInfoFile.existsSync(), isFalse); expect(xcodeProjectInfoFile.existsSync(), isFalse);
@ -64,9 +72,11 @@ void main() {
macOSProject, macOSProject,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
macosProjectMigration.migrate(); macosProjectMigration.migrate();
expect(testUsage.events, isEmpty); expect(testUsage.events, isEmpty);
expect(fakeAnalytics.sentEvents, isEmpty);
expect(xcodeProjectInfoFile.lastModifiedSync(), projectLastModified); expect(xcodeProjectInfoFile.lastModifiedSync(), projectLastModified);
expect(xcodeProjectInfoFile.readAsStringSync(), contents); expect(xcodeProjectInfoFile.readAsStringSync(), contents);
@ -85,6 +95,7 @@ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.
macOSProject, macOSProject,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
macosProjectMigration.migrate(); macosProjectMigration.migrate();
expect(xcodeProjectInfoFile.readAsStringSync(), contents); expect(xcodeProjectInfoFile.readAsStringSync(), contents);
@ -108,9 +119,11 @@ keep this 2
macOSProject, macOSProject,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
macosProjectMigration.migrate(); macosProjectMigration.migrate();
expect(testUsage.events, isEmpty); expect(testUsage.events, isEmpty);
expect(fakeAnalytics.sentEvents, isEmpty);
expect(xcodeProjectInfoFile.readAsStringSync(), r''' expect(xcodeProjectInfoFile.readAsStringSync(), r'''
keep this 1 keep this 1
@ -130,6 +143,7 @@ keep this 2
macOSProject, macOSProject,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
expect(macosProjectMigration.migrate, expect(macosProjectMigration.migrate,
@ -137,6 +151,13 @@ keep this 2
expect(testUsage.events, contains( expect(testUsage.events, contains(
const TestUsageEvent('macos-migration', 'remove-frameworks', label: 'failure'), const TestUsageEvent('macos-migration', 'remove-frameworks', label: 'failure'),
)); ));
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'macos-migration',
parameter: 'remove-frameworks',
result: 'failure',
)
));
}); });
testWithoutContext( testWithoutContext(
@ -150,12 +171,20 @@ keep this 2
macOSProject, macOSProject,
testLogger, testLogger,
testUsage, testUsage,
fakeAnalytics,
); );
expect(macosProjectMigration.migrate, expect(macosProjectMigration.migrate,
throwsToolExit(message: 'Your Xcode project requires migration')); throwsToolExit(message: 'Your Xcode project requires migration'));
expect(testUsage.events, contains( expect(testUsage.events, contains(
const TestUsageEvent('macos-migration', 'remove-frameworks', label: 'failure'), const TestUsageEvent('macos-migration', 'remove-frameworks', label: 'failure'),
)); ));
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'macos-migration',
parameter: 'remove-frameworks',
result: 'failure',
)
));
}); });
}); });

View File

@ -22,10 +22,12 @@ import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/macos/xcdevice.dart'; import 'package:flutter_tools/src/macos/xcdevice.dart';
import 'package:flutter_tools/src/macos/xcode.dart'; import 'package:flutter_tools/src/macos/xcode.dart';
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
import '../../src/fake_process_manager.dart'; import '../../src/fake_process_manager.dart';
import '../../src/fakes.dart';
void main() { void main() {
late BufferLogger logger; late BufferLogger logger;
@ -515,6 +517,7 @@ void main() {
fileSystem: fileSystem, fileSystem: fileSystem,
coreDeviceControl: FakeIOSCoreDeviceControl(), coreDeviceControl: FakeIOSCoreDeviceControl(),
xcodeDebug: FakeXcodeDebug(), xcodeDebug: FakeXcodeDebug(),
analytics: NoOpAnalytics(),
); );
}); });
@ -533,12 +536,17 @@ void main() {
late XCDevice xcdevice; late XCDevice xcdevice;
late Xcode xcode; late Xcode xcode;
late MemoryFileSystem fileSystem; late MemoryFileSystem fileSystem;
late FakeAnalytics fakeAnalytics;
late FakeIOSCoreDeviceControl coreDeviceControl; late FakeIOSCoreDeviceControl coreDeviceControl;
setUp(() { setUp(() {
xcode = Xcode.test(processManager: FakeProcessManager.any()); xcode = Xcode.test(processManager: FakeProcessManager.any());
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
coreDeviceControl = FakeIOSCoreDeviceControl(); coreDeviceControl = FakeIOSCoreDeviceControl();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
xcdevice = XCDevice( xcdevice = XCDevice(
processManager: fakeProcessManager, processManager: fakeProcessManager,
logger: logger, logger: logger,
@ -550,6 +558,7 @@ void main() {
fileSystem: fileSystem, fileSystem: fileSystem,
coreDeviceControl: coreDeviceControl, coreDeviceControl: coreDeviceControl,
xcodeDebug: FakeXcodeDebug(), xcodeDebug: FakeXcodeDebug(),
analytics: fakeAnalytics,
); );
}); });
@ -1447,6 +1456,13 @@ void main() {
expect(devices[4].devModeEnabled, true); expect(devices[4].devModeEnabled, true);
expect(fakeProcessManager, hasNoRemainingExpectations); expect(fakeProcessManager, hasNoRemainingExpectations);
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'device',
parameter: 'ios-trust-failure',
)
));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Platform: () => macPlatform, Platform: () => macPlatform,
Artifacts: () => Artifacts.test(), Artifacts: () => Artifacts.test(),

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
@ -12,8 +13,10 @@ import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart'; import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:multicast_dns/multicast_dns.dart'; import 'package:multicast_dns/multicast_dns.dart';
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../src/common.dart'; import '../src/common.dart';
import '../src/fakes.dart';
void main() { void main() {
group('mDNS Discovery', () { group('mDNS Discovery', () {
@ -57,6 +60,7 @@ void main() {
preliminaryMDnsClient: client, preliminaryMDnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForAttach(); final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForAttach();
@ -80,6 +84,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForAttach(); final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForAttach();
@ -107,6 +112,7 @@ void main() {
preliminaryMDnsClient: client, preliminaryMDnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect(portDiscovery.queryForAttach, throwsToolExit()); expect(portDiscovery.queryForAttach, throwsToolExit());
@ -130,6 +136,7 @@ void main() {
preliminaryMDnsClient: client, preliminaryMDnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForAttach(); final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForAttach();
@ -157,6 +164,7 @@ void main() {
preliminaryMDnsClient: client, preliminaryMDnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect(portDiscovery.queryForAttach, throwsToolExit()); expect(portDiscovery.queryForAttach, throwsToolExit());
@ -168,6 +176,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final int? port = (await portDiscovery.queryForAttach())?.port; final int? port = (await portDiscovery.queryForAttach())?.port;
@ -176,11 +185,17 @@ void main() {
testWithoutContext('Prints helpful message when there is no ipv4 link local address.', () async { testWithoutContext('Prints helpful message when there is no ipv4 link local address.', () async {
final BufferLogger logger = BufferLogger.test(); final BufferLogger logger = BufferLogger.test();
final MemoryFileSystem fs = MemoryFileSystem.test();
final FakeAnalytics fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fs,
fakeFlutterVersion: FakeFlutterVersion(),
);
final MDnsVmServiceDiscovery portDiscovery = MDnsVmServiceDiscovery( final MDnsVmServiceDiscovery portDiscovery = MDnsVmServiceDiscovery(
mdnsClient: emptyClient, mdnsClient: emptyClient,
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: fakeAnalytics,
); );
final Uri? uri = await portDiscovery.getVMServiceUriForAttach( final Uri? uri = await portDiscovery.getVMServiceUriForAttach(
'', '',
@ -188,6 +203,12 @@ void main() {
); );
expect(uri, isNull); expect(uri, isNull);
expect(logger.errorText, contains('Personal Hotspot')); expect(logger.errorText, contains('Personal Hotspot'));
expect(fakeAnalytics.sentEvents, contains(
Event.appleUsageEvent(
workflow: 'ios-mdns',
parameter: 'no-ipv4-link-local',
)
));
}); });
testWithoutContext('One port available, no appId', () async { testWithoutContext('One port available, no appId', () async {
@ -207,6 +228,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final int? port = (await portDiscovery.queryForAttach())?.port; final int? port = (await portDiscovery.queryForAttach())?.port;
expect(port, 123); expect(port, 123);
@ -234,6 +256,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForAttach(); final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForAttach();
expect(result?.port, 123); expect(result?.port, 123);
@ -261,6 +284,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final int? port = (await portDiscovery.queryForAttach(applicationId: 'fiz'))?.port; final int? port = (await portDiscovery.queryForAttach(applicationId: 'fiz'))?.port;
expect(port, 321); expect(port, 321);
@ -289,6 +313,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final int? port = (await portDiscovery.queryForAttach(applicationId: 'bar'))?.port; final int? port = (await portDiscovery.queryForAttach(applicationId: 'bar'))?.port;
expect(port, 1234); expect(port, 1234);
@ -305,6 +330,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect( expect(
() async => portDiscovery.queryForAttach(), () async => portDiscovery.queryForAttach(),
@ -330,6 +356,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final Uri? uri = await portDiscovery.getVMServiceUriForAttach('bar', device, hostVmservicePort: 0); final Uri? uri = await portDiscovery.getVMServiceUriForAttach('bar', device, hostVmservicePort: 0);
expect(uri.toString(), 'http://127.0.0.1:123/'); expect(uri.toString(), 'http://127.0.0.1:123/');
@ -363,6 +390,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final Uri? uri = await portDiscovery.getVMServiceUriForAttach( final Uri? uri = await portDiscovery.getVMServiceUriForAttach(
'bar', 'bar',
@ -400,6 +428,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final Uri? uri = await portDiscovery.getVMServiceUriForAttach( final Uri? uri = await portDiscovery.getVMServiceUriForAttach(
'bar', 'bar',
@ -434,6 +463,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect( expect(
portDiscovery.getVMServiceUriForAttach( portDiscovery.getVMServiceUriForAttach(
@ -464,6 +494,7 @@ void main() {
preliminaryMDnsClient: emptyClient, preliminaryMDnsClient: emptyClient,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect( expect(
portDiscovery.getVMServiceUriForAttach( portDiscovery.getVMServiceUriForAttach(
@ -485,6 +516,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect(() async => portDiscovery.queryForLaunch(applicationId: 'app-id'), throwsAssertionError); expect(() async => portDiscovery.queryForLaunch(applicationId: 'app-id'), throwsAssertionError);
@ -497,6 +529,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForLaunch( final MDnsVmServiceDiscoveryResult? result = await portDiscovery.queryForLaunch(
@ -514,6 +547,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: logger, logger: logger,
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final Uri? uri = await portDiscovery.getVMServiceUriForLaunch( final Uri? uri = await portDiscovery.getVMServiceUriForLaunch(
@ -535,6 +569,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect( expect(
() async => portDiscovery.queryForLaunch(applicationId: 'app-id', deviceVmservicePort: 123), () async => portDiscovery.queryForLaunch(applicationId: 'app-id', deviceVmservicePort: 123),
@ -559,6 +594,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final Uri? uri = await portDiscovery.getVMServiceUriForLaunch( final Uri? uri = await portDiscovery.getVMServiceUriForLaunch(
'bar', 'bar',
@ -596,6 +632,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final Uri? uri = await portDiscovery.getVMServiceUriForLaunch( final Uri? uri = await portDiscovery.getVMServiceUriForLaunch(
'bar', 'bar',
@ -633,6 +670,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final Uri? uri = await portDiscovery.getVMServiceUriForLaunch( final Uri? uri = await portDiscovery.getVMServiceUriForLaunch(
'bar', 'bar',
@ -667,6 +705,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect( expect(
portDiscovery.getVMServiceUriForLaunch( portDiscovery.getVMServiceUriForLaunch(
@ -699,6 +738,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final Uri? uri = await portDiscovery.getVMServiceUriForLaunch( final Uri? uri = await portDiscovery.getVMServiceUriForLaunch(
@ -728,6 +768,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect( expect(
portDiscovery.getVMServiceUriForLaunch( portDiscovery.getVMServiceUriForLaunch(
@ -749,6 +790,7 @@ void main() {
), ),
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect(portDiscovery.deviceNameMatchesTargetName('My phone', 'My-Phone.local'), isTrue); expect(portDiscovery.deviceNameMatchesTargetName('My phone', 'My-Phone.local'), isTrue);
@ -762,6 +804,7 @@ void main() {
), ),
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
expect(portDiscovery.deviceNameMatchesTargetName('My phone', 'My-Phone-2.local'), isFalse); expect(portDiscovery.deviceNameMatchesTargetName('My phone', 'My-Phone-2.local'), isFalse);
}); });
@ -791,6 +834,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService(client); final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService(client);
expect(result?.domainName, 'srv-foo'); expect(result?.domainName, 'srv-foo');
@ -821,6 +865,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService( final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService(
client, client,
@ -850,6 +895,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService( final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService(
client, client,
@ -887,6 +933,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService( final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService(
client, client,
@ -924,6 +971,7 @@ void main() {
mdnsClient: client, mdnsClient: client,
logger: BufferLogger.test(), logger: BufferLogger.test(),
flutterUsage: TestUsage(), flutterUsage: TestUsage(),
analytics: NoOpAnalytics(),
); );
final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService( final MDnsVmServiceDiscoveryResult? result = await portDiscovery.firstMatchingVmService(
client, client,

View File

@ -233,7 +233,8 @@ void main() {
Event.flutterCommandResult( Event.flutterCommandResult(
commandPath: 'dummy', commandPath: 'dummy',
result: 'success', result: 'success',
maxRss: 10 maxRss: 10,
commandHasTerminal: false,
), ),
]); ]);
}); });
@ -266,7 +267,8 @@ void main() {
Event.flutterCommandResult( Event.flutterCommandResult(
commandPath: 'dummy', commandPath: 'dummy',
result: 'warning', result: 'warning',
maxRss: 10 maxRss: 10,
commandHasTerminal: false,
), ),
]); ]);
}); });
@ -301,7 +303,8 @@ void main() {
Event.flutterCommandResult( Event.flutterCommandResult(
commandPath: 'dummy', commandPath: 'dummy',
result: 'fail', result: 'fail',
maxRss: 10 maxRss: 10,
commandHasTerminal: false,
), ),
]); ]);
}); });
@ -414,7 +417,8 @@ void main() {
Event.flutterCommandResult( Event.flutterCommandResult(
commandPath: 'dummy', commandPath: 'dummy',
result: 'killed', result: 'killed',
maxRss: 10 maxRss: 10,
commandHasTerminal: false,
), ),
]); ]);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{

View File

@ -32,6 +32,8 @@ void main() {
late MemoryFileSystem fileSystem; late MemoryFileSystem fileSystem;
group('runner', () { group('runner', () {
late FakeAnalytics fakeAnalytics;
setUp(() { setUp(() {
// Instead of exiting with dart:io exit(), this causes an exception to // Instead of exiting with dart:io exit(), this causes an exception to
// be thrown, which we catch with the onError callback in the zone below. // be thrown, which we catch with the onError callback in the zone below.
@ -50,6 +52,11 @@ void main() {
Cache.disableLocking(); Cache.disableLocking();
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
}); });
tearDown(() { tearDown(() {
@ -92,6 +99,7 @@ void main() {
// attempt. // attempt.
final CrashingUsage crashingUsage = globals.flutterUsage as CrashingUsage; final CrashingUsage crashingUsage = globals.flutterUsage as CrashingUsage;
expect(crashingUsage.sentException.toString(), 'Exception: an exception % --'); expect(crashingUsage.sentException.toString(), 'Exception: an exception % --');
expect(fakeAnalytics.sentEvents, contains(Event.exception(exception: '_Exception')));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Platform: () => FakePlatform(environment: <String, String>{ Platform: () => FakePlatform(environment: <String, String>{
'FLUTTER_ANALYTICS_LOG_FILE': 'test', 'FLUTTER_ANALYTICS_LOG_FILE': 'test',
@ -102,6 +110,7 @@ void main() {
Usage: () => CrashingUsage(), Usage: () => CrashingUsage(),
Artifacts: () => Artifacts.test(), Artifacts: () => Artifacts.test(),
HttpClientFactory: () => () => FakeHttpClient.any(), HttpClientFactory: () => () => FakeHttpClient.any(),
Analytics: () => fakeAnalytics,
}); });
// This Completer completes when CrashingFlutterCommand.runCommand // This Completer completes when CrashingFlutterCommand.runCommand