// 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:convert'; import 'dart:io'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; import 'package:path/path.dart' as path; import '../prepare_package.dart'; void main() { group('ArchiveCreator', () { ArchiveCreator preparer; Directory tmpDir; Directory flutterDir; File outputFile; MockProcessRunner runner; List results; final List> args = >[]; final List> namedArgs = >[]; final String zipExe = Platform.isWindows ? '7za.exe' : 'zip'; final String tarExe = Platform.isWindows ? 'tar.exe' : 'tar'; final String gitExe = Platform.isWindows ? 'git.bat' : 'git'; String flutterExe; void _verifyCommand(List args, String expected) { final List expectedList = expected.split(' '); final String executable = expectedList.removeAt(0); expect(args[0], executable); expect(args[1], orderedEquals(expectedList)); } ProcessResult _nextResult(Invocation invocation) { args.add(invocation.positionalArguments); namedArgs.add(invocation.namedArguments); return results.isEmpty ? new MockProcessResult('', '', 0) : results.removeAt(0); } void _answerWithResults() { when( runner.call( typed(captureAny), typed(captureAny), environment: typed(captureAny, named: 'environment'), workingDirectory: typed(captureAny, named: 'workingDirectory'), includeParentEnvironment: typed(captureAny, named: 'includeParentEnvironment'), ), ).thenAnswer(_nextResult); } setUp(() async { runner = new MockProcessRunner(); args.clear(); namedArgs.clear(); tmpDir = await Directory.systemTemp.createTemp('flutter_'); flutterDir = new Directory(path.join(tmpDir.path, 'flutter')); flutterExe = path.join(flutterDir.path, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter'); }); tearDown(() async { await tmpDir.delete(recursive: true); }); test('sets PUB_CACHE properly', () async { outputFile = new File(path.join(tmpDir.absolute.path, 'flutter_master.tar.xz')); preparer = new ArchiveCreator(tmpDir, outputFile, runner: runner); _answerWithResults(); results = [new MockProcessResult('deadbeef\n', '', 0)]; preparer.checkoutFlutter('master'); preparer.prepareArchive(); preparer.createArchive(); expect( verify(runner.call( captureAny, captureAny, workingDirectory: captureAny, environment: captureAny, includeParentEnvironment: typed(captureAny, named: 'includeParentEnvironment'), )).captured[2]['PUB_CACHE'], endsWith(path.join('flutter', '.pub-cache')), ); }); test('calls the right commands for tar output', () async { outputFile = new File(path.join(tmpDir.absolute.path, 'flutter_master.tar.xz')); preparer = new ArchiveCreator(tmpDir, outputFile, runner: runner); _answerWithResults(); results = [new MockProcessResult('deadbeef\n', '', 0)]; preparer.checkoutFlutter('master'); preparer.prepareArchive(); preparer.createArchive(); final List commands = [ '$gitExe clone -b master https://chromium.googlesource.com/external/github.com/flutter/flutter', '$gitExe reset --hard master', '$gitExe remote remove origin', '$gitExe remote add origin https://github.com/flutter/flutter.git', '$flutterExe doctor', '$flutterExe update-packages', '$flutterExe precache', '$flutterExe ide-config', '$flutterExe create --template=app ${path.join(tmpDir.path, 'create_app')}', '$flutterExe create --template=package ${path.join(tmpDir.path, 'create_package')}', '$flutterExe create --template=plugin ${path.join(tmpDir.path, 'create_plugin')}', '$gitExe clean -f -X **/.packages', '$tarExe cJf ${path.join(tmpDir.path, 'flutter_master.tar.xz')} flutter', ]; int step = 0; for (String command in commands) { _verifyCommand(args[step++], command); } }); test('calls the right commands for zip output', () async { outputFile = new File(path.join(tmpDir.absolute.path, 'flutter_master.zip')); preparer = new ArchiveCreator(tmpDir, outputFile, runner: runner); _answerWithResults(); results = [new MockProcessResult('deadbeef\n', '', 0)]; preparer.checkoutFlutter('master'); preparer.prepareArchive(); preparer.createArchive(); final List commands = [ '$gitExe clone -b master https://chromium.googlesource.com/external/github.com/flutter/flutter', '$gitExe reset --hard master', '$gitExe remote remove origin', '$gitExe remote add origin https://github.com/flutter/flutter.git', '$flutterExe doctor', '$flutterExe update-packages', '$flutterExe precache', '$flutterExe ide-config', '$flutterExe create --template=app ${path.join(tmpDir.path, 'create_app')}', '$flutterExe create --template=package ${path.join(tmpDir.path, 'create_package')}', '$flutterExe create --template=plugin ${path.join(tmpDir.path, 'create_plugin')}', '$gitExe clean -f -X **/.packages', ]; if (Platform.isWindows) { commands.add('$zipExe a -tzip -mx=9 ${path.join(tmpDir.path, 'flutter_master.zip')} flutter'); } else { commands.add('$zipExe -r -9 -q ${path.join(tmpDir.path, 'flutter_master.zip')} flutter'); } int step = 0; for (String command in commands) { _verifyCommand(args[step++], command); } }); test('throws when a command errors out', () async { outputFile = new File(path.join(tmpDir.absolute.path, 'flutter.tar.xz')); preparer = new ArchiveCreator( tmpDir, outputFile, runner: runner, ); results = [ new MockProcessResult('', '', 0), new MockProcessResult('OMG! OMG! an ERROR!\n', '', -1) ]; _answerWithResults(); expect(() => preparer.checkoutFlutter('master'), throwsA(const isInstanceOf())); expect(args.length, 2); _verifyCommand(args[0], '$gitExe clone -b master https://chromium.googlesource.com/external/github.com/flutter/flutter'); _verifyCommand(args[1], '$gitExe reset --hard master'); }); }); } class MockProcessRunner extends Mock implements Function { ProcessResult call( String executable, List arguments, { String workingDirectory, Map environment, bool includeParentEnvironment, bool runInShell, Encoding stdoutEncoding, Encoding stderrEncoding, }); } class MockProcessResult extends Mock implements ProcessResult { MockProcessResult(this.stdout, [this.stderr = '', this.exitCode = 0]); @override dynamic stdout = ''; @override dynamic stderr; @override int exitCode; }