blob: d11e3eeff188a6fdc49baf38680cd3a21bb55a59 [file] [log] [blame]
// 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.
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/analyze_size.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/process.dart';
import '../../src/common.dart';
import '../../src/context.dart';
const FakeCommand unzipCommmand = FakeCommand(
command: <String>[
'unzip',
'-o',
'-v',
'test.apk',
'-d',
'/.tmp_rand0/flutter_tools.rand0'
],
stdout: '''
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
11708 Defl:N 2592 78% 00-00-1980 00:00 07733eef AndroidManifest.xml
1399 Defl:N 1092 22% 00-00-1980 00:00 f53d952a META-INF/CERT.RSA
46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 META-INF/CERT.SF
46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 lib/arm64-v8a/libxyzzyapp.so
46298 Defl:N 14530 69% 00-00-1980 00:00 17df02b8 lib/arm64-v8a/libflutter.so
''',
);
const String aotSizeOutput = '''[
{
"l": "dart:_internal",
"c": "SubListIterable",
"n": "[Optimized] skip",
"s": 2400
},
{
"l": "dart:_internal",
"c": "SubListIterable",
"n": "[Optimized] new SubListIterable.",
"s": 3560
},
{
"l": "dart:core",
"c": "RangeError",
"n": "[Optimized] new RangeError.range",
"s": 3920
},
{
"l": "dart:core",
"c": "ArgumentError",
"n": "[Stub] Allocate ArgumentError",
"s": 4650
}
]
''';
void main() {
MemoryFileSystem fileSystem;
BufferLogger logger;
FakeProcessManager processManager;
setUp(() {
fileSystem = MemoryFileSystem.test();
logger = BufferLogger.test();
processManager = FakeProcessManager.list(<FakeCommand>[unzipCommmand]);
});
test('matchesPattern matches only entire strings', () {
expect(matchesPattern('', pattern: ''), isNotNull);
expect(matchesPattern('', pattern: 'foo'), null);
expect(matchesPattern('foo', pattern: ''), null);
expect(matchesPattern('foo', pattern: 'foo'), isNotNull);
expect(matchesPattern('foo', pattern: 'foobar'), null);
expect(matchesPattern('foobar', pattern: 'foo'), null);
expect(matchesPattern('foobar', pattern: RegExp(r'.*b.*')), isNotNull);
expect(matchesPattern('foobar', pattern: RegExp(r'.*b')), null);
});
test('builds APK analysis correctly', () async {
final SizeAnalyzer sizeAnalyzer = SizeAnalyzer(
fileSystem: fileSystem,
logger: logger,
processUtils: ProcessUtils(
processManager: processManager,
logger: logger,
),
appFilenamePattern: RegExp(r'lib.*app\.so'),
);
final File apk = fileSystem.file('test.apk')..createSync();
final File aotSizeJson = fileSystem.file('test.json')
..createSync()
..writeAsStringSync(aotSizeOutput);
final Map<String, dynamic> result = await sizeAnalyzer.analyzeApkSizeAndAotSnapshot(apk: apk, aotSnapshot: aotSizeJson);
expect(result['type'], contains('apk'));
final Map<String, dynamic> androidManifestMap = result['children'][0] as Map<String, dynamic>;
expect(androidManifestMap['n'], equals('AndroidManifest.xml'));
expect(androidManifestMap['value'], equals(2592));
final Map<String, dynamic> metaInfMap = result['children'][1] as Map<String, dynamic>;
expect(metaInfMap['n'], equals('META-INF'));
expect(metaInfMap['value'], equals(15622));
final Map<String, dynamic> certRsaMap = metaInfMap['children'][0] as Map<String, dynamic>;
expect(certRsaMap['n'], equals('CERT.RSA'));
expect(certRsaMap['value'], equals(1092));
final Map<String, dynamic> certSfMap = metaInfMap['children'][1] as Map<String, dynamic>;
expect(certSfMap['n'], equals('CERT.SF'));
expect(certSfMap['value'], equals(14530));
final Map<String, dynamic> libMap = result['children'][2] as Map<String, dynamic>;
expect(libMap['n'], equals('lib'));
expect(libMap['value'], equals(29060));
final Map<String, dynamic> arm64Map = libMap['children'][0] as Map<String, dynamic>;
expect(arm64Map['n'], equals('arm64-v8a'));
expect(arm64Map['value'], equals(29060));
final Map<String, dynamic> libAppMap = arm64Map['children'][0] as Map<String, dynamic>;
expect(libAppMap['n'], equals('libxyzzyapp.so (Dart AOT)'));
expect(libAppMap['value'], equals(14530));
expect(libAppMap['children'].length, equals(3));
final Map<String, dynamic> internalMap = libAppMap['children'][0] as Map<String, dynamic>;
final Map<String, dynamic> skipMap = internalMap['children'][0] as Map<String, dynamic>;
expect(skipMap['n'], 'skip');
expect(skipMap['value'], 2400);
final Map<String, dynamic> subListIterableMap = internalMap['children'][1] as Map<String, dynamic>;
expect(subListIterableMap['n'], 'new SubListIterable.');
expect(subListIterableMap['value'], 3560);
final Map<String, dynamic> coreMap = libAppMap['children'][1] as Map<String, dynamic>;
final Map<String, dynamic> rangeErrorMap = coreMap['children'][0] as Map<String, dynamic>;
expect(rangeErrorMap['n'], 'new RangeError.range');
expect(rangeErrorMap['value'], 3920);
final Map<String, dynamic> stubsMap = libAppMap['children'][2] as Map<String, dynamic>;
final Map<String, dynamic> allocateMap = stubsMap['children'][0] as Map<String, dynamic>;
expect(allocateMap['n'], 'Allocate ArgumentError');
expect(allocateMap['value'], 4650);
final Map<String, dynamic> libFlutterMap = arm64Map['children'][1] as Map<String, dynamic>;
expect(libFlutterMap['n'], equals('libflutter.so (Flutter Engine)'));
expect(libFlutterMap['value'], equals(14530));
});
test('outputs summary to command line correctly', () async {
final SizeAnalyzer sizeAnalyzer = SizeAnalyzer(
fileSystem: fileSystem,
logger: logger,
processUtils: ProcessUtils(
processManager: processManager,
logger: logger,
),
appFilenamePattern: RegExp(r'lib.*app\.so'),
);
final File apk = fileSystem.file('test.apk')..createSync();
final File aotSizeJson = fileSystem.file('test.json')
..createSync()
..writeAsStringSync(aotSizeOutput);
await sizeAnalyzer.analyzeApkSizeAndAotSnapshot(apk: apk, aotSnapshot: aotSizeJson);
final List<String> stdout = logger.statusText.split('\n');
expect(
stdout,
containsAll(<String>[
' AndroidManifest.xml 3 KB',
' META-INF 15 KB',
' lib 28 KB',
' lib/arm64-v8a/libxyzzyapp.so (Dart AOT) 14 KB',
' Dart AOT symbols accounted decompressed size 14 KB',
' dart:_internal/SubListIterable 6 KB',
' @stubs/allocation-stubs/dart:core/ArgumentError 5 KB',
' dart:core/RangeError 4 KB',
' lib/arm64-v8a/libflutter.so (Flutter Engine) 14 KB',
]),
);
});
}