build_info_test.dart 15.2 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:flutter_tools/src/artifacts.dart';
6
import 'package:flutter_tools/src/base/logger.dart';
7 8
import 'package:flutter_tools/src/build_info.dart';

9
import '../src/common.dart';
10
import '../src/context.dart';
11 12

void main() {
13
  late BufferLogger logger;
14 15 16
  setUp(() {
    logger = BufferLogger.test();
  });
17 18

  group('Validate build number', () {
19
    testWithoutContext('CFBundleVersion for iOS', () async {
20
      String? buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, 'xyz', logger);
21
      expect(buildName, isNull);
22
      buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '0.0.1', logger);
23
      expect(buildName, '0.0.1');
24
      buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '123.xyz', logger);
25
      expect(buildName, '123');
26
      buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '123.456.xyz', logger);
27 28 29
      expect(buildName, '123.456');
    });

30
    testWithoutContext('versionCode for Android', () async {
31
      String? buildName = validatedBuildNumberForPlatform(TargetPlatform.android_arm, '123.abc+-', logger);
32
      expect(buildName, '123');
33
      buildName = validatedBuildNumberForPlatform(TargetPlatform.android_arm, 'abc', logger);
34 35 36 37 38
      expect(buildName, '1');
    });
  });

  group('Validate build name', () {
39
    testWithoutContext('CFBundleShortVersionString for iOS', () async {
40
      String? buildName = validatedBuildNameForPlatform(TargetPlatform.ios, 'xyz', logger);
41
      expect(buildName, isNull);
42
      buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '0.0.1', logger);
43
      expect(buildName, '0.0.1');
44 45 46

      buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '123.456.xyz', logger);
      expect(logger.traceText, contains('Invalid build-name'));
47
      expect(buildName, '123.456.0');
48 49

      buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '123.xyz', logger);
50 51 52
      expect(buildName, '123.0.0');
    });

53
    testWithoutContext('versionName for Android', () async {
54
      String? buildName = validatedBuildNameForPlatform(TargetPlatform.android_arm, '123.abc+-', logger);
55
      expect(buildName, '123.abc+-');
56
      buildName = validatedBuildNameForPlatform(TargetPlatform.android_arm, 'abc+-', logger);
57 58
      expect(buildName, 'abc+-');
    });
59

60
    testWithoutContext('build mode configuration is correct', () {
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
      expect(BuildMode.debug.isRelease, false);
      expect(BuildMode.debug.isPrecompiled, false);
      expect(BuildMode.debug.isJit, true);

      expect(BuildMode.profile.isRelease, false);
      expect(BuildMode.profile.isPrecompiled, true);
      expect(BuildMode.profile.isJit, false);

      expect(BuildMode.release.isRelease, true);
      expect(BuildMode.release.isPrecompiled, true);
      expect(BuildMode.release.isJit, false);

      expect(BuildMode.jitRelease.isRelease, true);
      expect(BuildMode.jitRelease.isPrecompiled, false);
      expect(BuildMode.jitRelease.isJit, true);

      expect(BuildMode.fromName('debug'), BuildMode.debug);
      expect(BuildMode.fromName('profile'), BuildMode.profile);
      expect(BuildMode.fromName('jit_release'), BuildMode.jitRelease);
      expect(BuildMode.fromName('release'), BuildMode.release);
Dan Field's avatar
Dan Field committed
81
      expect(() => BuildMode.fromName('foo'), throwsArgumentError);
82
    });
83
  });
84

85 86 87 88 89 90 91 92 93 94 95 96
  testWithoutContext('getDartNameForDarwinArch returns name used in Dart SDK', () {
    expect(getDartNameForDarwinArch(DarwinArch.armv7),  'armv7');
    expect(getDartNameForDarwinArch(DarwinArch.arm64),  'arm64');
    expect(getDartNameForDarwinArch(DarwinArch.x86_64), 'x64');
  });

  testWithoutContext('getNameForDarwinArch returns Apple names', () {
    expect(getNameForDarwinArch(DarwinArch.armv7),  'armv7');
    expect(getNameForDarwinArch(DarwinArch.arm64),  'arm64');
    expect(getNameForDarwinArch(DarwinArch.x86_64), 'x86_64');
  });

97
  testWithoutContext('getNameForTargetPlatform on Darwin arches', () {
98 99 100 101 102
    expect(getNameForTargetPlatform(TargetPlatform.ios, darwinArch: DarwinArch.arm64), 'ios-arm64');
    expect(getNameForTargetPlatform(TargetPlatform.ios, darwinArch: DarwinArch.armv7), 'ios-armv7');
    expect(getNameForTargetPlatform(TargetPlatform.ios, darwinArch: DarwinArch.x86_64), 'ios-x86_64');
    expect(getNameForTargetPlatform(TargetPlatform.android), isNot(contains('ios')));
  });
