// 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/file.dart'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/android/multidex.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/globals.dart' as globals; import '../../src/common.dart'; import '../../src/context.dart'; void main() { testUsingContext('ensureMultidexUtilsExists patches file when invalid', () async { final Directory directory = globals.fs.currentDirectory; final File applicationFile = directory.childDirectory('android') .childDirectory('app') .childDirectory('src') .childDirectory('main') .childDirectory('java') .childDirectory('io') .childDirectory('flutter') .childDirectory('app') .childFile('FlutterMultiDexApplication.java'); applicationFile.createSync(recursive: true); applicationFile.writeAsStringSync('hello', flush: true); expect(applicationFile.readAsStringSync(), 'hello'); ensureMultiDexApplicationExists(directory); // File should remain untouched expect(applicationFile.readAsStringSync(), ''' // Generated file. // // If you wish to remove Flutter's multidex support, delete this entire file. // // Modifications to this file should be done in a copy under a different name // as this file may be regenerated. package io.flutter.app; import android.app.Application; import android.content.Context; import androidx.annotation.CallSuper; import androidx.multidex.MultiDex; /** * Extension of {@link android.app.Application}, adding multidex support. */ public class FlutterMultiDexApplication extends Application { @Override @CallSuper protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); } } '''); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('ensureMultiDexApplicationExists generates when does not exist', () async { final Directory directory = globals.fs.currentDirectory; final File applicationFile = directory.childDirectory('android') .childDirectory('app') .childDirectory('src') .childDirectory('main') .childDirectory('java') .childDirectory('io') .childDirectory('flutter') .childDirectory('app') .childFile('FlutterMultiDexApplication.java'); ensureMultiDexApplicationExists(directory); final String contents = applicationFile.readAsStringSync(); expect(contents.contains('FlutterMultiDexApplication'), true); expect(contents.contains('MultiDex.install(this);'), true); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('multiDexApplicationExists false when does not exist', () async { final Directory directory = globals.fs.currentDirectory; expect(multiDexApplicationExists(directory), false); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('multiDexApplicationExists true when does exist', () async { final Directory directory = globals.fs.currentDirectory; final File utilsFile = directory.childDirectory('android') .childDirectory('app') .childDirectory('src') .childDirectory('main') .childDirectory('java') .childDirectory('io') .childDirectory('flutter') .childDirectory('app') .childFile('FlutterMultiDexApplication.java'); utilsFile.createSync(recursive: true); expect(multiDexApplicationExists(directory), true); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('androidManifestHasNameVariable true with valid manifest', () async { final Directory directory = globals.fs.currentDirectory; final File applicationFile = directory.childDirectory('android') .childDirectory('app') .childDirectory('src') .childDirectory('main') .childFile('AndroidManifest.xml'); applicationFile.createSync(recursive: true); applicationFile.writeAsStringSync(r''' ''', flush: true); expect(androidManifestHasNameVariable(directory), true); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('androidManifestHasNameVariable false with no android:name attribute', () async { final Directory directory = globals.fs.currentDirectory; final File applicationFile = directory.childDirectory('android') .childDirectory('app') .childDirectory('src') .childDirectory('main') .childFile('AndroidManifest.xml'); applicationFile.createSync(recursive: true); applicationFile.writeAsStringSync(r''' ''', flush: true); expect(androidManifestHasNameVariable(directory), false); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('androidManifestHasNameVariable false with incorrect android:name attribute', () async { final Directory directory = globals.fs.currentDirectory; final File applicationFile = directory.childDirectory('android') .childDirectory('app') .childDirectory('src') .childDirectory('main') .childFile('AndroidManifest.xml'); applicationFile.createSync(recursive: true); applicationFile.writeAsStringSync(r''' ''', flush: true); expect(androidManifestHasNameVariable(directory), false); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('androidManifestHasNameVariable false with invalid xml manifest', () async { final Directory directory = globals.fs.currentDirectory; final File applicationFile = directory.childDirectory('android') .childDirectory('app') .childDirectory('src') .childDirectory('main') .childFile('AndroidManifest.xml'); applicationFile.createSync(recursive: true); applicationFile.writeAsStringSync(r''' ''', flush: true); expect(androidManifestHasNameVariable(directory), false); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('androidManifestHasNameVariable false with no manifest file', () async { final Directory directory = globals.fs.currentDirectory; expect(androidManifestHasNameVariable(directory), false); }, overrides: { FileSystem: () => MemoryFileSystem.test(), ProcessManager: () => FakeProcessManager.any(), }); }