analyze_size_test.dart 8.58 KB
Newer Older
1 2 3 4
// 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.

5
import 'package:file/file.dart';
6 7 8 9
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/base/io.dart';

import '../src/common.dart';
10
import 'test_utils.dart';
11

12 13 14
// This test file does not use [getLocalEngineArguments] because it requires
// multiple specific artifact output types.

15 16
const String apkDebugMessage = 'A summary of your APK analysis can be found at: ';
const String iosDebugMessage = 'A summary of your iOS bundle analysis can be found at: ';
17
const String macOSDebugMessage = 'A summary of your macOS bundle analysis can be found at: ';
18
const String runDevToolsMessage = 'dart devtools ';
19 20

void main() {
21
  testWithoutContext('--analyze-size flag produces expected output on hello_world for Android', () async {
22
    final String workingDirectory = fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world');
23 24
    final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
    final ProcessResult result = await processManager.run(<String>[
25 26 27
      flutterBin,
      'build',
      'apk',
28
      '--verbose',
29
      '--analyze-size',
30
      '--target-platform=android-arm64',
31
    ], workingDirectory: workingDirectory);
32

33 34 35 36
    expect(
      result,
      const ProcessResultMatcher(stdoutPattern: 'app-release.apk (total compressed)'),
    );
37 38 39 40 41 42

    final String line = result.stdout.toString()
      .split('\n')
      .firstWhere((String line) => line.contains(apkDebugMessage));

    final String outputFilePath = line.split(apkDebugMessage).last.trim();
43
    expect(fileSystem.file(fileSystem.path.join(workingDirectory, outputFilePath)), exists);
44
    expect(outputFilePath, contains('.flutter-devtools'));
45 46 47 48 49 50 51

    final String devToolsCommand = result.stdout.toString()
        .split('\n')
        .firstWhere((String line) => line.contains(runDevToolsMessage));
    final String commandArguments = devToolsCommand.split(runDevToolsMessage).last.trim();
    final String relativeAppSizePath = outputFilePath.split('.flutter-devtools/').last.trim();
    expect(commandArguments.contains('--appSizeBase=$relativeAppSizePath'), isTrue);
52 53
  });

54
  testWithoutContext('--analyze-size flag produces expected output on hello_world for iOS', () async {
55
    final String workingDirectory = fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world');
56
    final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
57 58
    final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('flutter_size_test.');
    final Directory codeSizeDir = tempDir.childDirectory('code size dir')..createSync();
59
    final ProcessResult result = await processManager.run(<String>[
60 61 62
      flutterBin,
      'build',
      'ios',
63
      '--verbose',
64
      '--analyze-size',
65
      '--code-size-directory=${codeSizeDir.path}',
66
      '--no-codesign',
67
    ], workingDirectory: workingDirectory);
68

69 70 71 72
    expect(
      result,
      const ProcessResultMatcher(stdoutPattern: 'Dart AOT symbols accounted decompressed size'),
    );
73 74 75 76 77 78

    final String line = result.stdout.toString()
      .split('\n')
      .firstWhere((String line) => line.contains(iosDebugMessage));

    final String outputFilePath = line.split(iosDebugMessage).last.trim();
79 80 81 82 83 84 85
    expect(fileSystem.file(fileSystem.path.join(workingDirectory, outputFilePath)), exists);

    final String devToolsCommand = result.stdout.toString()
        .split('\n')
        .firstWhere((String line) => line.contains(runDevToolsMessage));
    final String commandArguments = devToolsCommand.split(runDevToolsMessage).last.trim();
    final String relativeAppSizePath = outputFilePath.split('.flutter-devtools/').last.trim();
86

87
    expect(commandArguments.contains('--appSizeBase=$relativeAppSizePath'), isTrue);
88 89
    expect(codeSizeDir.existsSync(), true);
    tempDir.deleteSync(recursive: true);
90
  }, skip: !platform.isMacOS); // [intended] iOS can only be built on macos.
91 92 93 94 95 96 97 98 99 100

  testWithoutContext('--analyze-size flag produces expected output on hello_world for macOS', () async {
    final String workingDirectory = fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world');
    final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
    final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('flutter_size_test.');
    final Directory codeSizeDir = tempDir.childDirectory('code size dir')..createSync();

    final ProcessResult configResult = await processManager.run(<String>[
      flutterBin,
      'config',
101
      '--verbose',
102 103
      '--enable-macos-desktop',
    ], workingDirectory: workingDirectory);
104

105 106 107 108 109
    expect(
      configResult,
      const ProcessResultMatcher(),
    );

110 111 112
    printOnFailure('Output of flutter config:');
    printOnFailure(configResult.stdout.toString());
    printOnFailure(configResult.stderr.toString());
113 114 115 116 117 118 119 120 121

    final ProcessResult result = await processManager.run(<String>[
      flutterBin,
      'build',
      'macos',
      '--analyze-size',
      '--code-size-directory=${codeSizeDir.path}',
    ], workingDirectory: workingDirectory);

122 123 124 125
    expect(
      result,
      const ProcessResultMatcher(stdoutPattern: 'Dart AOT symbols accounted decompressed size'),
    );
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142

    final String line = result.stdout.toString()
      .split('\n')
      .firstWhere((String line) => line.contains(macOSDebugMessage));

    final String outputFilePath = line.split(macOSDebugMessage).last.trim();
    expect(fileSystem.file(fileSystem.path.join(workingDirectory, outputFilePath)), exists);

    final String devToolsCommand = result.stdout.toString()
        .split('\n')
        .firstWhere((String line) => line.contains(runDevToolsMessage));
    final String commandArguments = devToolsCommand.split(runDevToolsMessage).last.trim();
    final String relativeAppSizePath = outputFilePath.split('.flutter-devtools/').last.trim();

    expect(commandArguments.contains('--appSizeBase=$relativeAppSizePath'), isTrue);
    expect(codeSizeDir.existsSync(), true);
    tempDir.deleteSync(recursive: true);
143
  }, skip: !platform.isMacOS); // [intended] this is a macos only test.
144

145 146 147
  testWithoutContext('--analyze-size is only supported in release mode', () async {
    final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
    final ProcessResult result = await processManager.run(<String>[
148 149 150
      flutterBin,
      'build',
      'apk',
151
      '--verbose',
152 153 154
      '--analyze-size',
      '--target-platform=android-arm64',
      '--debug',
155
    ], workingDirectory: fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world'));
156 157 158 159 160 161 162
    expect(
      result,
      const ProcessResultMatcher(
        exitCode: 1,
        stderrPattern: '"--analyze-size" can only be used on release builds',
      ),
    );
163
  });
164 165 166

  testWithoutContext('--analyze-size is not supported in combination with --split-debug-info', () async {
    final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
167
    final List<String> command = <String>[
168 169 170
      flutterBin,
      'build',
      'apk',
171
      '--verbose',
172 173
      '--analyze-size',
      '--target-platform=android-arm64',
174
      '--split-debug-info=infos',
175 176 177 178 179 180
    ];
    final String workingDirectory =
        fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world');
    final ProcessResult result =
        await processManager.run(command, workingDirectory: workingDirectory);

181 182 183 184 185 186 187
    expect(
      result,
      const ProcessResultMatcher(
        exitCode: 1,
        stderrPattern: '"--analyze-size" cannot be combined with "--split-debug-info"',
      ),
    );
188
  });
189 190 191

  testWithoutContext('--analyze-size allows overriding the directory for code size files', () async {
    final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
192
    final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('flutter_size_test.');
193

194
    final List<String> command = <String>[
195 196 197
      flutterBin,
      'build',
      'apk',
198
      '--verbose',
199 200 201 202
      '--analyze-size',
      '--code-size-directory=${tempDir.path}',
      '--target-platform=android-arm64',
      '--release',
203 204 205 206 207 208 209 210 211 212 213
    ];
    final String workingDirectory = fileSystem.path.join(
      getFlutterRoot(),
      'examples',
      'hello_world',
    );
    final ProcessResult result = await processManager.run(
      command,
      workingDirectory: workingDirectory,
    );

214 215 216 217
    expect(
      result,
      const ProcessResultMatcher(),
    );
218

219 220 221
    expect(tempDir, exists);
    expect(tempDir.childFile('snapshot.arm64-v8a.json'), exists);
    expect(tempDir.childFile('trace.arm64-v8a.json'), exists);
222 223 224

    tempDir.deleteSync(recursive: true);
  });
225
}