103

104 105 106 107 108 109 110 111 112 113 114 115 116 117 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
  testWithoutContext('defaultIOSArchsForEnvironment', () {
    expect(defaultIOSArchsForEnvironment(
      EnvironmentType.physical,
      Artifacts.test(localEngine: 'ios_debug_unopt'),
    ).single, DarwinArch.arm64);

    expect(defaultIOSArchsForEnvironment(
      EnvironmentType.simulator,
      Artifacts.test(localEngine: 'ios_debug_sim_unopt'),
    ).single, DarwinArch.x86_64);

    expect(defaultIOSArchsForEnvironment(
      EnvironmentType.simulator,
      Artifacts.test(localEngine: 'ios_debug_sim_unopt_arm64'),
    ).single, DarwinArch.arm64);

    expect(defaultIOSArchsForEnvironment(
      EnvironmentType.physical, Artifacts.test(),
    ).single, DarwinArch.arm64);

    expect(defaultIOSArchsForEnvironment(
      EnvironmentType.simulator, Artifacts.test(),
    ), <DarwinArch>[ DarwinArch.x86_64, DarwinArch.arm64 ]);
  });

  testWithoutContext('defaultMacOSArchsForEnvironment', () {
    expect(defaultMacOSArchsForEnvironment(
      Artifacts.test(localEngine: 'host_debug_unopt'),
    ).single, DarwinArch.x86_64);

    expect(defaultMacOSArchsForEnvironment(
      Artifacts.test(localEngine: 'host_debug_unopt_arm64'),
    ).single, DarwinArch.arm64);

    expect(defaultMacOSArchsForEnvironment(
      Artifacts.test(),
    ), <DarwinArch>[ DarwinArch.x86_64, DarwinArch.arm64 ]);
  });

143
  testWithoutContext('getIOSArchForName on Darwin arches', () {
144 145 146 147
    expect(getIOSArchForName('armv7'), DarwinArch.armv7);
    expect(getIOSArchForName('arm64'), DarwinArch.arm64);
    expect(getIOSArchForName('arm64e'), DarwinArch.arm64);
    expect(getIOSArchForName('x86_64'), DarwinArch.x86_64);
148
    expect(() => getIOSArchForName('bogus'), throwsException);
149
  });
150

151 152 153 154 155 156 157 158 159 160 161
  testWithoutContext('named BuildInfo has correct defaults', () {
    expect(BuildInfo.debug.mode, BuildMode.debug);
    expect(BuildInfo.debug.trackWidgetCreation, true);

    expect(BuildInfo.profile.mode, BuildMode.profile);
    expect(BuildInfo.profile.trackWidgetCreation, false);

    expect(BuildInfo.release.mode, BuildMode.release);
    expect(BuildInfo.release.trackWidgetCreation, false);
  });

162 163 164 165 166 167 168 169 170 171
  testWithoutContext('toBuildSystemEnvironment encoding of standard values', () {
    const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
      treeShakeIcons: true,
      trackWidgetCreation: true,
      dartDefines: <String>['foo=2', 'bar=2'],
      dartObfuscation: true,
      splitDebugInfoPath: 'foo/',
      extraFrontEndOptions: <String>['--enable-experiment=non-nullable', 'bar'],
      extraGenSnapshotOptions: <String>['--enable-experiment=non-nullable', 'fizz'],
      bundleSkSLPath: 'foo/bar/baz.sksl.json',
172
      packagesPath: 'foo/.dart_tool/package_config.json',
173 174 175
      codeSizeDirectory: 'foo/code-size',
      fileSystemRoots: <String>['test5', 'test6'],
      fileSystemScheme: 'scheme',
176 177
      buildName: '122',
      buildNumber: '22'
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    );

    expect(buildInfo.toBuildSystemEnvironment(), <String, String>{
      'BuildMode': 'debug',
      'DartDefines': 'Zm9vPTI=,YmFyPTI=',
      'DartObfuscation': 'true',
      'ExtraFrontEndOptions': '--enable-experiment=non-nullable,bar',
      'ExtraGenSnapshotOptions': '--enable-experiment=non-nullable,fizz',
      'SplitDebugInfo': 'foo/',
      'TrackWidgetCreation': 'true',
      'TreeShakeIcons': 'true',
      'BundleSkSLPath': 'foo/bar/baz.sksl.json',
      'CodeSizeDirectory': 'foo/code-size',
      'FileSystemRoots': 'test5,test6',
      'FileSystemScheme': 'scheme',
193 194
      'BuildName': '122',
      'BuildNumber': '22',
195 196 197
    });
  });

