flutter/dev/bots/test/prepare_package_test.dart
Greg Spencer 29d59e3cb7
Switch Mac packaging to use .zip files. (#14894)
We can't use .tar.xz on Mac because although it can unpack them on the command line (with tar), the "Archive Utility" that runs when you double-click on them just does some crazy behavior (it
converts it to a compressed cpio archive, and when you double-click on that, it converts it back to .tar.xz, without ever unpacking it!)

So, this changes the script to use .zip for Mac, and the files are about 220MB larger than they need to be.
2018-02-27 13:15:32 -08:00

286 lines
12 KiB
Dart

// 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 'dart:convert';
import 'dart:io' hide Platform;
import 'dart:typed_data';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'package:path/path.dart' as path;
import 'package:platform/platform.dart' show FakePlatform;
import '../prepare_package.dart';
import 'fake_process_manager.dart';
void main() {
final String testRef = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef';
for (String platformName in <String>['macos', 'linux', 'windows']) {
final FakePlatform platform = new FakePlatform(
operatingSystem: platformName,
environment: <String, String>{},
);
group('ProcessRunner for $platform', () {
test('Returns stdout', () async {
final FakeProcessManager fakeProcessManager = new FakeProcessManager();
fakeProcessManager.fakeResults = <String, List<ProcessResult>>{
'echo test': <ProcessResult>[new ProcessResult(0, 0, 'output', 'error')],
};
final ProcessRunner processRunner = new ProcessRunner(
subprocessOutput: false, platform: platform, processManager: fakeProcessManager);
final String output = await processRunner.runProcess(<String>['echo', 'test']);
expect(output, equals('output'));
});
test('Throws on process failure', () async {
final FakeProcessManager fakeProcessManager = new FakeProcessManager();
fakeProcessManager.fakeResults = <String, List<ProcessResult>>{
'echo test': <ProcessResult>[new ProcessResult(0, -1, 'output', 'error')],
};
final ProcessRunner processRunner = new ProcessRunner(
subprocessOutput: false, platform: platform, processManager: fakeProcessManager);
expect(
expectAsync1((List<String> commandLine) async {
return processRunner.runProcess(commandLine);
})(<String>['echo', 'test']),
throwsA(const isInstanceOf<ProcessRunnerException>()));
});
});
group('ArchiveCreator for $platformName', () {
ArchiveCreator creator;
Directory tmpDir;
Directory flutterDir;
FakeProcessManager processManager;
final List<List<String>> args = <List<String>>[];
final List<Map<Symbol, dynamic>> namedArgs = <Map<Symbol, dynamic>>[];
String flutter;
Future<Uint8List> fakeHttpReader(Uri url, {Map<String, String> headers}) {
return new Future<Uint8List>.value(new Uint8List(0));
}
setUp(() async {
processManager = new FakeProcessManager();
args.clear();
namedArgs.clear();
tmpDir = await Directory.systemTemp.createTemp('flutter_');
flutterDir = new Directory(path.join(tmpDir.path, 'flutter'));
flutterDir.createSync(recursive: true);
creator = new ArchiveCreator(
tmpDir,
tmpDir,
testRef,
Branch.dev,
processManager: processManager,
subprocessOutput: false,
platform: platform,
httpReader: fakeHttpReader,
);
flutter = path.join(creator.flutterRoot.absolute.path, 'bin', 'flutter');
});
tearDown(() async {
// On Windows, the directory is locked and not able to be deleted yet. So
// we just leave some (very small, because we're not actually building
// archives here) trash around to be deleted at the next reboot.
if (!platform.isWindows) {
await tmpDir.delete(recursive: true);
}
});
test('sets PUB_CACHE properly', () async {
final String createBase = path.join(tmpDir.absolute.path, 'create_');
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter':
null,
'git reset --hard $testRef': null,
'git remote remove origin': null,
'git remote add origin https://github.com/flutter/flutter.git': null,
'git describe --tags --abbrev=0': <ProcessResult>[new ProcessResult(0, 0, 'v1.2.3', '')],
};
if (platform.isWindows) {
calls['7za x ${path.join(tmpDir.path, 'mingit.zip')}'] = null;
}
calls.addAll(<String, List<ProcessResult>>{
'$flutter doctor': null,
'$flutter update-packages': null,
'$flutter precache': null,
'$flutter ide-config': null,
'$flutter create --template=app ${createBase}app': null,
'$flutter create --template=package ${createBase}package': null,
'$flutter create --template=plugin ${createBase}plugin': null,
'git clean -f -X **/.packages': null,
});
final String archiveName = path.join(tmpDir.absolute.path,
'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}');
if (platform.isWindows) {
calls['7za a -tzip -mx=9 $archiveName flutter'] = null;
} else if (platform.isMacOS) {
calls['zip -r -9 $archiveName flutter'] = null;
} else if (platform.isLinux) {
calls['tar cJf $archiveName flutter'] = null;
}
processManager.fakeResults = calls;
await creator.initializeRepo();
await creator.createArchive();
expect(
verify(processManager.start(
captureAny,
workingDirectory: captureAny,
environment: captureAny,
)).captured[1]['PUB_CACHE'],
endsWith(path.join('flutter', '.pub-cache')),
);
});
test('calls the right commands for archive output', () async {
final String createBase = path.join(tmpDir.absolute.path, 'create_');
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter':
null,
'git reset --hard $testRef': null,
'git remote remove origin': null,
'git remote add origin https://github.com/flutter/flutter.git': null,
'git describe --tags --abbrev=0': <ProcessResult>[new ProcessResult(0, 0, 'v1.2.3', '')],
};
if (platform.isWindows) {
calls['7za x ${path.join(tmpDir.path, 'mingit.zip')}'] = null;
}
calls.addAll(<String, List<ProcessResult>>{
'$flutter doctor': null,
'$flutter update-packages': null,
'$flutter precache': null,
'$flutter ide-config': null,
'$flutter create --template=app ${createBase}app': null,
'$flutter create --template=package ${createBase}package': null,
'$flutter create --template=plugin ${createBase}plugin': null,
'git clean -f -X **/.packages': null,
});
final String archiveName = path.join(tmpDir.absolute.path,
'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}');
if (platform.isWindows) {
calls['7za a -tzip -mx=9 $archiveName flutter'] = null;
} else if (platform.isMacOS) {
calls['zip -r -9 $archiveName flutter'] = null;
} else if (platform.isLinux) {
calls['tar cJf $archiveName flutter'] = null;
}
processManager.fakeResults = calls;
creator = new ArchiveCreator(
tmpDir,
tmpDir,
testRef,
Branch.dev,
processManager: processManager,
subprocessOutput: false,
platform: platform,
httpReader: fakeHttpReader,
);
await creator.initializeRepo();
await creator.createArchive();
processManager.verifyCalls(calls.keys.toList());
});
test('throws when a command errors out', () async {
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter':
<ProcessResult>[new ProcessResult(0, 0, 'output1', '')],
'git reset --hard $testRef': <ProcessResult>[new ProcessResult(0, -1, 'output2', '')],
};
processManager.fakeResults = calls;
expect(expectAsync0(creator.initializeRepo),
throwsA(const isInstanceOf<ProcessRunnerException>()));
});
});
group('ArchivePublisher for $platformName', () {
FakeProcessManager processManager;
Directory tempDir;
setUp(() async {
processManager = new FakeProcessManager();
tempDir = await Directory.systemTemp.createTemp('flutter_');
tempDir.createSync();
});
tearDown(() async {
// On Windows, the directory is locked and not able to be deleted yet. So
// we just leave some (very small, because we're not actually building
// archives here) trash around to be deleted at the next reboot.
if (!platform.isWindows) {
await tempDir.delete(recursive: true);
}
});
test('calls the right processes', () async {
final String releasesName = 'releases_$platformName.json';
final String archiveName = platform.isLinux ? 'archive.tar.xz' : 'archive.zip';
final String archiveMime = platform.isLinux ? 'application/x-gtar' : 'application/zip';
final String archivePath = path.join(tempDir.absolute.path, archiveName);
final String gsArchivePath = 'gs://flutter_infra/releases/dev/$platformName/$archiveName';
final String jsonPath = path.join(tempDir.absolute.path, releasesName);
final String gsJsonPath = 'gs://flutter_infra/releases/$releasesName';
final String releasesJson = '''{
"base_url": "https://storage.googleapis.com/flutter_infra/releases",
"current_release": {
"beta": "6da8ec6bd0c4801b80d666869e4069698561c043",
"dev": "f88c60b38c3a5ef92115d24e3da4175b4890daba"
},
"releases": {
"6da8ec6bd0c4801b80d666869e4069698561c043": {
"${platformName}_archive": "dev/linux/flutter_${platformName}_0.21.0-beta.zip",
"release_date": "2017-12-19T10:30:00,847287019-08:00",
"version": "0.21.0-beta"
},
"f88c60b38c3a5ef92115d24e3da4175b4890daba": {
"${platformName}_archive": "dev/linux/flutter_${platformName}_0.22.0-dev.zip",
"release_date": "2018-01-19T13:30:09,728487019-08:00",
"version": "0.22.0-dev"
}
}
}
''';
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
'gsutil rm $gsArchivePath': null,
'gsutil -h Content-Type:$archiveMime cp $archivePath $gsArchivePath': null,
'gsutil cat $gsJsonPath': <ProcessResult>[new ProcessResult(0, 0, releasesJson, '')],
'gsutil rm $gsJsonPath': null,
'gsutil -h Content-Type:application/json cp $jsonPath $gsJsonPath': null,
};
processManager.fakeResults = calls;
final File outputFile = new File(path.join(tempDir.absolute.path, archiveName));
assert(tempDir.existsSync());
final ArchivePublisher publisher = new ArchivePublisher(
tempDir,
testRef,
Branch.dev,
'1.2.3',
outputFile,
processManager: processManager,
subprocessOutput: false,
platform: platform,
);
assert(tempDir.existsSync());
await publisher.publishArchive();
processManager.verifyCalls(calls.keys.toList());
final File releaseFile = new File(jsonPath);
expect(releaseFile.existsSync(), isTrue);
final String contents = releaseFile.readAsStringSync();
// Make sure new data is added.
expect(contents, contains('"dev": "$testRef"'));
expect(contents, contains('"$testRef": {'));
expect(contents, contains('"${platformName}_archive": "dev/$platformName/$archiveName"'));
// Make sure existing entries are preserved.
expect(contents, contains('"6da8ec6bd0c4801b80d666869e4069698561c043": {'));
expect(contents, contains('"f88c60b38c3a5ef92115d24e3da4175b4890daba": {'));
expect(contents, contains('"beta": "6da8ec6bd0c4801b80d666869e4069698561c043"'));
// Make sure it's valid JSON, and in the right format.
final Map<String, dynamic> jsonData = json.decode(contents);
final JsonEncoder encoder = const JsonEncoder.withIndent(' ');
expect(contents, equals(encoder.convert(jsonData)));
});
});
}
}