// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter_devicelab/framework/devices.dart'; import 'package:flutter_devicelab/framework/framework.dart'; import 'package:flutter_devicelab/framework/task_result.dart'; import 'package:flutter_devicelab/framework/utils.dart'; import 'package:path/path.dart' as path; /// Basic launch test for desktop operating systems. void main() { task(() async { deviceOperatingSystem = DeviceOperatingSystem.macos; final Device device = await devices.workingDevice; // TODO(cbracken): https://github.com/flutter/flutter/issues/87508#issuecomment-1043753201 // Switch to dev/integration_tests/ui once we have CocoaPods working on M1 Macs. final Directory appDir = dir(path.join(flutterDirectory.path, 'examples/hello_world')); await inDirectory(appDir, () async { final Completer<void> ready = Completer<void>(); final List<String> stdout = <String>[]; final List<String> stderr = <String>[]; print('run: starting...'); final List<String> options = <String>[ '--release', '-d', device.deviceId, ]; final Process run = await startFlutter( 'run', options: options, isBot: false, ); int? runExitCode; run.stdout .transform<String>(utf8.decoder) .transform<String>(const LineSplitter()) .listen((String line) { print('run:stdout: $line'); if ( !line.startsWith('Building flutter tool...') && !line.startsWith('Running "flutter pub get" in ui...') && !line.startsWith('Resolving dependencies...') && // Catch engine piped output from unrelated concurrent Flutter apps !line.contains(RegExp(r'[A-Z]\/flutter \([0-9]+\):')) && // Empty lines could be due to the progress spinner breaking up. line.length > 1 ) { stdout.add(line); } if (line.contains('Quit (terminate the application on the device).')) { ready.complete(); } }); run.stderr .transform<String>(utf8.decoder) .transform<String>(const LineSplitter()) .listen((String line) { print('run:stderr: $line'); stderr.add(line); }); unawaited(run.exitCode.then<void>((int exitCode) { runExitCode = exitCode; })); await Future.any<dynamic>(<Future<dynamic>>[ ready.future, run.exitCode ]); if (runExitCode != null) { throw 'Failed to run test app; runner unexpected exited, with exit code $runExitCode.'; } run.stdin.write('q'); await run.exitCode; _findNextMatcherInList( stdout, (String line) => line.startsWith('Launching lib/main.dart on ') && line.endsWith(' in release mode...'), 'Launching lib/main.dart on', ); _findNextMatcherInList( stdout, (String line) => line.contains('Quit (terminate the application on the device).'), 'q Quit (terminate the application on the device)', ); _findNextMatcherInList( stdout, (String line) => line == 'Application finished.', 'Application finished.', ); }); return TaskResult.success(null); }); } void _findNextMatcherInList( List<String> list, bool Function(String testLine) matcher, String errorMessageExpectedLine ) { final List<String> copyOfListForErrorMessage = List<String>.from(list); while (list.isNotEmpty) { final String nextLine = list.first; list.removeAt(0); if (matcher(nextLine)) { return; } } throw ''' Did not find expected line $errorMessageExpectedLine in flutter run --release stdout $copyOfListForErrorMessage '''; }