blob: 0b0772b3f3abfe2dc2df4a9bb5effeae56814f5c [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/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cmake_project.dart';
import 'package:flutter_tools/src/windows/migrations/version_migration.dart';
import 'package:test/fake.dart';
import '../../../src/common.dart';
void main () {
group('Windows Flutter version migration', () {
late MemoryFileSystem memoryFileSystem;
late BufferLogger testLogger;
late FakeWindowsProject mockProject;
late File cmakeFile;
late File resourceFile;
setUp(() {
memoryFileSystem = MemoryFileSystem.test();
cmakeFile = memoryFileSystem.file('CMakeLists.txt');
resourceFile = memoryFileSystem.file('Runner.rc');
testLogger = BufferLogger(
terminal: Terminal.test(),
outputPreferences: OutputPreferences.test(),
);
mockProject = FakeWindowsProject(cmakeFile, resourceFile);
});
testWithoutContext('skipped if CMake file is missing', () async {
const String resourceFileContents = 'Hello world';
resourceFile.writeAsStringSync(resourceFileContents);
final VersionMigration migration = VersionMigration(
mockProject,
testLogger,
);
await migration.migrate();
expect(cmakeFile.existsSync(), isFalse);
expect(resourceFile.existsSync(), isTrue);
expect(testLogger.traceText,
contains('windows/runner/CMakeLists.txt file not found, skipping version migration'));
expect(testLogger.statusText, isEmpty);
});
testWithoutContext('skipped if resource file is missing', () async {
const String cmakeFileContents = 'Hello world';
cmakeFile.writeAsStringSync(cmakeFileContents);
final VersionMigration migration = VersionMigration(
mockProject,
testLogger,
);
await migration.migrate();
expect(cmakeFile.existsSync(), isTrue);
expect(resourceFile.existsSync(), isFalse);
expect(testLogger.traceText,
contains('windows/runner/Runner.rc file not found, skipping version migration'));
expect(testLogger.statusText, isEmpty);
});
testWithoutContext('skipped if nothing to migrate', () async {
const String cmakeFileContents = 'Nothing to migrate';
const String resourceFileContents = 'Nothing to migrate';
cmakeFile.writeAsStringSync(cmakeFileContents);
resourceFile.writeAsStringSync(resourceFileContents);
final DateTime cmakeUpdatedAt = cmakeFile.lastModifiedSync();
final DateTime resourceUpdatedAt = resourceFile.lastModifiedSync();
final VersionMigration versionMigration = VersionMigration(
mockProject,
testLogger,
);
await versionMigration.migrate();
expect(cmakeFile.lastModifiedSync(), cmakeUpdatedAt);
expect(cmakeFile.readAsStringSync(), cmakeFileContents);
expect(resourceFile.lastModifiedSync(), resourceUpdatedAt);
expect(resourceFile.readAsStringSync(), resourceFileContents);
expect(testLogger.statusText, isEmpty);
});
testWithoutContext('skipped if already migrated', () async {
const String cmakeFileContents =
'# Apply the standard set of build settings. This can be removed for applications\n'
'# that need different build settings.\n'
'apply_standard_settings(\${BINARY_NAME})\n'
'\n'
'# Add preprocessor definitions for the build version.\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\\"\${FLUTTER_VERSION}\\"")\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=\${FLUTTER_VERSION_MAJOR}")\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=\${FLUTTER_VERSION_MINOR}")\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=\${FLUTTER_VERSION_PATCH}")\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=\${FLUTTER_VERSION_BUILD}")\n'
'\n'
'# Disable Windows macros that collide with C++ standard library functions.\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "NOMINMAX")\n';
const String resourceFileContents =
'#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)\n'
'#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD\n'
'#else\n'
'#define VERSION_AS_NUMBER 1,0,0,0\n'
'#endif\n'
'\n'
'#if defined(FLUTTER_VERSION)\n'
'#define VERSION_AS_STRING FLUTTER_VERSION\n'
'#else\n'
'#define VERSION_AS_STRING "1.0.0"\n'
'#endif\n';
cmakeFile.writeAsStringSync(cmakeFileContents);
resourceFile.writeAsStringSync(resourceFileContents);
final DateTime cmakeUpdatedAt = cmakeFile.lastModifiedSync();
final DateTime resourceUpdatedAt = resourceFile.lastModifiedSync();
final VersionMigration versionMigration = VersionMigration(
mockProject,
testLogger,
);
await versionMigration.migrate();
expect(cmakeFile.lastModifiedSync(), cmakeUpdatedAt);
expect(cmakeFile.readAsStringSync(), cmakeFileContents);
expect(resourceFile.lastModifiedSync(), resourceUpdatedAt);
expect(resourceFile.readAsStringSync(), resourceFileContents);
expect(testLogger.statusText, isEmpty);
});
testWithoutContext('skipped if already migrated (CRLF)', () async {
const String cmakeFileContents =
'# Apply the standard set of build settings. This can be removed for applications\r\n'
'# that need different build settings.\r\n'
'apply_standard_settings(\${BINARY_NAME})\r\n'
'\r\n'
'# Add preprocessor definitions for the build version.\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\\"\${FLUTTER_VERSION}\\"")\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=\${FLUTTER_VERSION_MAJOR}")\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=\${FLUTTER_VERSION_MINOR}")\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=\${FLUTTER_VERSION_PATCH}")\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=\${FLUTTER_VERSION_BUILD}")\r\n'
'\r\n'
'# Disable Windows macros that collide with C++ standard library functions.\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "NOMINMAX")\r\n';
const String resourceFileContents =
'#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)\r\n'
'#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD\r\n'
'#else\r\n'
'#define VERSION_AS_NUMBER 1,0,0,0\r\n'
'#endif\r\n'
'\r\n'
'#if defined(FLUTTER_VERSION)\r\n'
'#define VERSION_AS_STRING FLUTTER_VERSION\r\n'
'#else\r\n'
'#define VERSION_AS_STRING "1.0.0"\r\n'
'#endif\r\n';
cmakeFile.writeAsStringSync(cmakeFileContents);
resourceFile.writeAsStringSync(resourceFileContents);
final DateTime cmakeUpdatedAt = cmakeFile.lastModifiedSync();
final DateTime resourceUpdatedAt = resourceFile.lastModifiedSync();
final VersionMigration versionMigration = VersionMigration(
mockProject,
testLogger,
);
await versionMigration.migrate();
expect(cmakeFile.lastModifiedSync(), cmakeUpdatedAt);
expect(cmakeFile.readAsStringSync(), cmakeFileContents);
expect(resourceFile.lastModifiedSync(), resourceUpdatedAt);
expect(resourceFile.readAsStringSync(), resourceFileContents);
expect(testLogger.statusText, isEmpty);
});
testWithoutContext('migrates project to set version information', () async {
cmakeFile.writeAsStringSync(
'# Apply the standard set of build settings. This can be removed for applications\n'
'# that need different build settings.\n'
'apply_standard_settings(\${BINARY_NAME})\n'
'\n'
'# Disable Windows macros that collide with C++ standard library functions.\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "NOMINMAX")\n'
);
resourceFile.writeAsStringSync(
'#ifdef FLUTTER_BUILD_NUMBER\n'
'#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER\n'
'#else\n'
'#define VERSION_AS_NUMBER 1,0,0\n'
'#endif\n'
'\n'
'#ifdef FLUTTER_BUILD_NAME\n'
'#define VERSION_AS_STRING #FLUTTER_BUILD_NAME\n'
'#else\n'
'#define VERSION_AS_STRING "1.0.0"\n'
'#endif\n'
);
final VersionMigration versionMigration = VersionMigration(
mockProject,
testLogger,
);
await versionMigration.migrate();
expect(cmakeFile.readAsStringSync(),
'# Apply the standard set of build settings. This can be removed for applications\n'
'# that need different build settings.\n'
'apply_standard_settings(\${BINARY_NAME})\n'
'\n'
'# Add preprocessor definitions for the build version.\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\\"\${FLUTTER_VERSION}\\"")\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=\${FLUTTER_VERSION_MAJOR}")\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=\${FLUTTER_VERSION_MINOR}")\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=\${FLUTTER_VERSION_PATCH}")\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=\${FLUTTER_VERSION_BUILD}")\n'
'\n'
'# Disable Windows macros that collide with C++ standard library functions.\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "NOMINMAX")\n'
);
expect(resourceFile.readAsStringSync(),
'#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)\n'
'#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD\n'
'#else\n'
'#define VERSION_AS_NUMBER 1,0,0,0\n'
'#endif\n'
'\n'
'#if defined(FLUTTER_VERSION)\n'
'#define VERSION_AS_STRING FLUTTER_VERSION\n'
'#else\n'
'#define VERSION_AS_STRING "1.0.0"\n'
'#endif\n'
);
expect(testLogger.statusText, contains('windows/runner/CMakeLists.txt does not define version information, updating.'));
expect(testLogger.statusText, contains('windows/runner/Runner.rc does not use Flutter version information, updating.'));
});
testWithoutContext('migrates project to set version information (CRLF)', () async {
cmakeFile.writeAsStringSync(
'# Apply the standard set of build settings. This can be removed for applications\r\n'
'# that need different build settings.\r\n'
'apply_standard_settings(\${BINARY_NAME})\r\n'
'\r\n'
'# Disable Windows macros that collide with C++ standard library functions.\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "NOMINMAX")\r\n'
);
resourceFile.writeAsStringSync(
'#ifdef FLUTTER_BUILD_NUMBER\r\n'
'#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER\r\n'
'#else\r\n'
'#define VERSION_AS_NUMBER 1,0,0\r\n'
'#endif\r\n'
'\r\n'
'#ifdef FLUTTER_BUILD_NAME\r\n'
'#define VERSION_AS_STRING #FLUTTER_BUILD_NAME\r\n'
'#else\r\n'
'#define VERSION_AS_STRING "1.0.0"\r\n'
'#endif\r\n'
);
final VersionMigration versionMigration = VersionMigration(
mockProject,
testLogger,
);
await versionMigration.migrate();
expect(cmakeFile.readAsStringSync(),
'# Apply the standard set of build settings. This can be removed for applications\r\n'
'# that need different build settings.\r\n'
'apply_standard_settings(\${BINARY_NAME})\r\n'
'\r\n'
'# Add preprocessor definitions for the build version.\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\\"\${FLUTTER_VERSION}\\"")\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=\${FLUTTER_VERSION_MAJOR}")\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=\${FLUTTER_VERSION_MINOR}")\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=\${FLUTTER_VERSION_PATCH}")\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=\${FLUTTER_VERSION_BUILD}")\r\n'
'\r\n'
'# Disable Windows macros that collide with C++ standard library functions.\r\n'
'target_compile_definitions(\${BINARY_NAME} PRIVATE "NOMINMAX")\r\n'
);
expect(resourceFile.readAsStringSync(),
'#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)\r\n'
'#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD\r\n'
'#else\r\n'
'#define VERSION_AS_NUMBER 1,0,0,0\r\n'
'#endif\r\n'
'\r\n'
'#if defined(FLUTTER_VERSION)\r\n'
'#define VERSION_AS_STRING FLUTTER_VERSION\r\n'
'#else\r\n'
'#define VERSION_AS_STRING "1.0.0"\r\n'
'#endif\r\n'
);
expect(testLogger.statusText, contains('windows/runner/CMakeLists.txt does not define version information, updating.'));
expect(testLogger.statusText, contains('windows/runner/Runner.rc does not use Flutter version information, updating.'));
});
});
}
class FakeWindowsProject extends Fake implements WindowsProject {
FakeWindowsProject(this.runnerCmakeFile, this.runnerResourceFile);
@override
final File runnerCmakeFile;
@override
final File runnerResourceFile;
}