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

import 'dart:async';

7
import 'package:file/memory.dart';
8
import 'package:flutter_tools/src/artifacts.dart';
9
import 'package:flutter_tools/src/base/io.dart';
10
import 'package:flutter_tools/src/base/logger.dart';
11
import 'package:flutter_tools/src/build_info.dart';
12 13 14
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:mockito/mockito.dart';
15
import 'package:package_config/package_config.dart';
16 17 18 19 20 21 22 23 24 25 26 27
import 'package:process/process.dart';

import '../src/common.dart';
import '../src/context.dart';
import '../src/mocks.dart';

void main() {
  ProcessManager mockProcessManager;
  MockProcess mockFrontendServer;
  MockStdIn mockFrontendServerStdIn;
  MockStream mockFrontendServerStdErr;

28 29
  List<String> latestCommand;

30 31 32 33 34 35 36 37 38 39 40 41 42
  setUp(() {
    mockProcessManager = MockProcessManager();
    mockFrontendServer = MockProcess();
    mockFrontendServerStdIn = MockStdIn();
    mockFrontendServerStdErr = MockStream();

    when(mockFrontendServer.stderr)
        .thenAnswer((Invocation invocation) => mockFrontendServerStdErr);
    final StreamController<String> stdErrStreamController = StreamController<String>();
    when(mockFrontendServerStdErr.transform<String>(any)).thenAnswer((_) => stdErrStreamController.stream);
    when(mockFrontendServer.stdin).thenReturn(mockFrontendServerStdIn);
    when(mockProcessManager.canRun(any)).thenReturn(true);
    when(mockProcessManager.start(any)).thenAnswer(
43
        (Invocation invocation) {
44
          latestCommand = invocation.positionalArguments.first as List<String>;
45 46
          return Future<Process>.value(mockFrontendServer);
        });
47 48 49
    when(mockFrontendServer.exitCode).thenAnswer((_) async => 0);
  });

50
  testWithoutContext('batch compile single dart successful compilation', () async {
51 52 53 54 55 56
    when(mockFrontendServer.stdout)
        .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
          Future<List<int>>.value(utf8.encode(
            'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0'
          ))
        ));
57 58 59 60 61 62 63 64 65
    final BufferLogger logger = BufferLogger.test();
    final KernelCompiler kernelCompiler = KernelCompiler(
      artifacts: Artifacts.test(),
      fileSystem: MemoryFileSystem.test(),
      fileSystemRoots: <String>[],
      fileSystemScheme: '',
      logger: logger,
      processManager: mockProcessManager
    );
66 67
    final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
      mainPath: '/path/to/main.dart',
68
      buildMode: BuildMode.debug,
69
      trackWidgetCreation: false,
70
      dartDefines: const <String>[],
71 72
      packageConfig: PackageConfig.empty,
      packagesPath: '.packages',
73 74 75
    );

    expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
76
    expect(logger.errorText, equals('line1\nline2\n'));
77
    expect(output.outputFilename, equals('/path/to/main.dart.dill'));
78 79 80 81
    final VerificationResult argVerification = verify(mockProcessManager.start(captureAny));
    expect(argVerification.captured.single, containsAll(<String>[
      '-Ddart.developer.causal_async_stacks=true',
    ]));
82 83
  });

84
  testWithoutContext('passes correct AOT config to kernel compiler in aot/profile mode', () async {
85 86 87 88 89 90
    when(mockFrontendServer.stdout)
      .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
        Future<List<int>>.value(utf8.encode(
          'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0'
        ))
      ));
91 92 93 94 95 96 97 98
    final KernelCompiler kernelCompiler = KernelCompiler(
      artifacts: Artifacts.test(),
      fileSystem: MemoryFileSystem.test(),
      fileSystemRoots: <String>[],
      fileSystemScheme: '',
      logger: BufferLogger.test(),
      processManager: mockProcessManager
    );
99 100 101 102 103 104
    await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
      mainPath: '/path/to/main.dart',
      buildMode: BuildMode.profile,
      trackWidgetCreation: false,
      aot: true,
      dartDefines: const <String>[],
105 106
      packageConfig: PackageConfig.empty,
      packagesPath: '.packages',
107 108 109 110 111 112 113 114 115
    );

    expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
    final VerificationResult argVerification = verify(mockProcessManager.start(captureAny));
    expect(argVerification.captured.single, containsAll(<String>[
      '--aot',
      '--tfa',
      '-Ddart.vm.profile=true',
      '-Ddart.vm.product=false',
116
      '-Ddart.developer.causal_async_stacks=false',
117 118 119
    ]));
  });

120
  testWithoutContext('passes correct AOT config to kernel compiler in aot/release mode', () async {
121 122 123 124 125 126
    when(mockFrontendServer.stdout)
      .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
        Future<List<int>>.value(utf8.encode(
          'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0'
        ))
      ));
127 128 129 130 131 132 133 134
    final KernelCompiler kernelCompiler = KernelCompiler(
      artifacts: Artifacts.test(),
      fileSystem: MemoryFileSystem.test(),
      fileSystemRoots: <String>[],
      fileSystemScheme: '',
      logger: BufferLogger.test(),
      processManager: mockProcessManager
    );
135 136 137 138 139
    await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
      mainPath: '/path/to/main.dart',
      buildMode: BuildMode.release,
      trackWidgetCreation: false,
      aot: true,
