android_test.dart 11.9 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
import 'package:file/memory.dart';
6
import 'package:file_testing/file_testing.dart';
7
import 'package:flutter_tools/src/artifacts.dart';
8
import 'package:flutter_tools/src/base/file_system.dart';
9
import 'package:flutter_tools/src/base/logger.dart';
10
import 'package:flutter_tools/src/base/platform.dart';
11 12 13
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/android.dart';
14
import 'package:flutter_tools/src/build_system/targets/assets.dart';
15
import 'package:flutter_tools/src/build_system/targets/common.dart';
16
import 'package:flutter_tools/src/convert.dart';
17 18

import '../../../src/common.dart';
19
import '../../../src/context.dart';
20
import '../../../src/fake_process_manager.dart';
21

22
final Platform platform = FakePlatform(operatingSystem: 'linux', environment: const <String, String>{});
23
void main() {
24 25 26 27 28 29 30 31 32 33
  FakeProcessManager processManager;
  FileSystem fileSystem;
  Artifacts artifacts;
  Logger logger;

  setUp(() {
    logger = BufferLogger.test();
    fileSystem = MemoryFileSystem.test();
    processManager = FakeProcessManager.list(<FakeCommand>[]);
    artifacts = Artifacts.test();
34 35
  });

36
  testWithoutContext('Android AOT targets has analyicsName', () {
37 38 39
    expect(androidArmProfile.analyticsName, 'android_aot');
  });

40
  testUsingContext('debug bundle contains expected resources', () async {
41
    final Environment environment = Environment.test(
42 43
      fileSystem.currentDirectory,
      outputDir: fileSystem.directory('out')..createSync(),
44 45
      defines: <String, String>{
        kBuildMode: 'debug',
46
      },
47 48 49 50
      processManager: processManager,
      artifacts: artifacts,
      fileSystem: fileSystem,
      logger: logger,
51 52 53 54 55
    );
    environment.buildDir.createSync(recursive: true);

    // create pre-requisites.
    environment.buildDir.childFile('app.dill')
56
      .writeAsStringSync('abcd');
57 58 59 60 61 62
    fileSystem
      .file(artifacts.getArtifactPath(Artifact.vmSnapshotData, mode: BuildMode.debug))
      .createSync(recursive: true);
    fileSystem
      .file(artifacts.getArtifactPath(Artifact.isolateSnapshotData, mode: BuildMode.debug))
      .createSync(recursive: true);
63 64 65

    await const DebugAndroidApplication().build(environment);

66 67 68 69 70 71
    expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'isolate_snapshot_data')).existsSync(), true);
    expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'vm_snapshot_data')).existsSync(), true);
    expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'kernel_blob.bin')).existsSync(), true);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
72 73
  });

74
  testUsingContext('debug bundle contains expected resources with bundle SkSL', () async {
75
    final Environment environment = Environment.test(
76 77
      fileSystem.currentDirectory,
      outputDir: fileSystem.directory('out')..createSync(),
78 79 80 81 82 83
      defines: <String, String>{
        kBuildMode: 'debug',
      },
      inputs: <String, String>{
        kBundleSkSLPath: 'bundle.sksl'
      },
84 85 86 87
      processManager: processManager,
      artifacts: artifacts,
      fileSystem: fileSystem,
      logger: logger,
88 89 90
      engineVersion: '2',
    );
    environment.buildDir.createSync(recursive: true);
91
    fileSystem.file('bundle.sksl').writeAsStringSync(json.encode(
92 93 94 95 96 97 98 99 100 101 102 103
      <String, Object>{
        'engineRevision': '2',
        'platform': 'android',
        'data': <String, Object>{
          'A': 'B',
        }
      }
    ));

    // create pre-requisites.
    environment.buildDir.childFile('app.dill')
      .writeAsStringSync('abcd');
104 105 106 107 108 109
    fileSystem
      .file(artifacts.getArtifactPath(Artifact.vmSnapshotData, mode: BuildMode.debug))
      .createSync(recursive: true);
    fileSystem
      .file(artifacts.getArtifactPath(Artifact.isolateSnapshotData, mode: BuildMode.debug))
      .createSync(recursive: true);
110 111 112

    await const DebugAndroidApplication().build(environment);

113 114 115 116 117 118 119
    expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'isolate_snapshot_data')), exists);
    expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'vm_snapshot_data')), exists);
    expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'kernel_blob.bin')), exists);
    expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'io.flutter.shaders.json')), exists);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
