hot_reload_test.dart 6.5 KB
Newer Older
1 2 3 4
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7 8 9
// Integration tests which invoke flutter instead of unit testing the code
// will not produce meaningful coverage information - we can measure coverage
// from the isolate running the test, but not from the isolate started via
// the command line process.
@Tags(<String>['no_coverage'])
10 11
import 'dart:async';

12
import 'package:file/file.dart';
13
import 'package:flutter_tools/src/base/common.dart';
14
import 'package:flutter_tools/src/base/file_system.dart';
15
import 'package:vm_service/vm_service.dart';
16

17
import '../src/common.dart';
18
import 'test_data/hot_reload_project.dart';
19
import 'test_driver.dart';
20
import 'test_utils.dart';
21 22

void main() {
23
  group('hot reload tests', () {
24
    Directory tempDir;
25
    final HotReloadProject _project = HotReloadProject();
26
    FlutterRunTestDriver _flutter;
27

28
    setUp(() async {
29
      tempDir = createResolvedTempDirectorySync('hot_reload_test.');
30
      await _project.setUpIn(tempDir);
31
      _flutter = FlutterRunTestDriver(tempDir);
32 33 34
    });

    tearDown(() async {
35
      await _flutter?.stop();
36
      tryToDelete(tempDir);
37 38
    });

39
    test('hot reload works without error', () async {
40
      await _flutter.run();
41
      await _flutter.hotReload();
42
    });
43

44
    test('newly added code executes during hot reload', () async {
45 46 47
      await _flutter.run();
      _project.uncommentHotReloadPrint();
      final StringBuffer stdout = StringBuffer();
48
      final StreamSubscription<String> subscription = _flutter.stdout.listen(stdout.writeln);
49
      try {
50 51
        await _flutter.hotReload();
        expect(stdout.toString(), contains('(((((RELOAD WORKED)))))'));
52
      } finally {
53
        await subscription.cancel();
54 55 56
      }
    });

57
    test('hot restart works without error', () async {
58 59
      await _flutter.run();
      await _flutter.hotRestart();
60
    });
61

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    test('breakpoints are hit after hot reload', () async {
      Isolate isolate;
      await _flutter.run(withDebugger: true, startPaused: true);
      final Completer<void> sawTick1 = Completer<void>();
      final Completer<void> sawTick3 = Completer<void>();
      final Completer<void> sawDebuggerPausedMessage = Completer<void>();
      final StreamSubscription<String> subscription = _flutter.stdout.listen(
        (String line) {
          if (line.contains('((((TICK 1))))')) {
            expect(sawTick1.isCompleted, isFalse);
            sawTick1.complete();
          }
          if (line.contains('((((TICK 3))))')) {
            expect(sawTick3.isCompleted, isFalse);
            sawTick3.complete();
          }
          if (line.contains('The application is paused in the debugger on a breakpoint.')) {
            expect(sawDebuggerPausedMessage.isCompleted, isFalse);
            sawDebuggerPausedMessage.complete();
          }
        },
      );
      await _flutter.resume(); // we start paused so we can set up our TICK 1 listener before the app starts
85
      unawaited(sawTick1.future.timeout(
86 87
        const Duration(seconds: 5),
        onTimeout: () { print('The test app is taking longer than expected to print its synchronization line...'); },
88
      ));
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
      await sawTick1.future; // after this, app is in steady state
      await _flutter.addBreakpoint(
        _project.scheduledBreakpointUri,
        _project.scheduledBreakpointLine,
      );
      await _flutter.hotReload(); // reload triggers code which eventually hits the breakpoint
      isolate = await _flutter.waitForPause();
      expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
      await _flutter.resume();
      await _flutter.addBreakpoint(
        _project.buildBreakpointUri,
        _project.buildBreakpointLine,
      );
      bool reloaded = false;
      final Future<void> reloadFuture = _flutter.hotReload().then((void value) { reloaded = true; });
      await sawTick3.future; // this should happen before it pauses
      isolate = await _flutter.waitForPause();
      expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
      await sawDebuggerPausedMessage.future;
      expect(reloaded, isFalse);
      await _flutter.resume();
      await reloadFuture;
      expect(reloaded, isTrue);
      reloaded = false;
      await subscription.cancel();
    });

    test('hot reload doesn\'t reassemble if paused', () async {
117
      await _flutter.run(withDebugger: true);
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
      final Completer<void> sawTick2 = Completer<void>();
      final Completer<void> sawTick3 = Completer<void>();
      final Completer<void> sawDebuggerPausedMessage1 = Completer<void>();
      final Completer<void> sawDebuggerPausedMessage2 = Completer<void>();
      final StreamSubscription<String> subscription = _flutter.stdout.listen(
        (String line) {
          if (line.contains('((((TICK 2))))')) {
            expect(sawTick2.isCompleted, isFalse);
            sawTick2.complete();
          }
          if (line.contains('The application is paused in the debugger on a breakpoint.')) {
            expect(sawDebuggerPausedMessage1.isCompleted, isFalse);
            sawDebuggerPausedMessage1.complete();
          }
          if (line.contains('The application is paused in the debugger on a breakpoint; interface might not update.')) {
            expect(sawDebuggerPausedMessage2.isCompleted, isFalse);
            sawDebuggerPausedMessage2.complete();
          }
        },
      );
      await _flutter.addBreakpoint(
        _project.buildBreakpointUri,
        _project.buildBreakpointLine,
      );
      bool reloaded = false;
      final Future<void> reloadFuture = _flutter.hotReload().then((void value) { reloaded = true; });
      await sawTick2.future; // this should happen before it pauses
      final Isolate isolate = await _flutter.waitForPause();
146
      expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
147 148 149 150 151 152 153 154 155
      expect(reloaded, isFalse);
      await sawDebuggerPausedMessage1.future; // this is the one where it say "uh, you broke into the debugger while reloading"
      await reloadFuture; // this is the one where it times out because you're in the debugger
      expect(reloaded, isTrue);
      await _flutter.hotReload(); // now we're already paused
      expect(sawTick3.isCompleted, isFalse);
      await sawDebuggerPausedMessage2.future; // so we just get told that nothing is going to happen
      await _flutter.resume();
      await subscription.cancel();
156
    });
Dan Field's avatar
Dan Field committed
157
  }, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
158
}