| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:file/file.dart'; |
| import 'package:file/memory.dart'; |
| import 'package:file_testing/file_testing.dart'; |
| import 'package:flutter_tools/src/base/dds.dart'; |
| import 'package:flutter_tools/src/base/io.dart'; |
| import 'package:flutter_tools/src/base/logger.dart'; |
| import 'package:flutter_tools/src/base/signals.dart'; |
| import 'package:flutter_tools/src/base/terminal.dart'; |
| import 'package:flutter_tools/src/build_info.dart'; |
| import 'package:flutter_tools/src/build_system/tools/shader_compiler.dart'; |
| import 'package:flutter_tools/src/compile.dart'; |
| import 'package:flutter_tools/src/convert.dart'; |
| import 'package:flutter_tools/src/devfs.dart'; |
| import 'package:flutter_tools/src/device.dart'; |
| import 'package:flutter_tools/src/resident_runner.dart'; |
| import 'package:flutter_tools/src/vmservice.dart'; |
| import 'package:test/fake.dart'; |
| import 'package:vm_service/vm_service.dart' as vm_service; |
| |
| import '../src/common.dart'; |
| import '../src/fake_vm_services.dart'; |
| import '../src/fakes.dart'; |
| |
| final fakeUnpausedIsolate = vm_service.Isolate( |
| id: '1', |
| pauseEvent: vm_service.Event(kind: vm_service.EventKind.kResume, timestamp: 0), |
| breakpoints: <vm_service.Breakpoint>[], |
| extensionRPCs: <String>[], |
| libraries: <vm_service.LibraryRef>[ |
| vm_service.LibraryRef(id: '1', uri: 'file:///hello_world/main.dart', name: ''), |
| ], |
| livePorts: 0, |
| name: 'test', |
| number: '1', |
| pauseOnExit: false, |
| runnable: true, |
| startTime: 0, |
| isSystemIsolate: false, |
| isolateFlags: <vm_service.IsolateFlag>[], |
| ); |
| |
| final fakeFlutterView = FlutterView(id: 'a', uiIsolate: fakeUnpausedIsolate); |
| |
| final listViews = FakeVmServiceRequest( |
| method: kListViewsMethod, |
| jsonResponse: <String, Object>{ |
| 'views': <Object>[fakeFlutterView.toJson()], |
| }, |
| ); |
| |
| void main() { |
| testWithoutContext('keyboard input handling single help character', () async { |
| final testRunner = TestRunner(); |
| final Logger logger = BufferLogger.test(); |
| final signals = Signals.test(); |
| final terminal = Terminal.test(); |
| final fs = MemoryFileSystem.test(); |
| final processInfo = ProcessInfo.test(fs); |
| final terminalHandler = TerminalHandler( |
| testRunner, |
| logger: logger, |
| signals: signals, |
| terminal: terminal, |
| processInfo: processInfo, |
| reportReady: false, |
| ); |
| |
| expect(testRunner.hasHelpBeenPrinted, false); |
| await terminalHandler.processTerminalInput('h'); |
| expect(testRunner.hasHelpBeenPrinted, true); |
| }); |
| |
| testWithoutContext('keyboard input handling help character surrounded with newlines', () async { |
| final testRunner = TestRunner(); |
| final Logger logger = BufferLogger.test(); |
| final signals = Signals.test(); |
| final terminal = Terminal.test(); |
| final fs = MemoryFileSystem.test(); |
| final processInfo = ProcessInfo.test(fs); |
| final terminalHandler = TerminalHandler( |
| testRunner, |
| logger: logger, |
| signals: signals, |
| terminal: terminal, |
| processInfo: processInfo, |
| reportReady: false, |
| ); |
| |
| expect(testRunner.hasHelpBeenPrinted, false); |
| await terminalHandler.processTerminalInput('\nh\n'); |
| expect(testRunner.hasHelpBeenPrinted, true); |
| }); |
| |
| group('keycode verification, brought to you by the letter', () { |
| testWithoutContext('a, can handle trailing newlines', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('a\n'); |
| |
| expect(terminalHandler.lastReceivedCommand, 'a'); |
| }); |
| |
| testWithoutContext('n, can handle trailing only newlines', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[]); |
| await terminalHandler.processTerminalInput('\n\n'); |
| |
| expect(terminalHandler.lastReceivedCommand, ''); |
| }); |
| |
| testWithoutContext('a - debugToggleProfileWidgetBuilds', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.profileWidgetBuilds', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'enabled': 'false'}, |
| ), |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.profileWidgetBuilds', |
| args: <String, Object>{'isolateId': '1', 'enabled': 'true'}, |
| jsonResponse: <String, Object>{'enabled': 'true'}, |
| ), |
| ]); |
| |
| await terminalHandler.processTerminalInput('a'); |
| }); |
| |
| testWithoutContext('a - debugToggleProfileWidgetBuilds with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.profileWidgetBuilds', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'enabled': 'false'}, |
| ), |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.profileWidgetBuilds', |
| args: <String, Object>{'isolateId': '1', 'enabled': 'true'}, |
| jsonResponse: <String, Object>{'enabled': 'true'}, |
| ), |
| ], web: true); |
| |
| await terminalHandler.processTerminalInput('a'); |
| }); |
| |
| testWithoutContext( |
| 'a - debugToggleProfileWidgetBuilds without service protocol is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| |
| await terminalHandler.processTerminalInput('a'); |
| }, |
| ); |
| |
| testWithoutContext('b - debugToggleBrightness', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.brightnessOverride', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'value': 'Brightness.light'}, |
| ), |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.brightnessOverride', |
| args: <String, Object>{'isolateId': '1', 'value': 'Brightness.dark'}, |
| jsonResponse: <String, Object>{'value': 'Brightness.dark'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('b'); |
| |
| expect(terminalHandler.logger.statusText, contains('Changed brightness to Brightness.dark')); |
| }); |
| |
| testWithoutContext('b - debugToggleBrightness with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.brightnessOverride', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'value': 'Brightness.light'}, |
| ), |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.brightnessOverride', |
| args: <String, Object>{'isolateId': '1', 'value': 'Brightness.dark'}, |
| jsonResponse: <String, Object>{'value': 'Brightness.dark'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('b'); |
| |
| expect(terminalHandler.logger.statusText, contains('Changed brightness to Brightness.dark')); |
| }); |
| |
| testWithoutContext('b - debugToggleBrightness without service protocol is skipped', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| |
| await terminalHandler.processTerminalInput('b'); |
| }); |
| |
| testWithoutContext('d,D - detach', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[]); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| await terminalHandler.processTerminalInput('d'); |
| |
| expect(runner.calledDetach, true); |
| runner.calledDetach = false; |
| |
| await terminalHandler.processTerminalInput('D'); |
| |
| expect(runner.calledDetach, true); |
| }); |
| |
| testWithoutContext('h,H,? - printHelp', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[]); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| await terminalHandler.processTerminalInput('h'); |
| |
| expect(runner.calledPrintWithDetails, true); |
| runner.calledPrintWithDetails = false; |
| |
| await terminalHandler.processTerminalInput('H'); |
| |
| expect(runner.calledPrintWithDetails, true); |
| runner.calledPrintWithDetails = false; |
| |
| await terminalHandler.processTerminalInput('?'); |
| |
| expect(runner.calledPrintWithDetails, true); |
| }); |
| |
| testWithoutContext('i - debugToggleWidgetInspector', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.inspector.show', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ]); |
| |
| await terminalHandler.processTerminalInput('i'); |
| }); |
| |
| testWithoutContext('i - debugToggleWidgetInspector with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.inspector.show', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ], web: true); |
| |
| await terminalHandler.processTerminalInput('i'); |
| }); |
| |
| testWithoutContext( |
| 'i - debugToggleWidgetInspector without service protocol is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| |
| await terminalHandler.processTerminalInput('i'); |
| }, |
| ); |
| |
| testWithoutContext('I - debugToggleInvertOversizedImages', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.invertOversizedImages', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('I'); |
| }); |
| |
| testWithoutContext('I - debugToggleInvertOversizedImages with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.invertOversizedImages', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('I'); |
| }); |
| |
| testWithoutContext( |
| 'I - debugToggleInvertOversizedImages without service protocol is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('I'); |
| }, |
| ); |
| |
| testWithoutContext('I - debugToggleInvertOversizedImages in profile mode is skipped', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| buildMode: BuildMode.profile, |
| ); |
| await terminalHandler.processTerminalInput('I'); |
| }); |
| |
| testWithoutContext('L - debugDumpLayerTree', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpLayerTree', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'LAYER TREE'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('L'); |
| |
| expect(terminalHandler.logger.statusText, contains('LAYER TREE')); |
| }); |
| |
| testWithoutContext('L - debugDumpLayerTree with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpLayerTree', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'LAYER TREE'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('L'); |
| |
| expect(terminalHandler.logger.statusText, contains('LAYER TREE')); |
| }); |
| |
| testWithoutContext( |
| 'L - debugDumpLayerTree with service protocol and profile mode is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| buildMode: BuildMode.profile, |
| ); |
| await terminalHandler.processTerminalInput('L'); |
| }, |
| ); |
| |
| testWithoutContext('L - debugDumpLayerTree without service protocol is skipped', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('L'); |
| }); |
| |
| testWithoutContext('f - debugDumpFocusTree', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpFocusTree', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'FOCUS TREE'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('f'); |
| |
| expect(terminalHandler.logger.statusText, contains('FOCUS TREE')); |
| }); |
| |
| testWithoutContext('f - debugDumpLayerTree with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpFocusTree', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'FOCUS TREE'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('f'); |
| |
| expect(terminalHandler.logger.statusText, contains('FOCUS TREE')); |
| }); |
| |
| testWithoutContext( |
| 'f - debugDumpFocusTree with service protocol and profile mode is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| buildMode: BuildMode.profile, |
| ); |
| await terminalHandler.processTerminalInput('f'); |
| }, |
| ); |
| |
| testWithoutContext('f - debugDumpFocusTree without service protocol is skipped', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('f'); |
| }); |
| |
| testWithoutContext('o,O - debugTogglePlatform', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| // Request 1. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.platformOverride', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'value': 'iOS'}, |
| ), |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.platformOverride', |
| args: <String, Object>{'isolateId': '1', 'value': 'windows'}, |
| jsonResponse: <String, Object>{'value': 'windows'}, |
| ), |
| // Request 2. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.platformOverride', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'value': 'android'}, |
| ), |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.platformOverride', |
| args: <String, Object>{'isolateId': '1', 'value': 'iOS'}, |
| jsonResponse: <String, Object>{'value': 'iOS'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('o'); |
| await terminalHandler.processTerminalInput('O'); |
| |
| expect(terminalHandler.logger.statusText, contains('Switched operating system to windows')); |
| expect(terminalHandler.logger.statusText, contains('Switched operating system to iOS')); |
| }); |
| |
| testWithoutContext('o,O - debugTogglePlatform with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| // Request 1. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.platformOverride', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'value': 'iOS'}, |
| ), |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.platformOverride', |
| args: <String, Object>{'isolateId': '1', 'value': 'windows'}, |
| jsonResponse: <String, Object>{'value': 'windows'}, |
| ), |
| // Request 2. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.platformOverride', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'value': 'android'}, |
| ), |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.platformOverride', |
| args: <String, Object>{'isolateId': '1', 'value': 'iOS'}, |
| jsonResponse: <String, Object>{'value': 'iOS'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('o'); |
| await terminalHandler.processTerminalInput('O'); |
| |
| expect(terminalHandler.logger.statusText, contains('Switched operating system to windows')); |
| expect(terminalHandler.logger.statusText, contains('Switched operating system to iOS')); |
| }); |
| |
| testWithoutContext('o,O - debugTogglePlatform without service protocol is skipped', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('o'); |
| await terminalHandler.processTerminalInput('O'); |
| }); |
| |
| testWithoutContext('p - debugToggleDebugPaintSizeEnabled', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugPaint', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('p'); |
| }); |
| |
| testWithoutContext('p - debugToggleDebugPaintSizeEnabled with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugPaint', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('p'); |
| }); |
| |
| testWithoutContext( |
| 'p - debugToggleDebugPaintSizeEnabled without service protocol is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('p'); |
| }, |
| ); |
| |
| testWithoutContext('P - debugTogglePerformanceOverlayOverride', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.showPerformanceOverlay', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('P'); |
| }); |
| |
| testWithoutContext( |
| 'P - debugTogglePerformanceOverlayOverride with web target is skipped ', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| web: true, |
| ); |
| await terminalHandler.processTerminalInput('P'); |
| }, |
| ); |
| |
| testWithoutContext( |
| 'P - debugTogglePerformanceOverlayOverride without service protocol is skipped ', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('P'); |
| }, |
| ); |
| |
| testWithoutContext('S - debugDumpSemanticsTreeInTraversalOrder', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpSemanticsTreeInTraversalOrder', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'SEMANTICS DATA'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('S'); |
| |
| expect(terminalHandler.logger.statusText, contains('SEMANTICS DATA')); |
| }); |
| |
| testWithoutContext('S - debugDumpSemanticsTreeInTraversalOrder with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpSemanticsTreeInTraversalOrder', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'SEMANTICS DATA'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('S'); |
| |
| expect(terminalHandler.logger.statusText, contains('SEMANTICS DATA')); |
| }); |
| |
| testWithoutContext( |
| 'S - debugDumpSemanticsTreeInTraversalOrder without service protocol is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('S'); |
| }, |
| ); |
| |
| testWithoutContext('U - debugDumpSemanticsTreeInInverseHitTestOrder', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'SEMANTICS DATA'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('U'); |
| |
| expect(terminalHandler.logger.statusText, contains('SEMANTICS DATA')); |
| }); |
| |
| testWithoutContext('U - debugDumpSemanticsTreeInInverseHitTestOrder with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'SEMANTICS DATA'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('U'); |
| |
| expect(terminalHandler.logger.statusText, contains('SEMANTICS DATA')); |
| }); |
| |
| testWithoutContext( |
| 'U - debugDumpSemanticsTreeInInverseHitTestOrder without service protocol is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('U'); |
| }, |
| ); |
| |
| testWithoutContext('t,T - debugDumpRenderTree', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpRenderTree', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'RENDER DATA 1'}, |
| ), |
| // Request 2. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpRenderTree', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'RENDER DATA 2'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('t'); |
| await terminalHandler.processTerminalInput('T'); |
| |
| expect(terminalHandler.logger.statusText, contains('RENDER DATA 1')); |
| expect(terminalHandler.logger.statusText, contains('RENDER DATA 2')); |
| }); |
| |
| testWithoutContext('t,T - debugDumpRenderTree with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpRenderTree', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'RENDER DATA 1'}, |
| ), |
| // Request 2. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpRenderTree', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'RENDER DATA 2'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('t'); |
| await terminalHandler.processTerminalInput('T'); |
| |
| expect(terminalHandler.logger.statusText, contains('RENDER DATA 1')); |
| expect(terminalHandler.logger.statusText, contains('RENDER DATA 2')); |
| }); |
| |
| testWithoutContext('t,T - debugDumpRenderTree without service protocol is skipped', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('t'); |
| await terminalHandler.processTerminalInput('T'); |
| }); |
| |
| testWithoutContext('w,W - debugDumpApp', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpApp', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'WIDGET DATA 1'}, |
| ), |
| // Request 2. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpApp', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'WIDGET DATA 2'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('w'); |
| await terminalHandler.processTerminalInput('W'); |
| |
| expect(terminalHandler.logger.statusText, contains('WIDGET DATA 1')); |
| expect(terminalHandler.logger.statusText, contains('WIDGET DATA 2')); |
| }); |
| |
| testWithoutContext('w,W - debugDumpApp with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpApp', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'WIDGET DATA 1'}, |
| ), |
| // Request 2. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugDumpApp', |
| args: <String, Object>{'isolateId': '1'}, |
| jsonResponse: <String, Object>{'data': 'WIDGET DATA 2'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('w'); |
| await terminalHandler.processTerminalInput('W'); |
| |
| expect(terminalHandler.logger.statusText, contains('WIDGET DATA 1')); |
| expect(terminalHandler.logger.statusText, contains('WIDGET DATA 2')); |
| }); |
| |
| testWithoutContext('v - launchDevToolsInBrowser', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[]); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| for (final FlutterDevice? device in runner.flutterDevices) { |
| expect(device!.device!.dds.calledLaunchDevToolsInBrowser, isFalse); |
| } |
| await terminalHandler.processTerminalInput('v'); |
| for (final FlutterDevice? device in runner.flutterDevices) { |
| expect(device!.device!.dds.calledLaunchDevToolsInBrowser, isTrue); |
| } |
| }); |
| |
| testWithoutContext('v - does not launchDevToolsInBrowser on web in profile mode', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| web: true, |
| buildMode: BuildMode.profile, |
| ); |
| |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| final DartDevelopmentService dds = runner.flutterDevices.single.device!.dds; |
| |
| expect(dds.calledLaunchDevToolsInBrowser, isFalse); |
| await terminalHandler.processTerminalInput('v'); |
| expect(dds.calledLaunchDevToolsInBrowser, isFalse); |
| }); |
| |
| testWithoutContext('w,W - debugDumpApp without service protocol is skipped', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('w'); |
| await terminalHandler.processTerminalInput('W'); |
| }); |
| |
| testWithoutContext('z,Z - debugToggleDebugCheckElevationsEnabled', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugCheckElevationsEnabled', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| // Request 2. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugCheckElevationsEnabled', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ]); |
| await terminalHandler.processTerminalInput('z'); |
| await terminalHandler.processTerminalInput('Z'); |
| }); |
| |
| testWithoutContext('z,Z - debugToggleDebugCheckElevationsEnabled with web target', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[ |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugCheckElevationsEnabled', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| // Request 2. |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.debugCheckElevationsEnabled', |
| args: <String, Object>{'isolateId': '1'}, |
| ), |
| ], web: true); |
| await terminalHandler.processTerminalInput('z'); |
| await terminalHandler.processTerminalInput('Z'); |
| }); |
| |
| testWithoutContext( |
| 'z,Z - debugToggleDebugCheckElevationsEnabled without service protocol is skipped', |
| () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsServiceProtocol: false, |
| ); |
| await terminalHandler.processTerminalInput('z'); |
| await terminalHandler.processTerminalInput('Z'); |
| }, |
| ); |
| |
| testWithoutContext('q,Q - exit', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[]); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| await terminalHandler.processTerminalInput('q'); |
| |
| expect(runner.calledExit, true); |
| runner.calledExit = false; |
| |
| await terminalHandler.processTerminalInput('Q'); |
| |
| expect(runner.calledExit, true); |
| }); |
| |
| testWithoutContext('r - hotReload unsupported', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsHotReload: false, |
| ); |
| await terminalHandler.processTerminalInput('r'); |
| }); |
| |
| testWithoutContext('R - hotRestart unsupported', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| supportsRestart: false, |
| ); |
| await terminalHandler.processTerminalInput('R'); |
| }); |
| |
| testWithoutContext('r - hotReload', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[]); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| |
| await terminalHandler.processTerminalInput('r'); |
| |
| expect(runner.calledReload, true); |
| expect(runner.calledRestart, false); |
| }); |
| |
| testWithoutContext('R - hotRestart', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler(<FakeVmServiceRequest>[]); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| |
| await terminalHandler.processTerminalInput('R'); |
| |
| expect(runner.calledReload, false); |
| expect(runner.calledRestart, true); |
| }); |
| |
| testWithoutContext('r - hotReload with non-fatal error', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| reloadExitCode: 1, |
| ); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| |
| await terminalHandler.processTerminalInput('r'); |
| |
| expect(runner.calledReload, true); |
| expect(runner.calledRestart, false); |
| expect( |
| terminalHandler.logger.statusText, |
| contains('Try again after fixing the above error(s).'), |
| ); |
| }); |
| |
| testWithoutContext('R - hotRestart with non-fatal error', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| reloadExitCode: 1, |
| ); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| |
| await terminalHandler.processTerminalInput('R'); |
| |
| expect(runner.calledReload, false); |
| expect(runner.calledRestart, true); |
| expect( |
| terminalHandler.logger.statusText, |
| contains('Try again after fixing the above error(s).'), |
| ); |
| }); |
| |
| testWithoutContext('r - hotReload with fatal error', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| reloadExitCode: 1, |
| fatalReloadError: true, |
| ); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| |
| await expectLater(() => terminalHandler.processTerminalInput('r'), throwsToolExit()); |
| |
| expect(runner.calledReload, true); |
| expect(runner.calledRestart, false); |
| }); |
| |
| testWithoutContext('R - hotRestart with fatal error', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| reloadExitCode: 1, |
| fatalReloadError: true, |
| ); |
| final runner = terminalHandler.residentRunner as FakeResidentRunner; |
| |
| await expectLater(() => terminalHandler.processTerminalInput('R'), throwsToolExit()); |
| |
| expect(runner.calledReload, false); |
| expect(runner.calledRestart, true); |
| }); |
| }); |
| |
| testWithoutContext('ResidentRunner clears the screen when it should', () async { |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| reloadExitCode: 1, |
| fatalReloadError: true, |
| ); |
| const message = 'This should be cleared'; |
| |
| expect(terminalHandler.logger.statusText, equals('')); |
| terminalHandler.logger.printStatus(message); |
| expect(terminalHandler.logger.statusText, equals('$message\n')); // printStatus makes a newline |
| |
| await terminalHandler.processTerminalInput('c'); |
| expect(terminalHandler.logger.statusText, equals('')); |
| }); |
| |
| testWithoutContext('s, can take screenshot on debug device that supports screenshot', () async { |
| final logger = BufferLogger.test(); |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[ |
| listViews, |
| FakeVmServiceRequest( |
| method: 'ext.flutter.debugAllowBanner', |
| args: <String, Object?>{'isolateId': fakeUnpausedIsolate.id, 'enabled': 'false'}, |
| ), |
| FakeVmServiceRequest( |
| method: 'ext.flutter.debugAllowBanner', |
| args: <String, Object?>{'isolateId': fakeUnpausedIsolate.id, 'enabled': 'true'}, |
| ), |
| ], |
| logger: logger, |
| supportsScreenshot: true, |
| ); |
| |
| await terminalHandler.processTerminalInput('s'); |
| |
| expect(logger.statusText, contains('Screenshot written to flutter_01.png (0kB)')); |
| }); |
| |
| testWithoutContext( |
| 's, will not take screenshot on non-web device without screenshot tooling support', |
| () async { |
| final logger = BufferLogger.test(); |
| final FileSystem fileSystem = MemoryFileSystem.test(); |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| logger: logger, |
| fileSystem: fileSystem, |
| ); |
| |
| await terminalHandler.processTerminalInput('s'); |
| |
| expect(logger.statusText, isNot(contains('Screenshot written to'))); |
| }, |
| ); |
| |
| testWithoutContext( |
| 's, can take screenshot on debug web device that does not support screenshot', |
| () async { |
| final logger = BufferLogger.test(); |
| final FileSystem fileSystem = MemoryFileSystem.test(); |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[ |
| listViews, |
| FakeVmServiceRequest( |
| method: 'ext.flutter.debugAllowBanner', |
| args: <String, Object?>{'isolateId': fakeUnpausedIsolate.id, 'enabled': 'false'}, |
| ), |
| FakeVmServiceRequest( |
| method: 'ext.dwds.screenshot', |
| args: <String, Object>{}, |
| jsonResponse: <String, Object>{ |
| 'data': base64.encode(<int>[1, 2, 3, 4]), |
| }, |
| ), |
| FakeVmServiceRequest( |
| method: 'ext.flutter.debugAllowBanner', |
| args: <String, Object?>{'isolateId': fakeUnpausedIsolate.id, 'enabled': 'true'}, |
| ), |
| ], |
| logger: logger, |
| web: true, |
| fileSystem: fileSystem, |
| ); |
| |
| await terminalHandler.processTerminalInput('s'); |
| |
| expect(logger.statusText, contains('Screenshot written to flutter_01.png (0kB)')); |
| expect(fileSystem.currentDirectory.childFile('flutter_01.png').readAsBytesSync(), <int>[ |
| 1, |
| 2, |
| 3, |
| 4, |
| ]); |
| }, |
| ); |
| |
| testWithoutContext( |
| 's, can take screenshot on device that does not support service protocol', |
| () async { |
| final logger = BufferLogger.test(); |
| final FileSystem fileSystem = MemoryFileSystem.test(); |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| logger: logger, |
| supportsScreenshot: true, |
| supportsServiceProtocol: false, |
| fileSystem: fileSystem, |
| ); |
| |
| await terminalHandler.processTerminalInput('s'); |
| |
| expect(logger.statusText, contains('Screenshot written to flutter_01.png (0kB)')); |
| expect(fileSystem.currentDirectory.childFile('flutter_01.png').readAsBytesSync(), <int>[ |
| 1, |
| 2, |
| 3, |
| 4, |
| ]); |
| }, |
| ); |
| |
| testWithoutContext( |
| 's, does not take a screenshot on a device that does not support screenshot or the service protocol', |
| () async { |
| final logger = BufferLogger.test(); |
| final FileSystem fileSystem = MemoryFileSystem.test(); |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| logger: logger, |
| supportsServiceProtocol: false, |
| fileSystem: fileSystem, |
| ); |
| |
| await terminalHandler.processTerminalInput('s'); |
| |
| expect(logger.statusText, '\n'); |
| expect(fileSystem.currentDirectory.childFile('flutter_01.png'), isNot(exists)); |
| }, |
| ); |
| |
| testWithoutContext( |
| 's, does not take a screenshot on a web device that does not support screenshot or the service protocol', |
| () async { |
| final logger = BufferLogger.test(); |
| final FileSystem fileSystem = MemoryFileSystem.test(); |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[], |
| logger: logger, |
| supportsServiceProtocol: false, |
| web: true, |
| fileSystem: fileSystem, |
| ); |
| |
| await terminalHandler.processTerminalInput('s'); |
| |
| expect(logger.statusText, '\n'); |
| expect(fileSystem.currentDirectory.childFile('flutter_01.png'), isNot(exists)); |
| }, |
| ); |
| |
| testWithoutContext( |
| 's, bails taking screenshot on debug device if dwds.screenshot throws RpcError, restoring banner', |
| () async { |
| final logger = BufferLogger.test(); |
| final FileSystem fileSystem = MemoryFileSystem.test(); |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[ |
| listViews, |
| FakeVmServiceRequest( |
| method: 'ext.flutter.debugAllowBanner', |
| args: <String, Object?>{'isolateId': fakeUnpausedIsolate.id, 'enabled': 'false'}, |
| ), |
| FakeVmServiceRequest( |
| method: 'ext.dwds.screenshot', |
| // Failed response, |
| error: FakeRPCError(code: vm_service.RPCErrorKind.kInternalError.code), |
| ), |
| FakeVmServiceRequest( |
| method: 'ext.flutter.debugAllowBanner', |
| args: <String, Object?>{'isolateId': fakeUnpausedIsolate.id, 'enabled': 'true'}, |
| ), |
| ], |
| logger: logger, |
| web: true, |
| fileSystem: fileSystem, |
| ); |
| |
| await terminalHandler.processTerminalInput('s'); |
| |
| expect(logger.errorText, contains('Error')); |
| }, |
| ); |
| |
| testWithoutContext( |
| 's, bails taking screenshot on debug device if debugAllowBanner during second request', |
| () async { |
| final logger = BufferLogger.test(); |
| final FileSystem fileSystem = MemoryFileSystem.test(); |
| final TerminalHandler terminalHandler = setUpTerminalHandler( |
| <FakeVmServiceRequest>[ |
| listViews, |
| FakeVmServiceRequest( |
| method: 'ext.flutter.debugAllowBanner', |
| args: <String, Object?>{'isolateId': fakeUnpausedIsolate.id, 'enabled': 'false'}, |
| ), |
| FakeVmServiceRequest( |
| method: 'ext.flutter.debugAllowBanner', |
| args: <String, Object?>{'isolateId': fakeUnpausedIsolate.id, 'enabled': 'true'}, |
| // Failed response, |
| error: FakeRPCError(code: vm_service.RPCErrorKind.kInternalError.code), |
| ), |
| ], |
| logger: logger, |
| supportsScreenshot: true, |
| fileSystem: fileSystem, |
| ); |
| |
| await terminalHandler.processTerminalInput('s'); |
| |
| expect(logger.errorText, contains('Error')); |
| }, |
| ); |
| |
| testWithoutContext('pidfile creation', () { |
| final testLogger = BufferLogger.test(); |
| final Signals signals = _TestSignals(Signals.defaultExitSignals); |
| final terminal = Terminal.test(); |
| final fs = MemoryFileSystem.test(); |
| final processInfo = ProcessInfo.test(fs); |
| final residentRunner = FakeResidentRunner( |
| FlutterDevice( |
| FakeDevice(), |
| buildInfo: BuildInfo.debug, |
| generator: FakeResidentCompiler(), |
| developmentShaderCompiler: const FakeShaderCompiler(), |
| ), |
| testLogger, |
| fs, |
| ); |
| residentRunner |
| ..supportsRestart = true |
| ..supportsServiceProtocol = true |
| ..stayResident = true; |
| |
| const filename = 'test.pid'; |
| final terminalHandler = TerminalHandler( |
| residentRunner, |
| logger: testLogger, |
| signals: signals, |
| terminal: terminal, |
| processInfo: processInfo, |
| reportReady: false, |
| pidFile: filename, |
| ); |
| |
| expect(fs.file(filename), isNot(exists)); |
| terminalHandler.setupTerminal(); |
| terminalHandler.registerSignalHandlers(); |
| expect(fs.file(filename), exists); |
| terminalHandler.stop(); |
| expect(fs.file(filename), isNot(exists)); |
| }); |
| } |
| |
| class FakeResidentRunner extends ResidentHandlers { |
| FakeResidentRunner(FlutterDevice device, this.logger, this.fileSystem) |
| : flutterDevices = <FlutterDevice>[device]; |
| |
| var calledDetach = false; |
| var calledPrint = false; |
| var calledExit = false; |
| var calledPrintWithDetails = false; |
| var calledReload = false; |
| var calledRestart = false; |
| var reloadExitCode = 0; |
| var fatalReloadError = false; |
| |
| @override |
| final Logger logger; |
| |
| @override |
| final FileSystem fileSystem; |
| |
| @override |
| final List<FlutterDevice> flutterDevices; |
| |
| @override |
| var canHotReload = true; |
| |
| @override |
| var hotMode = true; |
| |
| @override |
| var isRunningDebug = true; |
| |
| @override |
| var isRunningProfile = false; |
| |
| @override |
| var isRunningRelease = false; |
| |
| @override |
| var stayResident = true; |
| |
| @override |
| var supportsRestart = true; |
| |
| @override |
| var supportsDetach = true; |
| |
| @override |
| var supportsServiceProtocol = true; |
| |
| @override |
| Future<void> cleanupAfterSignal() async {} |
| |
| @override |
| Future<void> detach() async { |
| calledDetach = true; |
| } |
| |
| @override |
| Future<void> exit() async { |
| calledExit = true; |
| } |
| |
| @override |
| void printHelp({required bool details, bool reloadIsRestart = false}) { |
| if (details) { |
| calledPrintWithDetails = true; |
| } else { |
| calledPrint = true; |
| } |
| } |
| |
| @override |
| Future<void> runSourceGenerators() async {} |
| |
| @override |
| Future<OperationResult> restart({ |
| bool fullRestart = false, |
| bool pause = false, |
| String? reason, |
| }) async { |
| if (fullRestart && !supportsRestart) { |
| throw StateError('illegal restart'); |
| } |
| if (!fullRestart && !canHotReload) { |
| throw StateError('illegal reload'); |
| } |
| if (fullRestart) { |
| calledRestart = true; |
| } else { |
| calledReload = true; |
| } |
| return OperationResult(reloadExitCode, '', fatal: fatalReloadError); |
| } |
| } |
| |
| class FakeDevice extends Fake implements Device { |
| @override |
| Future<bool> isSupported() async => true; |
| |
| @override |
| var supportsScreenshot = false; |
| |
| @override |
| String get name => 'Fake Device'; |
| |
| @override |
| String get displayName => name; |
| |
| @override |
| var dds = DartDevelopmentService(logger: FakeLogger()); |
| |
| @override |
| Future<void> takeScreenshot(File file) async { |
| if (!supportsScreenshot) { |
| throw StateError('illegal screenshot attempt'); |
| } |
| file.writeAsBytesSync(<int>[1, 2, 3, 4]); |
| } |
| } |
| |
| TerminalHandler setUpTerminalHandler( |
| List<FakeVmServiceRequest> requests, { |
| bool supportsRestart = true, |
| bool supportsServiceProtocol = true, |
| bool supportsHotReload = true, |
| bool web = false, |
| bool fatalReloadError = false, |
| bool supportsScreenshot = false, |
| int reloadExitCode = 0, |
| BuildMode buildMode = BuildMode.debug, |
| Logger? logger, |
| FileSystem? fileSystem, |
| }) { |
| final Logger testLogger = logger ?? BufferLogger.test(); |
| final signals = Signals.test(); |
| final terminal = Terminal.test(); |
| final FileSystem localFileSystem = fileSystem ?? MemoryFileSystem.test(); |
| final processInfo = ProcessInfo.test(MemoryFileSystem.test()); |
| final device = FlutterDevice( |
| FakeDevice()..supportsScreenshot = supportsScreenshot, |
| buildInfo: BuildInfo( |
| buildMode, |
| '', |
| treeShakeIcons: false, |
| packageConfigPath: '.dart_tool/package_config.json', |
| ), |
| generator: FakeResidentCompiler(), |
| developmentShaderCompiler: const FakeShaderCompiler(), |
| targetPlatform: web ? TargetPlatform.web_javascript : TargetPlatform.android_arm, |
| ); |
| device.vmService = FakeVmServiceHost(requests: requests).vmService; |
| final residentRunner = FakeResidentRunner(device, testLogger, localFileSystem) |
| ..supportsServiceProtocol = supportsServiceProtocol |
| ..supportsRestart = supportsRestart |
| ..canHotReload = supportsHotReload |
| ..fatalReloadError = fatalReloadError |
| ..reloadExitCode = reloadExitCode; |
| |
| switch (buildMode) { |
| case BuildMode.debug: |
| residentRunner |
| ..isRunningDebug = true |
| ..isRunningProfile = false |
| ..isRunningRelease = false; |
| case BuildMode.profile: |
| residentRunner |
| ..isRunningDebug = false |
| ..isRunningProfile = true |
| ..isRunningRelease = false; |
| case BuildMode.release: |
| residentRunner |
| ..isRunningDebug = false |
| ..isRunningProfile = false |
| ..isRunningRelease = true; |
| case _: |
| // NOOP |
| } |
| return TerminalHandler( |
| residentRunner, |
| logger: testLogger, |
| signals: signals, |
| terminal: terminal, |
| processInfo: processInfo, |
| reportReady: false, |
| ); |
| } |
| |
| class FakeResidentCompiler extends Fake implements ResidentCompiler {} |
| |
| class TestRunner extends Fake implements ResidentRunner { |
| var hasHelpBeenPrinted = false; |
| |
| @override |
| Future<void> cleanupAfterSignal() async {} |
| |
| @override |
| Future<void> cleanupAtFinish() async {} |
| |
| @override |
| void printHelp({bool? details, bool reloadIsRestart = false}) { |
| hasHelpBeenPrinted = true; |
| } |
| |
| @override |
| Future<int?> run({ |
| Completer<DebugConnectionInfo>? connectionInfoCompleter, |
| Completer<void>? appStartedCompleter, |
| bool enableDevTools = false, |
| String? route, |
| }) async => null; |
| |
| @override |
| Future<int?> attach({ |
| Completer<DebugConnectionInfo>? connectionInfoCompleter, |
| Completer<void>? appStartedCompleter, |
| bool enableDevTools = false, |
| bool needsFullRestart = true, |
| }) async => null; |
| } |
| |
| class _TestSignals implements Signals { |
| _TestSignals(this.exitSignals); |
| |
| final List<ProcessSignal> exitSignals; |
| |
| final _handlersTable = <ProcessSignal, Map<Object, SignalHandler>>{}; |
| |
| @override |
| Object addHandler(ProcessSignal signal, SignalHandler handler) { |
| final token = Object(); |
| _handlersTable.putIfAbsent(signal, () => <Object, SignalHandler>{})[token] = handler; |
| return token; |
| } |
| |
| @override |
| Future<bool> removeHandler(ProcessSignal signal, Object token) async { |
| if (!_handlersTable.containsKey(signal)) { |
| return false; |
| } |
| if (!_handlersTable[signal]!.containsKey(token)) { |
| return false; |
| } |
| _handlersTable[signal]!.remove(token); |
| return true; |
| } |
| |
| @override |
| Stream<Object> get errors => _errors.stream; |
| final _errors = StreamController<Object>(); |
| } |
| |
| class FakeShaderCompiler implements DevelopmentShaderCompiler { |
| const FakeShaderCompiler(); |
| |
| @override |
| void configureCompiler(TargetPlatform? platform) {} |
| |
| @override |
| Future<DevFSContent> recompileShader(DevFSContent inputShader) { |
| throw UnimplementedError(); |
| } |
| } |