140
      dartDefines: const <String>[],
141 142
      packageConfig: PackageConfig.empty,
      packagesPath: '.packages',
143 144 145 146
    );

    expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
    final VerificationResult argVerification = verify(mockProcessManager.start(captureAny));
147 148 149 150 151
    expect(argVerification.captured.single, containsAll(<String>[
      '--aot',
      '--tfa',
      '-Ddart.vm.profile=false',
      '-Ddart.vm.product=true',
152
      '-Ddart.developer.causal_async_stacks=false',
153
    ]));
154 155
  });

156
  testWithoutContext('batch compile single dart failed compilation', () async {
157 158 159 160 161 162
    when(mockFrontendServer.stdout)
        .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
          Future<List<int>>.value(utf8.encode(
            'result abc\nline1\nline2\nabc\nabc'
          ))
        ));
163 164 165 166 167 168 169 170 171
    final BufferLogger logger = BufferLogger.test();
    final KernelCompiler kernelCompiler = KernelCompiler(
      artifacts: Artifacts.test(),
      fileSystem: MemoryFileSystem.test(),
      fileSystemRoots: <String>[],
      fileSystemScheme: '',
      logger: logger,
      processManager: mockProcessManager
    );
172 173
    final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
      mainPath: '/path/to/main.dart',
174
      buildMode: BuildMode.debug,
175
      trackWidgetCreation: false,
176
      dartDefines: const <String>[],
177 178
      packageConfig: PackageConfig.empty,
      packagesPath: '.packages',
179 180 181
    );

    expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
182
    expect(logger.errorText, equals('line1\nline2\n'));
183 184 185
    expect(output, equals(null));
  });

186
  testWithoutContext('batch compile single dart abnormal compiler termination', () async {
187 188 189 190 191 192 193
    when(mockFrontendServer.exitCode).thenAnswer((_) async => 255);
    when(mockFrontendServer.stdout)
        .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
        Future<List<int>>.value(utf8.encode(
            'result abc\nline1\nline2\nabc\nabc'
        ))
    ));
194 195 196 197 198 199 200 201 202
    final BufferLogger logger = BufferLogger.test();
    final KernelCompiler kernelCompiler = KernelCompiler(
      artifacts: Artifacts.test(),
      fileSystem: MemoryFileSystem.test(),
      fileSystemRoots: <String>[],
      fileSystemScheme: '',
      logger: logger,
      processManager: mockProcessManager
    );
203 204 205
    final CompilerOutput output = await kernelCompiler.compile(
      sdkRoot: '/path/to/sdkroot',
      mainPath: '/path/to/main.dart',
206
      buildMode: BuildMode.debug,
207
      trackWidgetCreation: false,
208
      dartDefines: const <String>[],
209 210
      packageConfig: PackageConfig.empty,
      packagesPath: '.packages',
211 212
    );
    expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
213
    expect(logger.errorText, equals('line1\nline2\n'));
214 215
    expect(output, equals(null));
  });
216

217
  testWithoutContext('passes dartDefines to the kernel compiler', () async {
218 219 220 221 222
    // Use unsuccessful result because it's easier to setup in test. We only care about arguments passed to the compiler.
    when(mockFrontendServer.exitCode).thenAnswer((_) async => 255);
    when(mockFrontendServer.stdout).thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
      Future<List<int>>.value(<int>[])
    ));
223 224 225 226 227 228 229 230
    final KernelCompiler kernelCompiler = KernelCompiler(
      artifacts: Artifacts.test(),
      fileSystem: MemoryFileSystem.test(),
      fileSystemRoots: <String>[],
      fileSystemScheme: '',
      logger: BufferLogger.test(),
      processManager: mockProcessManager
    );
231 232 233 234 235
    await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
      mainPath: '/path/to/main.dart',
      buildMode: BuildMode.debug,
      trackWidgetCreation: false,
      dartDefines: const <String>['FOO=bar', 'BAZ=qux'],
236 237
      packageConfig: PackageConfig.empty,
      packagesPath: '.packages',
238 239 240
    );

    expect(latestCommand, containsAllInOrder(<String>['-DFOO=bar', '-DBAZ=qux']));
241 242
  });

243
  testWithoutContext('maps a file to a multiroot scheme if provided', () async {
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    // Use unsuccessful result because it's easier to setup in test. We only care about arguments passed to the compiler.
    when(mockFrontendServer.exitCode).thenAnswer((_) async => 255);
    when(mockFrontendServer.stdout).thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
      Future<List<int>>.value(<int>[])
    ));
    final KernelCompiler kernelCompiler = KernelCompiler(
      artifacts: Artifacts.test(),
      fileSystem: MemoryFileSystem.test(),
      fileSystemRoots: <String>[
        '/foo/bar/fizz',
      ],
      fileSystemScheme: 'scheme',
      logger: BufferLogger.test(),
      processManager: mockProcessManager
    );
    await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
      mainPath: '/foo/bar/fizz/main.dart',
      buildMode: BuildMode.debug,
      trackWidgetCreation: false,
      dartDefines: const <String>[],
      packageConfig: PackageConfig.empty,
      packagesPath: '.packages',
    );

    expect(latestCommand, containsAll(<String>['scheme:///main.dart']));
269
  });
270 271 272 273
}

class MockProcess extends Mock implements Process {}
class MockProcessManager extends Mock implements ProcessManager {}