198
  testWithoutContext('toEnvironmentConfig encoding of standard values', () {
199 200 201 202 203 204 205 206
    const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
      treeShakeIcons: true,
      trackWidgetCreation: true,
      dartDefines: <String>['foo=2', 'bar=2'],
      dartObfuscation: true,
      splitDebugInfoPath: 'foo/',
      extraFrontEndOptions: <String>['--enable-experiment=non-nullable', 'bar'],
      extraGenSnapshotOptions: <String>['--enable-experiment=non-nullable', 'fizz'],
207
      bundleSkSLPath: 'foo/bar/baz.sksl.json',
208
      packagesPath: 'foo/.dart_tool/package_config.json',
209
      codeSizeDirectory: 'foo/code-size',
210 211
      // These values are ignored by toEnvironmentConfig
      androidProjectArgs: <String>['foo=bar', 'fizz=bazz']
212 213 214 215 216
    );

    expect(buildInfo.toEnvironmentConfig(), <String, String>{
      'TREE_SHAKE_ICONS': 'true',
      'TRACK_WIDGET_CREATION': 'true',
217
      'DART_DEFINES': 'Zm9vPTI=,YmFyPTI=',
218 219
      'DART_OBFUSCATION': 'true',
      'SPLIT_DEBUG_INFO': 'foo/',
220 221
      'EXTRA_FRONT_END_OPTIONS': '--enable-experiment=non-nullable,bar',
      'EXTRA_GEN_SNAPSHOT_OPTIONS': '--enable-experiment=non-nullable,fizz',
222
      'BUNDLE_SKSL_PATH': 'foo/bar/baz.sksl.json',
223
      'PACKAGE_CONFIG': 'foo/.dart_tool/package_config.json',
224
      'CODE_SIZE_DIRECTORY': 'foo/code-size',
225 226
    });
  });
227

228 229 230 231 232
  testWithoutContext('toGradleConfig encoding of standard values', () {
    const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
      treeShakeIcons: true,
      trackWidgetCreation: true,
      dartDefines: <String>['foo=2', 'bar=2'],
233
      dartDefineConfigJsonMap: <String, Object>{'baz': '2'},
234 235 236 237 238
      dartObfuscation: true,
      splitDebugInfoPath: 'foo/',
      extraFrontEndOptions: <String>['--enable-experiment=non-nullable', 'bar'],
      extraGenSnapshotOptions: <String>['--enable-experiment=non-nullable', 'fizz'],
      bundleSkSLPath: 'foo/bar/baz.sksl.json',
239
      packagesPath: 'foo/.dart_tool/package_config.json',
240
      codeSizeDirectory: 'foo/code-size',
241
      androidProjectArgs: <String>['foo=bar', 'fizz=bazz']
242 243 244 245 246 247 248 249 250 251 252
    );

    expect(buildInfo.toGradleConfig(), <String>[
      '-Pdart-defines=Zm9vPTI=,YmFyPTI=',
      '-Pdart-obfuscation=true',
      '-Pextra-front-end-options=--enable-experiment=non-nullable,bar',
      '-Pextra-gen-snapshot-options=--enable-experiment=non-nullable,fizz',
      '-Psplit-debug-info=foo/',
      '-Ptrack-widget-creation=true',
      '-Ptree-shake-icons=true',
      '-Pbundle-sksl-path=foo/bar/baz.sksl.json',
253 254
      '-Pcode-size-directory=foo/code-size',
      '-Pfoo=bar',
255
      '-Pfizz=bazz',
256
      '-Pbaz=2',
257 258 259
    ]);
  });

260
  testWithoutContext('encodeDartDefines encodes define values with base64 encoded components', () {
261 262 263 264 265
    expect(encodeDartDefines(<String>['"hello"']), 'ImhlbGxvIg==');
    expect(encodeDartDefines(<String>['https://www.google.com']), 'aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbQ==');
    expect(encodeDartDefines(<String>['2,3,4', '5']), 'MiwzLDQ=,NQ==');
    expect(encodeDartDefines(<String>['true', 'false', 'flase']), 'dHJ1ZQ==,ZmFsc2U=,Zmxhc2U=');
    expect(encodeDartDefines(<String>['1232,456', '2']), 'MTIzMiw0NTY=,Mg==');
266 267
  });