120 121
  });

122
  testUsingContext('profile bundle contains expected resources', () async {
123
    final Environment environment = Environment.test(
124 125
      fileSystem.currentDirectory,
      outputDir: fileSystem.directory('out')..createSync(),
126 127
      defines: <String, String>{
        kBuildMode: 'profile',
128
      },
129 130 131 132
      artifacts: artifacts,
      processManager: processManager,
      fileSystem: fileSystem,
      logger: logger,
133 134 135 136 137
    );
    environment.buildDir.createSync(recursive: true);

    // create pre-requisites.
    environment.buildDir.childFile('app.so')
138
      .writeAsStringSync('abcd');
139 140 141

    await const ProfileAndroidApplication().build(environment);

142 143 144 145
    expect(fileSystem.file(fileSystem.path.join('out', 'app.so')).existsSync(), true);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
146 147
  });

148
  testWithoutContext('release bundle contains expected resources', () async {
149
    final Environment environment = Environment.test(
150 151
      fileSystem.currentDirectory,
      outputDir: fileSystem.directory('out')..createSync(),
152 153
      defines: <String, String>{
        kBuildMode: 'release',
154
      },
155 156 157 158
      artifacts: artifacts,
      processManager: processManager,
      fileSystem: fileSystem,
      logger: logger,
159 160 161 162 163
    );
    environment.buildDir.createSync(recursive: true);

    // create pre-requisites.
    environment.buildDir.childFile('app.so')
164
      .writeAsStringSync('abcd');
165 166 167

    await const ReleaseAndroidApplication().build(environment);

168
    expect(fileSystem.file(fileSystem.path.join('out', 'app.so')).existsSync(), true);
169
  });
170

