blob: 5c5f314dceebc1fc7a387ff39d1401599f4ad827 [file] [log] [blame]
// Copyright 2013 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 'dart:convert';
import 'dart:io' as io;
import 'package:engine_repo_tools/engine_repo_tools.dart';
import 'package:kernel/const_finder.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
void main() {
final engine = Engine.findWithin();
var buildDir = io.Platform.environment['FLUTTER_BUILD_DIRECTORY'];
buildDir ??= engine.latestOutput()?.path.path;
if (buildDir == null) {
fail('No build directory found. Set FLUTTER_BUILD_DIRECTORY');
}
final fixturesPath = path.join(
engine.flutterDir.path,
'tools',
'const_finder',
'test',
'fixtures',
);
final String fixturesUrl = io.Platform.isWindows
? '/$fixturesPath'.replaceAll(io.Platform.pathSeparator, '/')
: fixturesPath;
final frontendServerSnapshot = path.join(
buildDir,
'gen',
'frontend_server_aot.dart.snapshot',
);
final flutterPatchedSdk = path.join(
buildDir,
'flutter_patched_sdk',
);
final librariesDotJson = path.join(
flutterPatchedSdk,
'lib',
'libraries.json',
);
final String packageConfig = path.join(
fixturesPath,
'.dart_tool',
'package_config.json',
);
final dart = io.Platform.resolvedExecutable;
final dartaotruntime = path.join(
path.dirname(io.Platform.resolvedExecutable),
'dartaotruntime',
);
void compileAOTDill({
required String sourcePath,
required String dillPath,
}) {
final result = io.Process.runSync(
dartaotruntime,
[
frontendServerSnapshot,
'--sdk-root=$flutterPatchedSdk',
'--target=flutter',
'--aot',
'--tfa',
'--packages=$packageConfig',
'--output-dill=$dillPath',
sourcePath,
],
);
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
if (result.exitCode != 0) {
fail('Failed to compile AOT dill');
}
addTearDown(() => io.File(dillPath).deleteSync());
}
void compileDart2JSDill({
required String sourcePath,
required String dillPath,
}) {
final result = io.Process.runSync(
dart,
[
'compile',
'js',
'--libraries-spec=$librariesDotJson',
'-Ddart.vm.product=true',
'-o',
dillPath,
'--packages=$packageConfig',
'--cfe-only',
sourcePath,
],
);
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
if (result.exitCode != 0) {
fail('Failed to compile Dart2JS dill');
}
addTearDown(() => io.File(dillPath).deleteSync());
}
test('box_frontend (aot)', () {
final sourcePath = path.join(fixturesPath, 'lib', 'box.dart');
final dillPath = path.join(fixturesPath, 'box_frontend.dill');
compileAOTDill(sourcePath: sourcePath, dillPath: dillPath);
final finder = ConstFinder(
kernelFilePath: dillPath,
classLibraryUri: 'package:const_finder_fixtures/box.dart',
className: 'Box',
);
// Will timeout if we did things wrong.
jsonEncode(finder.findInstances());
});
test('box_web (dart2js)', () {
final sourcePath = path.join(fixturesPath, 'lib', 'box.dart');
final dillPath = path.join(fixturesPath, 'box_web.dill');
compileDart2JSDill(sourcePath: sourcePath, dillPath: dillPath);
final finder = ConstFinder(
kernelFilePath: dillPath,
classLibraryUri: 'package:const_finder_fixtures/box.dart',
className: 'Box',
);
// Will timeout if we did things wrong.
jsonEncode(finder.findInstances());
});
test('consts_frontend (aot)', () {
final sourcePath = path.join(fixturesPath, 'lib', 'consts.dart');
final dillPath = path.join(fixturesPath, 'consts_frontend.dill');
compileAOTDill(sourcePath: sourcePath, dillPath: dillPath);
final {
'constantInstances': List<Object?> constantInstances,
'nonConstantLocations': List<Object?> nonConstantLocations,
} = ConstFinder(
kernelFilePath: dillPath,
classLibraryUri: 'package:const_finder_fixtures/target.dart',
className: 'Target',
).findInstances();
expect(
constantInstances,
unorderedEquals([
{'stringValue': '100', 'intValue': 100, 'targetValue': null},
{'stringValue': '102', 'intValue': 102, 'targetValue': null},
{'stringValue': '101', 'intValue': 101},
{'stringValue': '103', 'intValue': 103, 'targetValue': null},
{'stringValue': '105', 'intValue': 105, 'targetValue': null},
{'stringValue': '104', 'intValue': 104},
{'stringValue': '106', 'intValue': 106, 'targetValue': null},
{'stringValue': '108', 'intValue': 108, 'targetValue': null},
{'stringValue': '107', 'intValue': 107},
{'stringValue': '1', 'intValue': 1, 'targetValue': null},
{'stringValue': '4', 'intValue': 4, 'targetValue': null},
{'stringValue': '2', 'intValue': 2},
{'stringValue': '6', 'intValue': 6, 'targetValue': null},
{'stringValue': '8', 'intValue': 8, 'targetValue': null},
{'stringValue': '10', 'intValue': 10, 'targetValue': null},
{'stringValue': '9', 'intValue': 9},
{'stringValue': '7', 'intValue': 7, 'targetValue': null},
{'stringValue': '11', 'intValue': 11, 'targetValue': null},
{'stringValue': '12', 'intValue': 12, 'targetValue': null},
{'stringValue': 'package', 'intValue': -1, 'targetValue': null},
]),
);
expect(nonConstantLocations, isEmpty);
});
test('consts_web (dart2js)', () {
final sourcePath = path.join(fixturesPath, 'lib', 'consts.dart');
final dillPath = path.join(fixturesPath, 'consts_web.dill');
compileDart2JSDill(sourcePath: sourcePath, dillPath: dillPath);
final {
'constantInstances': List<Object?> constantInstances,
'nonConstantLocations': List<Object?> nonConstantLocations,
} = ConstFinder(
kernelFilePath: dillPath,
classLibraryUri: 'package:const_finder_fixtures/target.dart',
className: 'Target',
).findInstances();
expect(
constantInstances,
unorderedEquals([
{'stringValue': '100', 'intValue': 100, 'targetValue': null},
{'stringValue': '102', 'intValue': 102, 'targetValue': null},
{'stringValue': '101', 'intValue': 101},
{'stringValue': '103', 'intValue': 103, 'targetValue': null},
{'stringValue': '105', 'intValue': 105, 'targetValue': null},
{'stringValue': '104', 'intValue': 104},
{'stringValue': '106', 'intValue': 106, 'targetValue': null},
{'stringValue': '108', 'intValue': 108, 'targetValue': null},
{'stringValue': '107', 'intValue': 107},
{'stringValue': '1', 'intValue': 1, 'targetValue': null},
{'stringValue': '4', 'intValue': 4, 'targetValue': null},
{'stringValue': '2', 'intValue': 2},
{'stringValue': '6', 'intValue': 6, 'targetValue': null},
{'stringValue': '8', 'intValue': 8, 'targetValue': null},
{'stringValue': '10', 'intValue': 10, 'targetValue': null},
{'stringValue': '9', 'intValue': 9},
{'stringValue': '7', 'intValue': 7, 'targetValue': null},
{'stringValue': '11', 'intValue': 11, 'targetValue': null},
{'stringValue': '12', 'intValue': 12, 'targetValue': null},
{'stringValue': 'package', 'intValue': -1, 'targetValue': null},
]),
);
expect(nonConstantLocations, [
{
'file': 'file://$fixturesUrl/pkg/package.dart',
'line': 14,
'column': 25,
}
]);
});
test('consts_and_non_frontend (aot)', () {
final sourcePath = path.join(fixturesPath, 'lib', 'consts_and_non.dart');
final dillPath = path.join(fixturesPath, 'consts_and_non_frontend.dill');
compileAOTDill(sourcePath: sourcePath, dillPath: dillPath);
final {
'constantInstances': List<Object?> constantInstances,
'nonConstantLocations': List<Object?> nonConstantLocations,
} = ConstFinder(
kernelFilePath: dillPath,
classLibraryUri: 'package:const_finder_fixtures/target.dart',
className: 'Target',
).findInstances();
expect(
constantInstances,
unorderedEquals([
{'stringValue': '1', 'intValue': 1, 'targetValue': null},
{'stringValue': '4', 'intValue': 4, 'targetValue': null},
{'stringValue': '6', 'intValue': 6, 'targetValue': null},
{'stringValue': '8', 'intValue': 8, 'targetValue': null},
{'stringValue': '10', 'intValue': 10, 'targetValue': null},
{'stringValue': '9', 'intValue': 9},
{'stringValue': '7', 'intValue': 7, 'targetValue': null},
]),
);
expect(nonConstantLocations, [
{
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
'line': 14,
'column': 26,
},
{
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
'line': 16,
'column': 26,
},
{
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
'line': 16,
'column': 41,
},
{
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
'line': 17,
'column': 26,
},
{
'file': 'file://$fixturesUrl/pkg/package.dart',
'line': 14,
'column': 25,
}
]);
});
test('consts_and_non_web (dart2js)', () {
final sourcePath = path.join(fixturesPath, 'lib', 'consts_and_non.dart');
final dillPath = path.join(fixturesPath, 'consts_and_non_web.dill');
compileDart2JSDill(sourcePath: sourcePath, dillPath: dillPath);
final {
'constantInstances': List<Object?> constantInstances,
'nonConstantLocations': List<Object?> nonConstantLocations,
} = ConstFinder(
kernelFilePath: dillPath,
classLibraryUri: 'package:const_finder_fixtures/target.dart',
className: 'Target',
).findInstances();
expect(
constantInstances,
unorderedEquals([
{'stringValue': '1', 'intValue': 1, 'targetValue': null},
{'stringValue': '4', 'intValue': 4, 'targetValue': null},
{'stringValue': '6', 'intValue': 6, 'targetValue': null},
{'stringValue': '8', 'intValue': 8, 'targetValue': null},
{'stringValue': '10', 'intValue': 10, 'targetValue': null},
{'stringValue': '9', 'intValue': 9},
{'stringValue': '7', 'intValue': 7, 'targetValue': null},
{'stringValue': 'package', 'intValue': -1, 'targetValue': null},
]),
);
expect(nonConstantLocations, [
{
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
'line': 14,
'column': 26,
},
{
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
'line': 16,
'column': 26,
},
{
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
'line': 16,
'column': 41,
},
{
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
'line': 17,
'column': 26,
},
{
'file': 'file://$fixturesUrl/pkg/package.dart',
'line': 14,
'column': 25,
}
]);
});
test('static_icon_provider_frontend (aot)', () {
final sourcePath = path.join(
fixturesPath,
'lib',
'static_icon_provider.dart',
);
final dillPath = path.join(
fixturesPath,
'static_icon_provider_frontend.dill',
);
compileAOTDill(sourcePath: sourcePath, dillPath: dillPath);
final finder = ConstFinder(
kernelFilePath: dillPath,
classLibraryUri: 'package:const_finder_fixtures/target.dart',
className: 'Target',
annotationClassName: 'StaticIconProvider',
annotationClassLibraryUri:
'package:const_finder_fixtures/static_icon_provider.dart',
);
final {
'constantInstances': List<Object?> constantInstances,
'nonConstantLocations': List<Object?> nonConstantLocations,
} = finder.findInstances();
expect(
constantInstances,
unorderedEquals([
{
'stringValue': 'used1',
'intValue': 1,
'targetValue': null,
},
{
'stringValue': 'used2',
'intValue': 2,
'targetValue': null,
},
]),
);
// TODO(fujino): This should have non-constant locations from the use of
// a tear-off, see https://github.com/flutter/flutter/issues/116797
expect(nonConstantLocations, isEmpty);
});
test('static_icon_provider_web (dart2js)', () {
final sourcePath = path.join(
fixturesPath,
'lib',
'static_icon_provider.dart',
);
final dillPath = path.join(
fixturesPath,
'static_icon_provider_web.dill',
);
compileDart2JSDill(sourcePath: sourcePath, dillPath: dillPath);
final finder = ConstFinder(
kernelFilePath: dillPath,
classLibraryUri: 'package:const_finder_fixtures/target.dart',
className: 'Target',
annotationClassName: 'StaticIconProvider',
annotationClassLibraryUri:
'package:const_finder_fixtures/static_icon_provider.dart',
);
final {
'constantInstances': List<Object?> constantInstances,
'nonConstantLocations': List<Object?> nonConstantLocations,
} = finder.findInstances();
expect(
constantInstances,
unorderedEquals([
{
'stringValue': 'used1',
'intValue': 1,
'targetValue': null,
},
{
'stringValue': 'used2',
'intValue': 2,
'targetValue': null,
},
]),
);
// TODO(fujino): This should have non-constant locations from the use of
// a tear-off, see https://github.com/flutter/flutter/issues/116797
expect(nonConstantLocations, isEmpty);
});
}