268
  testWithoutContext('decodeDartDefines decodes base64 encoded dart defines', () {
269
    expect(decodeDartDefines(<String, String>{
270
      kDartDefines: 'ImhlbGxvIg==',
271
    }, kDartDefines), <String>['"hello"']);
272
    expect(decodeDartDefines(<String, String>{
273
      kDartDefines: 'aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbQ==',
274
    }, kDartDefines), <String>['https://www.google.com']);
275
    expect(decodeDartDefines(<String, String>{
276
      kDartDefines: 'MiwzLDQ=,NQ==',
277
    }, kDartDefines), <String>['2,3,4', '5']);
278
    expect(decodeDartDefines(<String, String>{
279
      kDartDefines: 'dHJ1ZQ==,ZmFsc2U=,Zmxhc2U=',
280
    }, kDartDefines), <String>['true', 'false', 'flase']);
281
    expect(decodeDartDefines(<String, String>{
282
      kDartDefines: 'MTIzMiw0NTY=,Mg==',
283
    }, kDartDefines), <String>['1232,456', '2']);
284
  });
285 286 287 288 289 290 291

  group('Check repeated buildInfo variables', () {
    testUsingContext('toEnvironmentConfig repeated variable', () async {
      const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
          treeShakeIcons: true,
          trackWidgetCreation: true,
          dartDefines: <String>['foo=2', 'bar=2'],
292
          dartDefineConfigJsonMap: <String, Object>{'DART_DEFINES': 'Define a variable, but it occupies the variable name of the system'},
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
          dartObfuscation: true,
      );
      buildInfo.toEnvironmentConfig();
      expect(testLogger.warningText, contains('The key: [DART_DEFINES] already exists, you cannot use environment variables that have been used by the system'));
    });

    testUsingContext('toEnvironmentConfig repeated variable with DART_DEFINES not set', () async {
      // Simulate operation flutterCommand.getBuildInfo  with `dart-define-from-file` set dartDefines
      const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
          treeShakeIcons: true,
          dartDefines: <String>['DART_DEFINES=Define a variable, but it occupies the variable name of the system'],
          trackWidgetCreation: true,
          dartDefineConfigJsonMap: <String, Object>{ 'DART_DEFINES' : 'Define a variable, but it occupies the variable name of the system'},
          dartObfuscation: true,
      );
      buildInfo.toEnvironmentConfig();
      expect(testLogger.warningText, contains('The key: [DART_DEFINES] already exists, you cannot use environment variables that have been used by the system'));

    });

    testUsingContext('toGradleConfig repeated variable', () async {
      const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
          treeShakeIcons: true,
          trackWidgetCreation: true,
          dartDefines: <String>['foo=2', 'bar=2'],
318
          dartDefineConfigJsonMap: <String, Object>{'dart-defines': 'Define a variable, but it occupies the variable name of the system'},
319 320 321
          dartObfuscation: true,
      );
      buildInfo.toGradleConfig();
322
      expect(testLogger.warningText, contains('The key: [dart-defines] already exists, you cannot use gradle variables that have been used by the system'));
323 324 325 326 327 328 329 330
    });

    testUsingContext('toGradleConfig repeated variable with not set', () async {
      // Simulate operation flutterCommand.getBuildInfo  with `dart-define-from-file` set dartDefines
      const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
          treeShakeIcons: true,
          trackWidgetCreation: true,
          dartDefines: <String>['dart-defines=Define a variable, but it occupies the variable name of the system'],
331
          dartDefineConfigJsonMap: <String, Object>{'dart-defines': 'Define a variable, but it occupies the variable name of the system'},
332 333 334
          dartObfuscation: true,
      );
      buildInfo.toGradleConfig();
335
      expect(testLogger.warningText, contains('The key: [dart-defines] already exists, you cannot use gradle variables that have been used by the system'));
336 337 338 339 340 341 342
    });

    testUsingContext('toGradleConfig with androidProjectArgs override gradle project variant', () async {
      const BuildInfo buildInfo = BuildInfo(BuildMode.debug, '',
          treeShakeIcons: true,
          trackWidgetCreation: true,
          androidProjectArgs: <String>['applicationId=com.google'],
343
          dartDefineConfigJsonMap: <String, Object>{'applicationId': 'override applicationId'},
344 345 346
          dartObfuscation: true,
      );
      buildInfo.toGradleConfig();
347
      expect(testLogger.warningText, contains('The key: [applicationId] already exists, you cannot use gradle variables that have been used by the system'));
348 349 350
    });

  });
351
}