171 172
  testUsingContext('AndroidAot can build provided target platform', () async {
    processManager = FakeProcessManager.list(<FakeCommand>[]);
173
    final Environment environment = Environment.test(
174 175
      fileSystem.currentDirectory,
      outputDir: fileSystem.directory('out')..createSync(),
176 177
      defines: <String, String>{
        kBuildMode: 'release',
178
      },
179 180 181 182
      artifacts: artifacts,
      processManager: processManager,
      fileSystem: fileSystem,
      logger: logger,
183
    );
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    processManager.addCommand(FakeCommand(command: <String>[
      artifacts.getArtifactPath(
        Artifact.genSnapshot,
        platform: TargetPlatform.android_arm64,
        mode: BuildMode.release,
      ),
      '--deterministic',
      '--snapshot_kind=app-aot-elf',
      '--elf=${environment.buildDir.childDirectory('arm64-v8a').childFile('app.so').path}',
      '--strip',
      '--no-causal-async-stacks',
      '--lazy-async-stacks',
      environment.buildDir.childFile('app.dill').path,
      ],
    ));
199
    environment.buildDir.createSync(recursive: true);
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
    environment.buildDir.childFile('app.dill').createSync();
    environment.projectDir.childFile('.packages').writeAsStringSync('\n');
    const AndroidAot androidAot = AndroidAot(TargetPlatform.android_arm64, BuildMode.release);

    await androidAot.build(environment);

    expect(processManager.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('AndroidAot provide code size information.', () async {
    processManager = FakeProcessManager.list(<FakeCommand>[]);
    final Environment environment = Environment.test(
      fileSystem.currentDirectory,
      outputDir: fileSystem.directory('out')..createSync(),
      defines: <String, String>{
        kBuildMode: 'release',
        kCodeSizeDirectory: 'code_size_1',
      },
      artifacts: artifacts,
      processManager: processManager,
      fileSystem: fileSystem,
      logger: logger,
    );
    processManager.addCommand(FakeCommand(command: <String>[
      artifacts.getArtifactPath(
        Artifact.genSnapshot,
        platform: TargetPlatform.android_arm64,
        mode: BuildMode.release,
      ),
      '--deterministic',
      '--write-v8-snapshot-profile-to=code_size_1/snapshot.arm64-v8a.json',
      '--trace-precompiler-to=code_size_1/trace.arm64-v8a.json',
      '--snapshot_kind=app-aot-elf',
      '--elf=${environment.buildDir.childDirectory('arm64-v8a').childFile('app.so').path}',
      '--strip',
      '--no-causal-async-stacks',
      '--lazy-async-stacks',
      environment.buildDir.childFile('app.dill').path,
      ],
    ));
    environment.buildDir.createSync(recursive: true);
244
    environment.buildDir.childFile('app.dill').createSync();
245
    environment.projectDir.childFile('.packages').writeAsStringSync('\n');
246 247 248
    const AndroidAot androidAot = AndroidAot(TargetPlatform.android_arm64, BuildMode.release);

    await androidAot.build(environment);
249

250
    expect(processManager.hasRemainingExpectations, false);
251
  }, overrides: <Type, Generator>{
252 253
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
254 255
  });

256 257
  testUsingContext('kExtraGenSnapshotOptions passes values to gen_snapshot', () async {
    processManager = FakeProcessManager.list(<FakeCommand>[]);
258
    final Environment environment = Environment.test(
259 260
      fileSystem.currentDirectory,
      outputDir: fileSystem.directory('out')..createSync(),
261 262 263 264
      defines: <String, String>{
        kBuildMode: 'release',
        kExtraGenSnapshotOptions: 'foo,bar,baz=2',
        kTargetPlatform: 'android-arm',
265
      },
266 267 268 269
      processManager: processManager,
      artifacts: artifacts,
      fileSystem: fileSystem,
      logger: logger,
270
    );
271
    processManager.addCommand(
272
      FakeCommand(command: <String>[
273 274 275 276 277
        artifacts.getArtifactPath(
          Artifact.genSnapshot,
          platform: TargetPlatform.android_arm64,
          mode: BuildMode.release,
        ),
278
        '--deterministic',
279 280 281
        'foo',
        'bar',
        'baz=2',
282 283 284 285 286 287
        '--snapshot_kind=app-aot-elf',
        '--elf=${environment.buildDir.childDirectory('arm64-v8a').childFile('app.so').path}',
        '--strip',
        '--no-causal-async-stacks',
        '--lazy-async-stacks',
        environment.buildDir.childFile('app.dill').path
288 289
      ],
    ));
290 291 292
    environment.buildDir.createSync(recursive: true);
    environment.buildDir.childFile('app.dill').createSync();
    environment.projectDir.childFile('.packages').writeAsStringSync('\n');
293 294 295 296

    await const AndroidAot(TargetPlatform.android_arm64, BuildMode.release)
      .build(environment);
  }, overrides: <Type, Generator>{
297 298
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
299 300
  });

301
  testWithoutContext('android aot bundle copies so from abi directory', () async {
302
    final Environment environment = Environment.test(
303 304
      fileSystem.currentDirectory,
      outputDir: fileSystem.directory('out')..createSync(),
305 306
      defines: <String, String>{
        kBuildMode: 'release',
307
      },
308 309 310 311
      processManager: processManager,
      artifacts: artifacts,
      fileSystem: fileSystem,
      logger: logger,
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
    );
    environment.buildDir.createSync(recursive: true);
    const AndroidAot androidAot = AndroidAot(TargetPlatform.android_arm64, BuildMode.release);
    const AndroidAotBundle androidAotBundle = AndroidAotBundle(androidAot);
    // Create required files.
    environment.buildDir
      .childDirectory('arm64-v8a')
      .childFile('app.so')
      .createSync(recursive: true);

    await androidAotBundle.build(environment);

    expect(environment.outputDir
      .childDirectory('arm64-v8a')
      .childFile('app.so').existsSync(), true);
  });
328
}