| // Copyright 2017 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 'package:args/command_runner.dart'; | |
| import 'package:flutter_tools/src/base/file_system.dart'; | |
| import 'package:flutter_tools/src/cache.dart'; | |
| import 'package:flutter_tools/src/template.dart'; | |
| import 'package:flutter_tools/src/commands/ide_config.dart'; | |
| import '../src/common.dart'; | |
| import '../src/context.dart'; | |
| void main() { | |
| group('ide_config', () { | |
| Directory tempDir; | |
| Directory templateDir; | |
| Directory intellijDir; | |
| Directory toolsDir; | |
| Map<String, String> _getFilesystemContents([Directory root]) { | |
| final String tempPath = tempDir.absolute.path; | |
| final List<String> paths = | |
| (root ?? tempDir).listSync(recursive: true).map((FileSystemEntity entity) { | |
| final String relativePath = fs.path.relative(entity.path, from: tempPath); | |
| return relativePath; | |
| }).toList(); | |
| final Map<String, String> contents = <String, String>{}; | |
| for (String path in paths) { | |
| final String absPath = fs.path.join(tempPath, path); | |
| if (fs.isDirectorySync(absPath)) { | |
| contents[path] = 'dir'; | |
| } else if (fs.isFileSync(absPath)) { | |
| contents[path] = fs.file(absPath).readAsStringSync(); | |
| } | |
| } | |
| return contents; | |
| } | |
| Map<String, String> _getManifest(Directory base, String marker, {bool isTemplate = false}) { | |
| final String basePath = fs.path.relative(base.path, from: tempDir.absolute.path); | |
| final String suffix = isTemplate ? Template.copyTemplateExtension : ''; | |
| return <String, String>{ | |
| fs.path.join(basePath, '.idea'): 'dir', | |
| fs.path.join(basePath, '.idea', 'modules.xml$suffix'): 'modules $marker', | |
| fs.path.join(basePath, '.idea', 'vcs.xml$suffix'): 'vcs $marker', | |
| fs.path.join(basePath, '.idea', '.name$suffix'): | |
| 'codeStyleSettings $marker', | |
| fs.path.join(basePath, '.idea', 'runConfigurations'): 'dir', | |
| fs.path.join(basePath, '.idea', 'runConfigurations', 'hello_world.xml$suffix'): | |
| 'hello_world $marker', | |
| fs.path.join(basePath, 'flutter.iml$suffix'): 'flutter $marker', | |
| fs.path.join(basePath, 'packages', 'new', 'deep.iml$suffix'): 'deep $marker', | |
| }; | |
| } | |
| void _populateDir(Map<String, String> manifest) { | |
| for (String key in manifest.keys) { | |
| if (manifest[key] == 'dir') { | |
| tempDir.childDirectory(key)..createSync(recursive: true); | |
| } | |
| } | |
| for (String key in manifest.keys) { | |
| if (manifest[key] != 'dir') { | |
| tempDir.childFile(key) | |
| ..createSync(recursive: true) | |
| ..writeAsStringSync(manifest[key]); | |
| } | |
| } | |
| } | |
| bool _fileOrDirectoryExists(String path) { | |
| final String absPath = fs.path.join(tempDir.absolute.path, path); | |
| return fs.file(absPath).existsSync() || fs.directory(absPath).existsSync(); | |
| } | |
| Future<void> _updateIdeConfig({ | |
| Directory dir, | |
| List<String> args = const <String>[], | |
| Map<String, String> expectedContents = const <String, String>{}, | |
| List<String> unexpectedPaths = const <String>[], | |
| }) async { | |
| dir ??= tempDir; | |
| final IdeConfigCommand command = IdeConfigCommand(); | |
| final CommandRunner<void> runner = createTestCommandRunner(command); | |
| final List<String> finalArgs = <String>['--flutter-root=${tempDir.absolute.path}', 'ide-config']; | |
| finalArgs.addAll(args); | |
| await runner.run(finalArgs); | |
| for (String path in expectedContents.keys) { | |
| final String absPath = fs.path.join(tempDir.absolute.path, path); | |
| expect(_fileOrDirectoryExists(fs.path.join(dir.path, path)), true, | |
| reason: "$path doesn't exist"); | |
| if (fs.file(absPath).existsSync()) { | |
| expect(fs.file(absPath).readAsStringSync(), equals(expectedContents[path]), | |
| reason: "$path contents don't match"); | |
| } | |
| } | |
| for (String path in unexpectedPaths) { | |
| expect(_fileOrDirectoryExists(fs.path.join(dir.path, path)), false, reason: '$path exists'); | |
| } | |
| } | |
| setUpAll(() { | |
| Cache.disableLocking(); | |
| }); | |
| setUp(() { | |
| tempDir = fs.systemTempDirectory.createTempSync('flutter_tools_ide_config_test.'); | |
| final Directory packagesDir = tempDir.childDirectory('packages')..createSync(recursive: true); | |
| toolsDir = packagesDir.childDirectory('flutter_tools')..createSync(); | |
| templateDir = toolsDir.childDirectory('ide_templates')..createSync(); | |
| intellijDir = templateDir.childDirectory('intellij')..createSync(); | |
| }); | |
| tearDown(() { | |
| tryToDelete(tempDir); | |
| }); | |
| testUsingContext("doesn't touch existing files without --overwrite", () async { | |
| final Map<String, String> templateManifest = _getManifest( | |
| intellijDir, | |
| 'template', | |
| isTemplate: true, | |
| ); | |
| final Map<String, String> flutterManifest = _getManifest( | |
| tempDir, | |
| 'existing', | |
| ); | |
| _populateDir(templateManifest); | |
| _populateDir(flutterManifest); | |
| final Map<String, String> expectedContents = _getFilesystemContents(); | |
| return _updateIdeConfig( | |
| expectedContents: expectedContents, | |
| ); | |
| }, timeout: const Timeout.factor(2.0)); | |
| testUsingContext('creates non-existent files', () async { | |
| final Map<String, String> templateManifest = _getManifest( | |
| intellijDir, | |
| 'template', | |
| isTemplate: true, | |
| ); | |
| final Map<String, String> flutterManifest = _getManifest( | |
| tempDir, | |
| 'template', | |
| ); | |
| _populateDir(templateManifest); | |
| final Map<String, String> expectedContents = templateManifest; | |
| expectedContents.addAll(flutterManifest); | |
| return _updateIdeConfig( | |
| expectedContents: expectedContents, | |
| ); | |
| }, timeout: const Timeout.factor(2.0)); | |
| testUsingContext('overwrites existing files with --overwrite', () async { | |
| final Map<String, String> templateManifest = _getManifest( | |
| intellijDir, | |
| 'template', | |
| isTemplate: true, | |
| ); | |
| final Map<String, String> flutterManifest = _getManifest( | |
| tempDir, | |
| 'existing', | |
| ); | |
| _populateDir(templateManifest); | |
| _populateDir(flutterManifest); | |
| final Map<String, String> overwrittenManifest = _getManifest( | |
| tempDir, | |
| 'template', | |
| ); | |
| final Map<String, String> expectedContents = templateManifest; | |
| expectedContents.addAll(overwrittenManifest); | |
| return _updateIdeConfig( | |
| args: <String>['--overwrite'], | |
| expectedContents: expectedContents, | |
| ); | |
| }, timeout: const Timeout.factor(2.0)); | |
| testUsingContext('only adds new templates without --overwrite', () async { | |
| final Map<String, String> templateManifest = _getManifest( | |
| intellijDir, | |
| 'template', | |
| isTemplate: true, | |
| ); | |
| final String flutterIml = fs.path.join( | |
| 'packages', | |
| 'flutter_tools', | |
| 'ide_templates', | |
| 'intellij', | |
| 'flutter.iml${Template.copyTemplateExtension}', | |
| ); | |
| templateManifest.remove(flutterIml); | |
| _populateDir(templateManifest); | |
| templateManifest[flutterIml] = 'flutter existing'; | |
| final Map<String, String> flutterManifest = _getManifest( | |
| tempDir, | |
| 'existing', | |
| ); | |
| _populateDir(flutterManifest); | |
| final Map<String, String> expectedContents = flutterManifest; | |
| expectedContents.addAll(templateManifest); | |
| return _updateIdeConfig( | |
| args: <String>['--update-templates'], | |
| expectedContents: expectedContents, | |
| ); | |
| }, timeout: const Timeout.factor(2.0)); | |
| testUsingContext('update all templates with --overwrite', () async { | |
| final Map<String, String> templateManifest = _getManifest( | |
| intellijDir, | |
| 'template', | |
| isTemplate: true, | |
| ); | |
| _populateDir(templateManifest); | |
| final Map<String, String> flutterManifest = _getManifest( | |
| tempDir, | |
| 'existing', | |
| ); | |
| _populateDir(flutterManifest); | |
| final Map<String, String> updatedTemplates = _getManifest( | |
| intellijDir, | |
| 'existing', | |
| isTemplate: true, | |
| ); | |
| final Map<String, String> expectedContents = flutterManifest; | |
| expectedContents.addAll(updatedTemplates); | |
| return _updateIdeConfig( | |
| args: <String>['--update-templates', '--overwrite'], | |
| expectedContents: expectedContents, | |
| ); | |
| }, timeout: const Timeout.factor(2.0)); | |
| testUsingContext('removes deleted imls with --overwrite', () async { | |
| final Map<String, String> templateManifest = _getManifest( | |
| intellijDir, | |
| 'template', | |
| isTemplate: true, | |
| ); | |
| _populateDir(templateManifest); | |
| final Map<String, String> flutterManifest = _getManifest( | |
| tempDir, | |
| 'existing', | |
| ); | |
| flutterManifest.remove('flutter.iml'); | |
| _populateDir(flutterManifest); | |
| final Map<String, String> updatedTemplates = _getManifest( | |
| intellijDir, | |
| 'existing', | |
| isTemplate: true, | |
| ); | |
| final String flutterIml = fs.path.join( | |
| 'packages', | |
| 'flutter_tools', | |
| 'ide_templates', | |
| 'intellij', | |
| 'flutter.iml${Template.copyTemplateExtension}', | |
| ); | |
| updatedTemplates.remove(flutterIml); | |
| final Map<String, String> expectedContents = flutterManifest; | |
| expectedContents.addAll(updatedTemplates); | |
| return _updateIdeConfig( | |
| args: <String>['--update-templates', '--overwrite'], | |
| expectedContents: expectedContents, | |
| ); | |
| }, timeout: const Timeout.factor(2.0)); | |
| testUsingContext('removes deleted imls with --overwrite, including empty parent dirs', () async { | |
| final Map<String, String> templateManifest = _getManifest( | |
| intellijDir, | |
| 'template', | |
| isTemplate: true, | |
| ); | |
| _populateDir(templateManifest); | |
| final Map<String, String> flutterManifest = _getManifest( | |
| tempDir, | |
| 'existing', | |
| ); | |
| flutterManifest.remove(fs.path.join('packages', 'new', 'deep.iml')); | |
| _populateDir(flutterManifest); | |
| final Map<String, String> updatedTemplates = _getManifest( | |
| intellijDir, | |
| 'existing', | |
| isTemplate: true, | |
| ); | |
| String deepIml = fs.path.join( | |
| 'packages', | |
| 'flutter_tools', | |
| 'ide_templates', | |
| 'intellij'); | |
| // Remove the all the dir entries too. | |
| updatedTemplates.remove(deepIml); | |
| deepIml = fs.path.join(deepIml, 'packages'); | |
| updatedTemplates.remove(deepIml); | |
| deepIml = fs.path.join(deepIml, 'new'); | |
| updatedTemplates.remove(deepIml); | |
| deepIml = fs.path.join(deepIml, 'deep.iml'); | |
| updatedTemplates.remove(deepIml); | |
| final Map<String, String> expectedContents = flutterManifest; | |
| expectedContents.addAll(updatedTemplates); | |
| return _updateIdeConfig( | |
| args: <String>['--update-templates', '--overwrite'], | |
| expectedContents: expectedContents, | |
| ); | |
| }, timeout: const Timeout.factor(2.0)); | |
| }); | |
| } |