mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
Hello services run (#4969)
* making flutter run work with gradle * locate android studio * add test for settings * review comments
This commit is contained in:
parent
932059b901
commit
57b76a050f
|
@ -4,7 +4,7 @@
|
|||
android:versionCode="1"
|
||||
android:versionName="1.0.0" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.flutter.examples.HelloWorld" android:versionCode="1" android:versionName="0.0.1">
|
||||
|
||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application android:label="Flutter Hello" android:name="org.domokit.sky.shell.SkyApplication">
|
||||
|
|
188
packages/flutter_tools/lib/src/android/gradle.dart
Normal file
188
packages/flutter_tools/lib/src/android/gradle.dart
Normal file
|
@ -0,0 +1,188 @@
|
|||
// Copyright 2016 The Chromium 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:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../base/logger.dart';
|
||||
import '../base/os.dart';
|
||||
import '../base/process.dart';
|
||||
import '../base/utils.dart';
|
||||
import '../build_info.dart';
|
||||
import '../cache.dart';
|
||||
import '../globals.dart';
|
||||
import 'android_sdk.dart';
|
||||
|
||||
const String gradleManifestPath = 'android/app/src/main/AndroidManifest.xml';
|
||||
const String gradleAppOut = 'android/app/build/outputs/apk/app-debug.apk';
|
||||
|
||||
bool isProjectUsingGradle() {
|
||||
return FileSystemEntity.isFileSync('android/build.gradle');
|
||||
}
|
||||
|
||||
String locateSystemGradle({ bool ensureExecutable: true }) {
|
||||
String gradle = _locateSystemGradle();
|
||||
if (ensureExecutable && gradle != null) {
|
||||
File file = new File(gradle);
|
||||
if (file.existsSync())
|
||||
os.makeExecutable(file);
|
||||
}
|
||||
return gradle;
|
||||
}
|
||||
|
||||
String _locateSystemGradle() {
|
||||
// See if the user has explicitly configured gradle-dir.
|
||||
String gradleDir = config.getValue('gradle-dir');
|
||||
if (gradleDir != null) {
|
||||
if (FileSystemEntity.isFileSync(gradleDir))
|
||||
return gradleDir;
|
||||
return path.join(gradleDir, 'bin', 'gradle');
|
||||
}
|
||||
|
||||
// Look relative to Android Studio.
|
||||
String studioPath = config.getValue('android-studio-dir');
|
||||
|
||||
if (studioPath == null && os.isMacOS) {
|
||||
final String kDefaultMacPath = '/Applications/Android Studio.app';
|
||||
if (FileSystemEntity.isDirectorySync(kDefaultMacPath))
|
||||
studioPath = kDefaultMacPath;
|
||||
}
|
||||
|
||||
if (studioPath != null) {
|
||||
// '/Applications/Android Studio.app/Contents/gradle/gradle-2.10/bin/gradle'
|
||||
if (os.isMacOS && !studioPath.endsWith('Contents'))
|
||||
studioPath = path.join(studioPath, 'Contents');
|
||||
|
||||
Directory dir = new Directory(path.join(studioPath, 'gradle'));
|
||||
if (dir.existsSync()) {
|
||||
// We find the first valid gradle directory.
|
||||
for (FileSystemEntity entity in dir.listSync()) {
|
||||
if (entity is Directory && path.basename(entity.path).startsWith('gradle-')) {
|
||||
String executable = path.join(entity.path, 'bin', 'gradle');
|
||||
if (FileSystemEntity.isFileSync(executable))
|
||||
return executable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use 'which'.
|
||||
File file = os.which('gradle');
|
||||
if (file != null)
|
||||
return file.path;
|
||||
|
||||
// We couldn't locate gradle.
|
||||
return null;
|
||||
}
|
||||
|
||||
String locateProjectGradlew({ bool ensureExecutable: true }) {
|
||||
final String path = 'android/gradlew';
|
||||
|
||||
if (FileSystemEntity.isFileSync(path)) {
|
||||
if (ensureExecutable)
|
||||
os.makeExecutable(new File(path));
|
||||
return path;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> buildGradleProject(BuildMode buildMode) async {
|
||||
// Create android/local.properties.
|
||||
File localProperties = new File('android/local.properties');
|
||||
if (!localProperties.existsSync()) {
|
||||
localProperties.writeAsStringSync(
|
||||
'sdk.dir=${androidSdk.directory}\n'
|
||||
'flutter.sdk=${Cache.flutterRoot}\n'
|
||||
);
|
||||
}
|
||||
|
||||
// Update the local.settings file with the build mode.
|
||||
// TODO(devoncarew): It would be nicer if we could pass this information in via a cli flag.
|
||||
SettingsFile settings = new SettingsFile.parseFromFile(localProperties);
|
||||
settings.values['flutter.buildMode'] = getModeName(buildMode);
|
||||
settings.writeContents(localProperties);
|
||||
|
||||
String gradlew = locateProjectGradlew();
|
||||
|
||||
if (gradlew == null) {
|
||||
String gradle = locateSystemGradle();
|
||||
if (gradle == null) {
|
||||
printError(
|
||||
'Unable to locate gradle. Please configure the path to gradle using \'flutter config --gradle\'.'
|
||||
);
|
||||
return 1;
|
||||
} else {
|
||||
printTrace('Using gradle from $gradle.');
|
||||
}
|
||||
|
||||
// Stamp the android/app/build.gradle file with the current android sdk and build tools version.
|
||||
File appGradleFile = new File('android/app/build.gradle');
|
||||
if (appGradleFile.existsSync()) {
|
||||
_GradleFile gradleFile = new _GradleFile.parse(appGradleFile);
|
||||
AndroidSdkVersion sdkVersion = androidSdk.latestVersion;
|
||||
gradleFile.replace('compileSdkVersion', "${sdkVersion.sdkLevel}");
|
||||
gradleFile.replace('buildToolsVersion', "'${sdkVersion.buildToolsVersionName}'");
|
||||
gradleFile.writeContents(appGradleFile);
|
||||
}
|
||||
|
||||
// Run 'gradle wrapper'.
|
||||
Status status = logger.startProgress('Running \'gradle wrapper\'...');
|
||||
int exitcode = await runCommandAndStreamOutput(
|
||||
<String>[gradle, 'wrapper'],
|
||||
workingDirectory: 'android',
|
||||
allowReentrantFlutter: true
|
||||
);
|
||||
status.stop(showElapsedTime: true);
|
||||
if (exitcode != 0)
|
||||
return exitcode;
|
||||
|
||||
gradlew = locateProjectGradlew();
|
||||
if (gradlew == null) {
|
||||
printError('Unable to build android/gradlew.');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Run 'gradlew build'.
|
||||
Status status = logger.startProgress('Running \'gradlew build\'...');
|
||||
int exitcode = await runCommandAndStreamOutput(
|
||||
<String>[new File('android/gradlew').absolute.path, 'build'],
|
||||
workingDirectory: 'android',
|
||||
allowReentrantFlutter: true
|
||||
);
|
||||
status.stop(showElapsedTime: true);
|
||||
|
||||
if (exitcode == 0) {
|
||||
File apkFile = new File(gradleAppOut);
|
||||
printStatus('Built $gradleAppOut (${getSizeAsMB(apkFile.lengthSync())}).');
|
||||
}
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
class _GradleFile {
|
||||
_GradleFile.parse(File file) {
|
||||
contents = file.readAsStringSync();
|
||||
}
|
||||
|
||||
String contents;
|
||||
|
||||
void replace(String key, String newValue) {
|
||||
// Replace 'ws key ws value' with the new value.
|
||||
final RegExp regex = new RegExp('\\s+$key\\s+(\\S+)', multiLine: true);
|
||||
Match match = regex.firstMatch(contents);
|
||||
if (match != null) {
|
||||
String oldValue = match.group(1);
|
||||
int offset = match.end - oldValue.length;
|
||||
contents = contents.substring(0, offset) + newValue + contents.substring(match.end);
|
||||
}
|
||||
}
|
||||
|
||||
void writeContents(File file) {
|
||||
file.writeAsStringSync(contents);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import 'dart:io';
|
|||
import 'package:path/path.dart' as path;
|
||||
import 'package:xml/xml.dart' as xml;
|
||||
|
||||
import 'android/gradle.dart';
|
||||
import 'build_info.dart';
|
||||
import 'ios/plist_utils.dart';
|
||||
|
||||
|
@ -49,9 +50,20 @@ class AndroidApk extends ApplicationPackage {
|
|||
|
||||
/// Creates a new AndroidApk based on the information in the Android manifest.
|
||||
factory AndroidApk.fromCurrentDirectory() {
|
||||
String manifestPath = path.join('android', 'AndroidManifest.xml');
|
||||
String manifestPath;
|
||||
String apkPath;
|
||||
|
||||
if (isProjectUsingGradle()) {
|
||||
manifestPath = gradleManifestPath;
|
||||
apkPath = gradleAppOut;
|
||||
} else {
|
||||
manifestPath = path.join('android', 'AndroidManifest.xml');
|
||||
apkPath = path.join('build', 'app.apk');
|
||||
}
|
||||
|
||||
if (!FileSystemEntity.isFileSync(manifestPath))
|
||||
return null;
|
||||
|
||||
String manifestString = new File(manifestPath).readAsStringSync();
|
||||
xml.XmlDocument document = xml.parse(manifestString);
|
||||
|
||||
|
@ -75,7 +87,7 @@ class AndroidApk extends ApplicationPackage {
|
|||
return new AndroidApk(
|
||||
buildDir: 'build',
|
||||
id: id,
|
||||
apkPath: path.join('build', 'app.apk'),
|
||||
apkPath: apkPath,
|
||||
launchActivity: launchActivity
|
||||
);
|
||||
}
|
||||
|
|
49
packages/flutter_tools/lib/src/base/config.dart
Normal file
49
packages/flutter_tools/lib/src/base/config.dart
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2016 The Chromium 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';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'context.dart';
|
||||
|
||||
class Config {
|
||||
Config([File configFile]) {
|
||||
_configFile = configFile ?? new File(path.join(_userHomeDir(), '.flutter_settings'));
|
||||
if (_configFile.existsSync())
|
||||
_values = JSON.decode(_configFile.readAsStringSync());
|
||||
}
|
||||
|
||||
static Config get instance => context[Config] ?? (context[Config] = new Config());
|
||||
|
||||
File _configFile;
|
||||
Map<String, dynamic> _values = <String, dynamic>{};
|
||||
|
||||
Iterable<String> get keys => _values.keys;
|
||||
|
||||
dynamic getValue(String key) => _values[key];
|
||||
|
||||
void setValue(String key, String value) {
|
||||
_values[key] = value;
|
||||
_flushValues();
|
||||
}
|
||||
|
||||
void removeValue(String key) {
|
||||
_values.remove(key);
|
||||
_flushValues();
|
||||
}
|
||||
|
||||
void _flushValues() {
|
||||
String json = new JsonEncoder.withIndent(' ').convert(_values);
|
||||
json = '$json\n';
|
||||
_configFile.writeAsStringSync(json);
|
||||
}
|
||||
}
|
||||
|
||||
String _userHomeDir() {
|
||||
String envKey = Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
|
||||
String value = Platform.environment[envKey];
|
||||
return value == null ? '.' : value;
|
||||
}
|
|
@ -127,3 +127,28 @@ class ItemListNotifier<T> {
|
|||
_removedController.close();
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsFile {
|
||||
SettingsFile.parse(String contents) {
|
||||
for (String line in contents.split('\n')) {
|
||||
line = line.trim();
|
||||
if (line.startsWith('#') || line.isEmpty)
|
||||
continue;
|
||||
int index = line.indexOf('=');
|
||||
if (index != -1)
|
||||
values[line.substring(0, index)] = line.substring(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
factory SettingsFile.parseFromFile(File file) {
|
||||
return new SettingsFile.parse(file.readAsStringSync());
|
||||
}
|
||||
|
||||
final Map<String, String> values = <String, String>{};
|
||||
|
||||
void writeContents(File file) {
|
||||
file.writeAsStringSync(values.keys.map((String key) {
|
||||
return '$key=${values[key]}';
|
||||
}).join('\n'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'dart:io';
|
|||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../android/android_sdk.dart';
|
||||
import '../android/gradle.dart';
|
||||
import '../base/file_system.dart' show ensureDirectoryExists;
|
||||
import '../base/logger.dart';
|
||||
import '../base/os.dart';
|
||||
|
@ -202,25 +203,32 @@ class BuildApkCommand extends FlutterCommand {
|
|||
|
||||
@override
|
||||
Future<int> runInProject() async {
|
||||
// TODO(devoncarew): This command should take an arg for the output type (arm / x64).
|
||||
|
||||
return await buildAndroid(
|
||||
TargetPlatform.android_arm,
|
||||
getBuildMode(),
|
||||
force: true,
|
||||
manifest: argResults['manifest'],
|
||||
resources: argResults['resources'],
|
||||
outputFile: argResults['output-file'],
|
||||
target: argResults['target'],
|
||||
flxPath: argResults['flx'],
|
||||
aotPath: argResults['aot-path'],
|
||||
keystore: (argResults['keystore'] ?? '').isEmpty ? null : new ApkKeystoreInfo(
|
||||
keystore: argResults['keystore'],
|
||||
password: argResults['keystore-password'],
|
||||
keyAlias: argResults['keystore-key-alias'],
|
||||
keyPassword: argResults['keystore-key-password']
|
||||
)
|
||||
);
|
||||
if (isProjectUsingGradle()) {
|
||||
return await buildAndroidWithGradle(
|
||||
TargetPlatform.android_arm,
|
||||
getBuildMode(),
|
||||
target: argResults['target']
|
||||
);
|
||||
} else {
|
||||
// TODO(devoncarew): This command should take an arg for the output type (arm / x64).
|
||||
return await buildAndroid(
|
||||
TargetPlatform.android_arm,
|
||||
getBuildMode(),
|
||||
force: true,
|
||||
manifest: argResults['manifest'],
|
||||
resources: argResults['resources'],
|
||||
outputFile: argResults['output-file'],
|
||||
target: argResults['target'],
|
||||
flxPath: argResults['flx'],
|
||||
aotPath: argResults['aot-path'],
|
||||
keystore: (argResults['keystore'] ?? '').isEmpty ? null : new ApkKeystoreInfo(
|
||||
keystore: argResults['keystore'],
|
||||
password: argResults['keystore-password'],
|
||||
keyAlias: argResults['keystore-key-alias'],
|
||||
keyPassword: argResults['keystore-key-password']
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,24 +564,53 @@ Future<int> buildAndroid(
|
|||
return result;
|
||||
}
|
||||
|
||||
Future<int> buildAndroidWithGradle(
|
||||
TargetPlatform platform,
|
||||
BuildMode buildMode, {
|
||||
bool force: false,
|
||||
String target
|
||||
}) async {
|
||||
// Validate that we can find an android sdk.
|
||||
if (androidSdk == null) {
|
||||
printError('No Android SDK found. Try setting the ANDROID_HOME environment variable.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
List<String> validationResult = androidSdk.validateSdkWellFormed();
|
||||
if (validationResult.isNotEmpty) {
|
||||
validationResult.forEach(printError);
|
||||
printError('Try re-installing or updating your Android SDK.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
return buildGradleProject(buildMode);
|
||||
}
|
||||
|
||||
Future<int> buildApk(
|
||||
TargetPlatform platform, {
|
||||
String target,
|
||||
BuildMode buildMode: BuildMode.debug
|
||||
}) async {
|
||||
if (!FileSystemEntity.isFileSync(_kDefaultAndroidManifestPath)) {
|
||||
printError('Cannot build APK: missing $_kDefaultAndroidManifestPath.');
|
||||
return 1;
|
||||
if (isProjectUsingGradle()) {
|
||||
return await buildAndroidWithGradle(
|
||||
platform,
|
||||
buildMode,
|
||||
force: false,
|
||||
target: target
|
||||
);
|
||||
} else {
|
||||
if (!FileSystemEntity.isFileSync(_kDefaultAndroidManifestPath)) {
|
||||
printError('Cannot build APK: missing $_kDefaultAndroidManifestPath.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
return await buildAndroid(
|
||||
platform,
|
||||
buildMode,
|
||||
force: false,
|
||||
target: target
|
||||
);
|
||||
}
|
||||
|
||||
int result = await buildAndroid(
|
||||
platform,
|
||||
buildMode,
|
||||
force: false,
|
||||
target: target
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _readBuildMeta(String buildDirectoryPath) {
|
||||
|
|
|
@ -12,6 +12,8 @@ class ConfigCommand extends FlutterCommand {
|
|||
argParser.addFlag('analytics',
|
||||
negatable: true,
|
||||
help: 'Enable or disable reporting anonymously tool usage statistics and crash reports.');
|
||||
argParser.addOption('gradle-dir', help: 'The gradle install directory.');
|
||||
argParser.addOption('android-studio-dir', help: 'The Android Studio install directory.');
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -27,7 +29,17 @@ class ConfigCommand extends FlutterCommand {
|
|||
final List<String> aliases = <String>['configure'];
|
||||
|
||||
@override
|
||||
String get usageFooter => 'Analytics reporting is currently ${flutterUsage.enabled ? 'enabled' : 'disabled'}.';
|
||||
String get usageFooter {
|
||||
// List all config settings.
|
||||
String values = config.keys.map((String key) {
|
||||
return ' $key: ${config.getValue(key)}';
|
||||
}).join('\n');
|
||||
if (values.isNotEmpty)
|
||||
values = '\nSettings:\n$values\n\n';
|
||||
return
|
||||
'$values'
|
||||
'Analytics reporting is currently ${flutterUsage.enabled ? 'enabled' : 'disabled'}.';
|
||||
}
|
||||
|
||||
@override
|
||||
bool get requiresProjectRoot => false;
|
||||
|
@ -42,10 +54,27 @@ class ConfigCommand extends FlutterCommand {
|
|||
bool value = argResults['analytics'];
|
||||
flutterUsage.enabled = value;
|
||||
printStatus('Analytics reporting ${value ? 'enabled' : 'disabled'}.');
|
||||
} else {
|
||||
printStatus(usage);
|
||||
}
|
||||
|
||||
if (argResults.wasParsed('gradle-dir'))
|
||||
_updateConfig('gradle-dir', argResults['gradle-dir']);
|
||||
|
||||
if (argResults.wasParsed('android-studio-dir'))
|
||||
_updateConfig('android-studio-dir', argResults['android-studio-dir']);
|
||||
|
||||
if (argResults.arguments.isEmpty)
|
||||
printStatus(usage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _updateConfig(String keyName, String keyValue) {
|
||||
if (keyValue.isEmpty) {
|
||||
config.removeValue(keyName);
|
||||
printStatus('Removing "$keyName" value.');
|
||||
} else {
|
||||
config.setValue(keyName, keyValue);
|
||||
printStatus('Setting "$keyName" value to "$keyValue".');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
import 'android/android_sdk.dart';
|
||||
import 'base/config.dart';
|
||||
import 'base/context.dart';
|
||||
import 'base/logger.dart';
|
||||
import 'cache.dart';
|
||||
|
@ -15,6 +16,7 @@ DeviceManager get deviceManager => context[DeviceManager];
|
|||
Logger get logger => context[Logger];
|
||||
AndroidSdk get androidSdk => context[AndroidSdk];
|
||||
Cache get cache => Cache.instance;
|
||||
Config get config => Config.instance;
|
||||
Doctor get doctor => context[Doctor];
|
||||
ToolConfiguration get tools => ToolConfiguration.instance;
|
||||
Usage get flutterUsage => Usage.instance;
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'analyze_test.dart' as analyze_test;
|
|||
import 'android_device_test.dart' as android_device_test;
|
||||
import 'android_sdk_test.dart' as android_sdk_test;
|
||||
import 'base_utils_test.dart' as base_utils_test;
|
||||
import 'config_test.dart' as config_test;
|
||||
import 'context_test.dart' as context_test;
|
||||
import 'create_test.dart' as create_test;
|
||||
import 'daemon_test.dart' as daemon_test;
|
||||
|
@ -33,6 +34,7 @@ import 'test_test.dart' as test_test;
|
|||
import 'toolchain_test.dart' as toolchain_test;
|
||||
import 'trace_test.dart' as trace_test;
|
||||
import 'upgrade_test.dart' as upgrade_test;
|
||||
import 'utils_test.dart' as utils_test;
|
||||
|
||||
void main() {
|
||||
Cache.disableLocking();
|
||||
|
@ -43,6 +45,7 @@ void main() {
|
|||
android_device_test.main();
|
||||
android_sdk_test.main();
|
||||
base_utils_test.main();
|
||||
config_test.main();
|
||||
context_test.main();
|
||||
create_test.main();
|
||||
daemon_test.main();
|
||||
|
@ -60,4 +63,5 @@ void main() {
|
|||
toolchain_test.main();
|
||||
trace_test.main();
|
||||
upgrade_test.main();
|
||||
utils_test.main();
|
||||
}
|
||||
|
|
38
packages/flutter_tools/test/config_test.dart
Normal file
38
packages/flutter_tools/test/config_test.dart
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2016 The Chromium 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:io';
|
||||
|
||||
import 'package:flutter_tools/src/base/config.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
Config config;
|
||||
|
||||
setUp(() {
|
||||
Directory tempDiretory = Directory.systemTemp.createTempSync('flutter_test');
|
||||
File file = new File(path.join(tempDiretory.path, '.settings'));
|
||||
config = new Config(file);
|
||||
});
|
||||
|
||||
group('config', () {
|
||||
test('get set value', () async {
|
||||
expect(config.getValue('foo'), null);
|
||||
config.setValue('foo', 'bar');
|
||||
expect(config.getValue('foo'), 'bar');
|
||||
expect(config.keys, contains('foo'));
|
||||
});
|
||||
|
||||
test('removeValue', () async {
|
||||
expect(config.getValue('foo'), null);
|
||||
config.setValue('foo', 'bar');
|
||||
expect(config.getValue('foo'), 'bar');
|
||||
expect(config.keys, contains('foo'));
|
||||
config.removeValue('foo');
|
||||
expect(config.getValue('foo'), null);
|
||||
expect(config.keys, isNot(contains('foo')));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
|
21
packages/flutter_tools/test/utils_test.dart
Normal file
21
packages/flutter_tools/test/utils_test.dart
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2016 The Chromium 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:flutter_tools/src/base/utils.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('SettingsFile', () {
|
||||
test('parse', () {
|
||||
SettingsFile file = new SettingsFile.parse('''
|
||||
# ignore comment
|
||||
foo=bar
|
||||
baz=qux
|
||||
''');
|
||||
expect(file.values['foo'], 'bar');
|
||||
expect(file.values['baz'], 'qux');
|
||||
expect(file.values, hasLength(2));
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue