| // 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. |
| |
| // @dart = 2.8 |
| |
| import 'package:flutter_tools/src/base/platform.dart'; |
| import 'package:flutter_tools/src/devtools_launcher.dart'; |
| import 'package:flutter_tools/src/vmservice.dart'; |
| import 'package:vm_service/vm_service.dart' as vm_service; |
| |
| import 'package:flutter_tools/src/base/logger.dart'; |
| import 'package:flutter_tools/src/resident_devtools_handler.dart'; |
| import 'package:flutter_tools/src/resident_runner.dart'; |
| import 'package:test/fake.dart'; |
| |
| import '../src/common.dart'; |
| import '../src/context.dart'; |
| |
| final vm_service.Isolate isolate = vm_service.Isolate( |
| id: '1', |
| pauseEvent: vm_service.Event( |
| kind: vm_service.EventKind.kResume, |
| timestamp: 0 |
| ), |
| breakpoints: <vm_service.Breakpoint>[], |
| exceptionPauseMode: null, |
| 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>[], |
| extensionRPCs: <String>['foo'] |
| ); |
| |
| final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate( |
| id: '1', |
| pauseEvent: vm_service.Event( |
| kind: vm_service.EventKind.kResume, |
| timestamp: 0 |
| ), |
| breakpoints: <vm_service.Breakpoint>[], |
| exceptionPauseMode: null, |
| 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 vm_service.VM fakeVM = vm_service.VM( |
| isolates: <vm_service.IsolateRef>[fakeUnpausedIsolate], |
| pid: 1, |
| hostCPU: '', |
| isolateGroups: <vm_service.IsolateGroupRef>[], |
| targetCPU: '', |
| startTime: 0, |
| name: 'dart', |
| architectureBits: 64, |
| operatingSystem: '', |
| version: '', |
| systemIsolateGroups: <vm_service.IsolateGroupRef>[], |
| systemIsolates: <vm_service.IsolateRef>[], |
| ); |
| |
| final FlutterView fakeFlutterView = FlutterView( |
| id: 'a', |
| uiIsolate: fakeUnpausedIsolate, |
| ); |
| |
| final FakeVmServiceRequest listViews = FakeVmServiceRequest( |
| method: kListViewsMethod, |
| jsonResponse: <String, Object>{ |
| 'views': <Object>[ |
| fakeFlutterView.toJson(), |
| ], |
| }, |
| ); |
| |
| void main() { |
| testWithoutContext('Does not serve devtools if launcher is null', () async { |
| final ResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler( |
| null, |
| FakeResidentRunner(), |
| BufferLogger.test(), |
| ); |
| |
| await handler.serveAndAnnounceDevTools(flutterDevices: <FlutterDevice>[]); |
| |
| expect(handler.activeDevToolsServer, null); |
| }); |
| |
| testWithoutContext('Does not serve devtools if ResidentRunner does not support the service protocol', () async { |
| final ResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler( |
| FakeDevtoolsLauncher(), |
| FakeResidentRunner()..supportsServiceProtocol = false, |
| BufferLogger.test(), |
| ); |
| |
| await handler.serveAndAnnounceDevTools(flutterDevices: <FlutterDevice>[]); |
| |
| expect(handler.activeDevToolsServer, null); |
| }); |
| |
| testWithoutContext('Can use devtools with existing devtools URI', () async { |
| final DevtoolsServerLauncher launcher = DevtoolsServerLauncher( |
| processManager: FakeProcessManager.list(<FakeCommand>[]), |
| pubExecutable: 'pub', |
| logger: BufferLogger.test(), |
| platform: FakePlatform(), |
| persistentToolState: null, |
| ); |
| final ResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler( |
| // Uses real devtools instance which should be a no-op if |
| // URI is already set. |
| launcher, |
| FakeResidentRunner(), |
| BufferLogger.test(), |
| ); |
| |
| await handler.serveAndAnnounceDevTools( |
| devToolsServerAddress: Uri.parse('http://localhost:8181'), |
| flutterDevices: <FlutterDevice>[], |
| ); |
| |
| expect(handler.activeDevToolsServer.host, 'localhost'); |
| expect(handler.activeDevToolsServer.port, 8181); |
| }); |
| |
| testWithoutContext('serveAndAnnounceDevTools with attached device does not fail on null vm service', () async { |
| final ResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler( |
| FakeDevtoolsLauncher()..activeDevToolsServer = DevToolsServerAddress('localhost', 8080), |
| FakeResidentRunner(), |
| BufferLogger.test(), |
| ); |
| |
| // VM Service is intentionally null |
| final FakeFlutterDevice device = FakeFlutterDevice(); |
| |
| await handler.serveAndAnnounceDevTools( |
| flutterDevices: <FlutterDevice>[device], |
| ); |
| }); |
| |
| testWithoutContext('serveAndAnnounceDevTools with invokes devtools and vm_service setter', () async { |
| final ResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler( |
| FakeDevtoolsLauncher()..activeDevToolsServer = DevToolsServerAddress('localhost', 8080), |
| FakeResidentRunner(), |
| BufferLogger.test(), |
| ); |
| final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ |
| const FakeVmServiceRequest( |
| method: 'streamListen', |
| args: <String, Object>{ |
| 'streamId': 'Extension', |
| } |
| ), |
| FakeVmServiceRequest(method: 'getVM', jsonResponse: fakeVM.toJson()), |
| FakeVmServiceRequest( |
| method: 'getIsolate', |
| jsonResponse: isolate.toJson(), |
| args: <String, Object>{ |
| 'isolateId': '1', |
| }, |
| ), |
| FakeVmServiceStreamResponse( |
| streamId: 'Extension', |
| event: vm_service.Event( |
| timestamp: 0, |
| extensionKind: 'Flutter.FrameworkInitialization', |
| kind: 'test', |
| ), |
| ), |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.activeDevToolsServerAddress', |
| args: <String, Object>{ |
| 'isolateId': '1', |
| 'value': 'http://localhost:8080', |
| }, |
| ), |
| listViews, |
| const FakeVmServiceRequest( |
| method: 'ext.flutter.connectedVmServiceUri', |
| args: <String, Object>{ |
| 'isolateId': '1', |
| 'value': 'http://localhost:1234', |
| }, |
| ), |
| ]); |
| |
| final FakeFlutterDevice device = FakeFlutterDevice() |
| ..vmService = fakeVmServiceHost.vmService; |
| setHttpAddress(Uri.parse('http://localhost:1234'), fakeVmServiceHost.vmService); |
| |
| await handler.serveAndAnnounceDevTools( |
| flutterDevices: <FlutterDevice>[device], |
| ); |
| }); |
| |
| testWithoutContext('wait for extension handles an immediate extension', () { |
| final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ |
| const FakeVmServiceRequest( |
| method: 'streamListen', |
| args: <String, Object>{ |
| 'streamId': 'Extension', |
| } |
| ), |
| FakeVmServiceRequest(method: 'getVM', jsonResponse: fakeVM.toJson()), |
| FakeVmServiceRequest( |
| method: 'getIsolate', |
| jsonResponse: isolate.toJson(), |
| args: <String, Object>{ |
| 'isolateId': '1', |
| }, |
| ), |
| ]); |
| waitForExtension(fakeVmServiceHost.vmService, 'foo'); |
| }); |
| |
| testWithoutContext('wait for extension handles no isolates', () { |
| final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ |
| const FakeVmServiceRequest( |
| method: 'streamListen', |
| args: <String, Object>{ |
| 'streamId': 'Extension', |
| } |
| ), |
| FakeVmServiceRequest(method: 'getVM', jsonResponse: vm_service.VM( |
| isolates: <vm_service.IsolateRef>[], |
| pid: 1, |
| hostCPU: '', |
| isolateGroups: <vm_service.IsolateGroupRef>[], |
| targetCPU: '', |
| startTime: 0, |
| name: 'dart', |
| architectureBits: 64, |
| operatingSystem: '', |
| version: '', |
| systemIsolateGroups: <vm_service.IsolateGroupRef>[], |
| systemIsolates: <vm_service.IsolateRef>[], |
| ).toJson()), |
| FakeVmServiceStreamResponse( |
| streamId: 'Extension', |
| event: vm_service.Event( |
| timestamp: 0, |
| extensionKind: 'Flutter.FrameworkInitialization', |
| kind: 'test', |
| ), |
| ), |
| ]); |
| waitForExtension(fakeVmServiceHost.vmService, 'foo'); |
| }); |
| } |
| |
| |
| class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher { |
| @override |
| DevToolsServerAddress activeDevToolsServer; |
| |
| @override |
| Future<DevToolsServerAddress> serve() { |
| return null; |
| } |
| |
| @override |
| Future<void> get ready => Future<void>.value(); |
| } |
| |
| class FakeResidentRunner extends Fake implements ResidentRunner { |
| @override |
| bool supportsServiceProtocol = true; |
| |
| @override |
| bool reportedDebuggers = false; |
| } |
| |
| class FakeFlutterDevice extends Fake implements FlutterDevice { |
| @override |
| vm_service.VmService vmService; |
| } |