resident_web_runner_cold_test.dart 8.32 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
// @dart = 2.8

7 8
import 'dart:async';

9
import 'package:file/memory.dart';
10
import 'package:flutter_tools/src/application_package.dart';
11
import 'package:flutter_tools/src/base/common.dart';
12
import 'package:flutter_tools/src/base/file_system.dart';
13
import 'package:flutter_tools/src/base/logger.dart';
14
import 'package:flutter_tools/src/base/time.dart';
15
import 'package:flutter_tools/src/build_info.dart';
16
import 'package:flutter_tools/src/build_system/build_system.dart';
17
import 'package:flutter_tools/src/devfs.dart';
18
import 'package:flutter_tools/src/device.dart';
19 20
import 'package:flutter_tools/src/isolated/devfs_web.dart';
import 'package:flutter_tools/src/isolated/resident_web_runner.dart';
21
import 'package:flutter_tools/src/project.dart';
22
import 'package:flutter_tools/src/reporting/reporting.dart';
23
import 'package:flutter_tools/src/resident_runner.dart';
24 25
import 'package:flutter_tools/src/vmservice.dart';
import 'package:test/fake.dart';
26 27

import '../src/common.dart';
28
import '../src/context.dart';
29
import '../src/test_build_system.dart';
30 31

void main() {
32 33 34
  FakeFlutterDevice mockFlutterDevice;
  FakeWebDevFS mockWebDevFS;
  FileSystem fileSystem;
35 36

  setUp(() {
37 38 39 40 41 42 43 44 45 46
    fileSystem = MemoryFileSystem.test();
    mockWebDevFS = FakeWebDevFS();
    final FakeWebDevice mockWebDevice = FakeWebDevice();
    mockFlutterDevice = FakeFlutterDevice(mockWebDevice);
    mockFlutterDevice._devFS = mockWebDevFS;

    fileSystem.file('.packages').writeAsStringSync('\n');
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true);
    fileSystem.file(fileSystem.path.join('web', 'index.html')).createSync(recursive: true);
47 48
  });

49 50 51
  testUsingContext('Can successfully run and connect without vmservice', () async {
    final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
    final ResidentWebRunner residentWebRunner = ResidentWebRunner(
52 53 54 55 56 57
      mockFlutterDevice,
      flutterProject: project,
      debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
      ipv6: true,
      stayResident: true,
      urlTunneller: null,
58 59 60 61
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
      usage: TestUsage(),
62
    );
63 64 65 66 67 68 69 70

    final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    final DebugConnectionInfo debugConnectionInfo = await connectionInfoCompleter.future;

    expect(debugConnectionInfo.wsUri, null);
71
  }, overrides: <Type, Generator>{
72
    BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
73
    FileSystem: () => fileSystem,
74 75
    ProcessManager: () => FakeProcessManager.any(),
  });
76

77
  // Regression test for https://github.com/flutter/flutter/issues/60613
78
  testUsingContext('ResidentWebRunner calls appFailedToStart if initial compilation fails', () async {
79 80 81 82 83 84 85 86 87 88 89 90 91
    final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
    final ResidentWebRunner residentWebRunner = ResidentWebRunner(
      mockFlutterDevice,
      flutterProject: project,
      debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
      ipv6: true,
      stayResident: true,
      urlTunneller: null,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
      usage: TestUsage(),
    );
92

93
    expect(() => residentWebRunner.run(), throwsToolExit());
94 95
    expect(await residentWebRunner.waitForAppToFinish(), 1);
  }, overrides: <Type, Generator>{
96
    BuildSystem: () => TestBuildSystem.all(BuildResult(success: false)),
97
    FileSystem: () => fileSystem,
98 99
    ProcessManager: () => FakeProcessManager.any(),
  });
100 101

  // Regression test for https://github.com/flutter/flutter/issues/60613
102
  testUsingContext('ResidentWebRunner calls appFailedToStart if error is thrown during startup', () async {
103 104 105 106 107 108 109 110 111 112 113 114 115
    final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
    final ResidentWebRunner residentWebRunner = ResidentWebRunner(
      mockFlutterDevice,
      flutterProject: project,
      debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
      ipv6: true,
      stayResident: true,
      urlTunneller: null,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
      usage: TestUsage(),
    );
116

117
    expect(() async => residentWebRunner.run(), throwsException);
118 119
    expect(await residentWebRunner.waitForAppToFinish(), 1);
  }, overrides: <Type, Generator>{
120
    BuildSystem: () => TestBuildSystem.error(Exception('foo')),
121
    FileSystem: () => fileSystem,
122 123
    ProcessManager: () => FakeProcessManager.any(),
  });
124

125
  testUsingContext('Can full restart after attaching', () async {
126 127 128 129 130 131 132 133 134 135 136 137 138
    final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
    final ResidentWebRunner residentWebRunner = ResidentWebRunner(
      mockFlutterDevice,
      flutterProject: project,
      debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
      ipv6: true,
      stayResident: true,
      urlTunneller: null,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
      usage: TestUsage(),
    );
139
    final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
140
    unawaited(residentWebRunner.run(
141 142 143 144 145 146
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    final OperationResult result = await residentWebRunner.restart(fullRestart: true);

    expect(result.code, 0);
147
  }, overrides: <Type, Generator>{
148
    BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
149
    FileSystem: () => fileSystem,
150 151
    ProcessManager: () => FakeProcessManager.any(),
  });
152

153
  testUsingContext('Fails on compilation errors in hot restart', () async {
154 155 156 157 158 159 160 161 162 163 164 165 166
    final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
    final ResidentWebRunner residentWebRunner = ResidentWebRunner(
      mockFlutterDevice,
      flutterProject: project,
      debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
      ipv6: true,
      stayResident: true,
      urlTunneller: null,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
      usage: TestUsage(),
    );
167
    final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
168
    unawaited(residentWebRunner.run(
169 170 171 172 173 174 175
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    final OperationResult result = await residentWebRunner.restart(fullRestart: true);

    expect(result.code, 1);
    expect(result.message, contains('Failed to recompile application.'));
176
  }, overrides: <Type, Generator>{
177 178 179 180
    BuildSystem: () => TestBuildSystem.list(<BuildResult>[
      BuildResult(success: true),
      BuildResult(success: false),
    ]),
181
    FileSystem: () => fileSystem,
182 183
    ProcessManager: () => FakeProcessManager.any(),
  });
184
}
185

186 187 188
class FakeWebDevFS extends Fake implements WebDevFS {
  @override
  List<Uri> get sources => <Uri>[];
189

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
  @override
  Future<Uri> create() async {
    return Uri.base;
  }
}

class FakeWebDevice extends Fake implements Device {
  @override
  String get name => 'web';

  @override
  Future<bool> stopApp(
    covariant ApplicationPackage app, {
    String userIdentifier,
  }) async {
    return true;
  }

  @override
  Future<LaunchResult> startApp(
    covariant ApplicationPackage package, {
    String mainPath,
    String route,
    DebuggingOptions debuggingOptions,
    Map<String, dynamic> platformArgs,
    bool prebuiltApplication = false,
    bool ipv6 = false,
    String userIdentifier,
  }) async {
    return LaunchResult.succeeded();
  }
221 222
}

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
class FakeFlutterDevice extends Fake implements FlutterDevice {
  FakeFlutterDevice(this.device);

  @override
  final FakeWebDevice device;


  DevFS _devFS;

  @override
  DevFS get devFS => _devFS;

  @override
  set devFS(DevFS value) { }

  @override
  FlutterVmService vmService;
}