hot_mode_tests.dart 6.74 KB
Newer Older
1 2 3 4
// Copyright 2017 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
import 'dart:async';
import 'dart:convert';
7 8
import 'dart:io';

9
import 'package:flutter_devicelab/framework/ios.dart';
10 11 12 13 14 15
import 'package:path/path.dart' as path;

import '../framework/adb.dart';
import '../framework/framework.dart';
import '../framework/utils.dart';

16 17 18
final Directory _editedFlutterGalleryDir = dir(path.join(Directory.systemTemp.path, 'edited_flutter_gallery'));
final Directory flutterGalleryDir = dir(path.join(flutterDirectory.path, 'examples/flutter_gallery'));

19
TaskFunction createHotModeTest({ bool isPreviewDart2 = true }) {
20 21 22
  return () async {
    final Device device = await devices.workingDevice;
    await device.unlock();
23
    final File benchmarkFile = file(path.join(_editedFlutterGalleryDir.path, 'hot_benchmark.json'));
24 25
    rm(benchmarkFile);
    final List<String> options = <String>[
26
      '--hot', '-d', device.deviceId, '--benchmark', '--verbose', '--resident'
27
    ];
28 29 30 31
    if (isPreviewDart2)
      options.add('--preview-dart-2');
    else
      options.add('--no-preview-dart-2');
32
    setLocalEngineOptionIfNecessary(options);
33
    int hotReloadCount = 0;
34 35
    Map<String, dynamic> twoReloadsData;
    Map<String, dynamic> freshRestartReloadsData;
36 37 38 39 40
    await inDirectory(flutterDirectory, () async {
      rmTree(_editedFlutterGalleryDir);
      mkdirs(_editedFlutterGalleryDir);
      recursiveCopy(flutterGalleryDir, _editedFlutterGalleryDir);
      await inDirectory(_editedFlutterGalleryDir, () async {
41 42
        if (deviceOperatingSystem == DeviceOperatingSystem.ios)
          await prepareProvisioningCertificates(_editedFlutterGalleryDir.path);
43 44 45 46 47 48
        {
          final Process process = await startProcess(
              path.join(flutterDirectory.path, 'bin', 'flutter'),
              <String>['run']..addAll(options),
              environment: null
          );
49

50 51 52
          final Completer<Null> stdoutDone = new Completer<Null>();
          final Completer<Null> stderrDone = new Completer<Null>();
          process.stdout
53
              .transform(utf8.decoder)
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
              .transform(const LineSplitter())
              .listen((String line) {
            if (line.contains('\] Reloaded ')) {
              if (hotReloadCount == 0) {
                // Update the file and reload again.
                final File appDartSource = file(path.join(
                    _editedFlutterGalleryDir.path, 'lib/gallery/app.dart'
                ));
                appDartSource.writeAsStringSync(
                    appDartSource.readAsStringSync().replaceFirst(
                        "'Flutter Gallery'", "'Updated Flutter Gallery'"
                    )
                );
                process.stdin.writeln('r');
                ++hotReloadCount;
              } else {
                // Quit after second hot reload.
                process.stdin.writeln('q');
              }
            }
            print('stdout: $line');
          }, onDone: () {
            stdoutDone.complete();
          });
          process.stderr
79
              .transform(utf8.decoder)
80 81 82 83 84 85 86 87 88 89
              .transform(const LineSplitter())
              .listen((String line) {
            print('stderr: $line');
          }, onDone: () {
            stderrDone.complete();
          });

          await Future.wait<Null>(
              <Future<Null>>[stdoutDone.future, stderrDone.future]);
          await process.exitCode;
90

91
          twoReloadsData = json.decode(benchmarkFile.readAsStringSync());
92 93 94
        }
        benchmarkFile.deleteSync();

95 96
        // start `flutter run` again to make sure it loads from the previous state
        // (in case of --preview-dart-2 frontend loads up from previously generated kernel files).
97 98 99 100 101 102 103 104 105
        {
          final Process process = await startProcess(
              path.join(flutterDirectory.path, 'bin', 'flutter'),
              <String>['run']..addAll(options),
              environment: null
          );
          final Completer<Null> stdoutDone = new Completer<Null>();
          final Completer<Null> stderrDone = new Completer<Null>();
          process.stdout
106
              .transform(utf8.decoder)
107 108 109
              .transform(const LineSplitter())
              .listen((String line) {
            if (line.contains('\] Reloaded ')) {
110 111
              process.stdin.writeln('q');
            }
112 113 114 115 116
            print('stdout: $line');
          }, onDone: () {
            stdoutDone.complete();
          });
          process.stderr
117
              .transform(utf8.decoder)
118 119 120 121 122 123 124 125 126 127
              .transform(const LineSplitter())
              .listen((String line) {
            print('stderr: $line');
          }, onDone: () {
            stderrDone.complete();
          });

          await Future.wait<Null>(
              <Future<Null>>[stdoutDone.future, stderrDone.future]);
          await process.exitCode;
128

129
          freshRestartReloadsData =
130
              json.decode(benchmarkFile.readAsStringSync());
131
        }
132 133
      });
    });
134 135 136



137 138 139 140 141 142 143 144
    return new TaskResult.success(
      <String, dynamic> {
        'hotReloadInitialDevFSSyncMilliseconds': twoReloadsData['hotReloadInitialDevFSSyncMilliseconds'][0],
        'hotRestartMillisecondsToFrame': twoReloadsData['hotRestartMillisecondsToFrame'][0],
        'hotReloadMillisecondsToFrame' : twoReloadsData['hotReloadMillisecondsToFrame'][0],
        'hotReloadDevFSSyncMilliseconds': twoReloadsData['hotReloadDevFSSyncMilliseconds'][0],
        'hotReloadFlutterReassembleMilliseconds': twoReloadsData['hotReloadFlutterReassembleMilliseconds'][0],
        'hotReloadVMReloadMilliseconds': twoReloadsData['hotReloadVMReloadMilliseconds'][0],
145
        'hotReloadMillisecondsToFrameAfterChange' : twoReloadsData['hotReloadMillisecondsToFrame'][1],
146 147 148
        'hotReloadDevFSSyncMillisecondsAfterChange': twoReloadsData['hotReloadDevFSSyncMilliseconds'][1],
        'hotReloadFlutterReassembleMillisecondsAfterChange': twoReloadsData['hotReloadFlutterReassembleMilliseconds'][1],
        'hotReloadVMReloadMillisecondsAfterChange': twoReloadsData['hotReloadVMReloadMilliseconds'][1],
149
        'hotReloadInitialDevFSSyncAfterRelaunchMilliseconds' : freshRestartReloadsData['hotReloadInitialDevFSSyncMilliseconds'][0],
150 151 152 153 154 155 156 157
      },
      benchmarkScoreKeys: <String>[
        'hotReloadInitialDevFSSyncMilliseconds',
        'hotRestartMillisecondsToFrame',
        'hotReloadMillisecondsToFrame',
        'hotReloadDevFSSyncMilliseconds',
        'hotReloadFlutterReassembleMilliseconds',
        'hotReloadVMReloadMilliseconds',
158
        'hotReloadMillisecondsToFrameAfterChange',
159 160 161
        'hotReloadDevFSSyncMillisecondsAfterChange',
        'hotReloadFlutterReassembleMillisecondsAfterChange',
        'hotReloadVMReloadMillisecondsAfterChange',
162
        'hotReloadInitialDevFSSyncAfterRelaunchMilliseconds',
163 164
      ]
    );
165 166
  };
}