2017-09-01 02:35:05 +00:00
|
|
|
// Copyright 2016 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:file/file.dart';
|
|
|
|
import 'package:file/memory.dart';
|
2017-12-06 21:27:29 +00:00
|
|
|
import 'package:flutter_tools/src/cache.dart';
|
2017-12-02 00:20:06 +00:00
|
|
|
import 'package:flutter_tools/src/base/context.dart';
|
2017-09-01 02:35:05 +00:00
|
|
|
import 'package:flutter_tools/src/base/io.dart';
|
2017-12-05 22:46:39 +00:00
|
|
|
import 'package:flutter_tools/src/base/platform.dart';
|
2017-09-01 02:35:05 +00:00
|
|
|
import 'package:flutter_tools/src/dart/pub.dart';
|
2017-12-05 22:46:39 +00:00
|
|
|
|
2017-09-01 02:35:05 +00:00
|
|
|
import 'package:mockito/mockito.dart';
|
|
|
|
import 'package:process/process.dart';
|
|
|
|
import 'package:quiver/testing/async.dart';
|
|
|
|
import 'package:test/test.dart';
|
|
|
|
|
2017-12-06 21:27:29 +00:00
|
|
|
import '../src/common.dart';
|
2017-09-01 02:35:05 +00:00
|
|
|
import '../src/context.dart';
|
|
|
|
|
|
|
|
void main() {
|
2017-12-06 21:27:29 +00:00
|
|
|
setUpAll(() {
|
|
|
|
Cache.flutterRoot = getFlutterRoot();
|
|
|
|
});
|
|
|
|
|
2017-09-01 02:35:05 +00:00
|
|
|
testUsingContext('pub get 69', () async {
|
|
|
|
String error;
|
2017-12-02 00:20:06 +00:00
|
|
|
|
2018-03-28 17:58:28 +00:00
|
|
|
final MockProcessManager processMock = context[ProcessManager];
|
2017-12-02 00:20:06 +00:00
|
|
|
|
2017-09-01 02:35:05 +00:00
|
|
|
new FakeAsync().run((FakeAsync time) {
|
2018-03-07 05:36:03 +00:00
|
|
|
expect(processMock.lastPubEnvironment, isNull);
|
2018-02-21 19:47:26 +00:00
|
|
|
expect(testLogger.statusText, '');
|
2017-12-06 16:10:56 +00:00
|
|
|
pubGet(context: PubContext.flutterTests, checkLastModified: false).then((Null value) {
|
2017-09-01 02:35:05 +00:00
|
|
|
error = 'test completed unexpectedly';
|
2017-12-05 22:46:39 +00:00
|
|
|
}, onError: (dynamic thrownError) {
|
|
|
|
error = 'test failed unexpectedly: $thrownError';
|
2017-09-01 02:35:05 +00:00
|
|
|
});
|
|
|
|
time.elapse(const Duration(milliseconds: 500));
|
|
|
|
expect(testLogger.statusText,
|
|
|
|
'Running "flutter packages get" in /...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 1 in 1 second...\n'
|
|
|
|
);
|
2018-03-07 05:36:03 +00:00
|
|
|
expect(processMock.lastPubEnvironment, contains('flutter_cli:flutter_tests'));
|
2017-12-05 22:46:39 +00:00
|
|
|
expect(processMock.lastPubCache, isNull);
|
2017-09-01 02:35:05 +00:00
|
|
|
time.elapse(const Duration(milliseconds: 500));
|
|
|
|
expect(testLogger.statusText,
|
|
|
|
'Running "flutter packages get" in /...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 1 in 1 second...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 2 in 2 seconds...\n'
|
|
|
|
);
|
|
|
|
time.elapse(const Duration(seconds: 1));
|
|
|
|
expect(testLogger.statusText,
|
|
|
|
'Running "flutter packages get" in /...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 1 in 1 second...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 2 in 2 seconds...\n'
|
|
|
|
);
|
|
|
|
time.elapse(const Duration(seconds: 100)); // from t=0 to t=100
|
|
|
|
expect(testLogger.statusText,
|
|
|
|
'Running "flutter packages get" in /...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 1 in 1 second...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 2 in 2 seconds...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 3 in 4 seconds...\n' // at t=1
|
|
|
|
'pub get failed (69) -- attempting retry 4 in 8 seconds...\n' // at t=5
|
|
|
|
'pub get failed (69) -- attempting retry 5 in 16 seconds...\n' // at t=13
|
|
|
|
'pub get failed (69) -- attempting retry 6 in 32 seconds...\n' // at t=29
|
|
|
|
'pub get failed (69) -- attempting retry 7 in 64 seconds...\n' // at t=61
|
|
|
|
);
|
|
|
|
time.elapse(const Duration(seconds: 200)); // from t=0 to t=200
|
|
|
|
expect(testLogger.statusText,
|
|
|
|
'Running "flutter packages get" in /...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 1 in 1 second...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 2 in 2 seconds...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 3 in 4 seconds...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 4 in 8 seconds...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 5 in 16 seconds...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 6 in 32 seconds...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 7 in 64 seconds...\n'
|
|
|
|
'pub get failed (69) -- attempting retry 8 in 64 seconds...\n' // at t=39
|
|
|
|
'pub get failed (69) -- attempting retry 9 in 64 seconds...\n' // at t=103
|
|
|
|
'pub get failed (69) -- attempting retry 10 in 64 seconds...\n' // at t=167
|
|
|
|
);
|
|
|
|
});
|
|
|
|
expect(testLogger.errorText, isEmpty);
|
|
|
|
expect(error, isNull);
|
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
ProcessManager: () => new MockProcessManager(69),
|
|
|
|
FileSystem: () => new MockFileSystem(),
|
2017-12-05 22:46:39 +00:00
|
|
|
Platform: () => new FakePlatform(
|
|
|
|
environment: <String, String>{},
|
|
|
|
),
|
|
|
|
});
|
|
|
|
|
|
|
|
testUsingContext('pub cache in root is used', () async {
|
|
|
|
String error;
|
|
|
|
|
2018-03-28 17:58:28 +00:00
|
|
|
final MockProcessManager processMock = context[ProcessManager];
|
|
|
|
final MockFileSystem fsMock = context[FileSystem];
|
2017-12-05 22:46:39 +00:00
|
|
|
|
|
|
|
new FakeAsync().run((FakeAsync time) {
|
|
|
|
MockDirectory.findCache = true;
|
2018-03-07 05:36:03 +00:00
|
|
|
expect(processMock.lastPubEnvironment, isNull);
|
2017-12-05 22:46:39 +00:00
|
|
|
expect(processMock.lastPubCache, isNull);
|
2017-12-06 16:10:56 +00:00
|
|
|
pubGet(context: PubContext.flutterTests, checkLastModified: false).then((Null value) {
|
2017-12-05 22:46:39 +00:00
|
|
|
error = 'test completed unexpectedly';
|
|
|
|
}, onError: (dynamic thrownError) {
|
|
|
|
error = 'test failed unexpectedly: $thrownError';
|
|
|
|
});
|
|
|
|
time.elapse(const Duration(milliseconds: 500));
|
2017-12-06 21:27:29 +00:00
|
|
|
expect(processMock.lastPubCache, equals(fsMock.path.join(Cache.flutterRoot, '.pub-cache')));
|
2017-12-05 22:46:39 +00:00
|
|
|
expect(error, isNull);
|
|
|
|
});
|
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
ProcessManager: () => new MockProcessManager(69),
|
|
|
|
FileSystem: () => new MockFileSystem(),
|
|
|
|
Platform: () => new FakePlatform(
|
|
|
|
environment: <String, String>{},
|
|
|
|
),
|
|
|
|
});
|
|
|
|
|
|
|
|
testUsingContext('pub cache in environment is used', () async {
|
|
|
|
String error;
|
|
|
|
|
2018-03-28 17:58:28 +00:00
|
|
|
final MockProcessManager processMock = context[ProcessManager];
|
2017-12-05 22:46:39 +00:00
|
|
|
|
|
|
|
new FakeAsync().run((FakeAsync time) {
|
2017-12-06 21:27:29 +00:00
|
|
|
MockDirectory.findCache = true;
|
2018-03-07 05:36:03 +00:00
|
|
|
expect(processMock.lastPubEnvironment, isNull);
|
2017-12-05 22:46:39 +00:00
|
|
|
expect(processMock.lastPubCache, isNull);
|
2017-12-06 16:10:56 +00:00
|
|
|
pubGet(context: PubContext.flutterTests, checkLastModified: false).then((Null value) {
|
2017-12-05 22:46:39 +00:00
|
|
|
error = 'test completed unexpectedly';
|
|
|
|
}, onError: (dynamic thrownError) {
|
|
|
|
error = 'test failed unexpectedly: $thrownError';
|
|
|
|
});
|
|
|
|
time.elapse(const Duration(milliseconds: 500));
|
2017-12-06 21:27:29 +00:00
|
|
|
expect(processMock.lastPubCache, equals('custom/pub-cache/path'));
|
2017-12-05 22:46:39 +00:00
|
|
|
expect(error, isNull);
|
|
|
|
});
|
|
|
|
}, overrides: <Type, Generator>{
|
|
|
|
ProcessManager: () => new MockProcessManager(69),
|
|
|
|
FileSystem: () => new MockFileSystem(),
|
|
|
|
Platform: () => new FakePlatform(
|
2017-12-06 21:27:29 +00:00
|
|
|
environment: <String, String>{'PUB_CACHE': 'custom/pub-cache/path'},
|
2017-12-05 22:46:39 +00:00
|
|
|
),
|
2017-09-01 02:35:05 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-06-11 22:51:45 +00:00
|
|
|
typedef StartCallback = void Function(List<dynamic> command);
|
2017-09-01 02:35:05 +00:00
|
|
|
|
|
|
|
class MockProcessManager implements ProcessManager {
|
|
|
|
MockProcessManager(this.fakeExitCode);
|
|
|
|
|
|
|
|
final int fakeExitCode;
|
|
|
|
|
2018-03-07 05:36:03 +00:00
|
|
|
String lastPubEnvironment;
|
2017-12-05 22:46:39 +00:00
|
|
|
String lastPubCache;
|
2017-12-02 00:20:06 +00:00
|
|
|
|
2017-09-01 02:35:05 +00:00
|
|
|
@override
|
|
|
|
Future<Process> start(
|
|
|
|
List<dynamic> command, {
|
|
|
|
String workingDirectory,
|
|
|
|
Map<String, String> environment,
|
2018-06-05 06:50:40 +00:00
|
|
|
bool includeParentEnvironment = true,
|
|
|
|
bool runInShell = false,
|
|
|
|
ProcessStartMode mode = ProcessStartMode.NORMAL, // ignore: deprecated_member_use
|
2017-09-01 02:35:05 +00:00
|
|
|
}) {
|
2018-03-07 05:36:03 +00:00
|
|
|
lastPubEnvironment = environment['PUB_ENVIRONMENT'];
|
2017-12-05 22:46:39 +00:00
|
|
|
lastPubCache = environment['PUB_CACHE'];
|
2017-09-01 02:35:05 +00:00
|
|
|
return new Future<Process>.value(new MockProcess(fakeExitCode));
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
dynamic noSuchMethod(Invocation invocation) => null;
|
|
|
|
}
|
|
|
|
|
|
|
|
class MockProcess implements Process {
|
|
|
|
MockProcess(this.fakeExitCode);
|
|
|
|
|
|
|
|
final int fakeExitCode;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Stream<List<int>> get stdout => new MockStream<List<int>>();
|
|
|
|
|
|
|
|
@override
|
|
|
|
Stream<List<int>> get stderr => new MockStream<List<int>>();
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<int> get exitCode => new Future<int>.value(fakeExitCode);
|
|
|
|
|
|
|
|
@override
|
|
|
|
dynamic noSuchMethod(Invocation invocation) => null;
|
|
|
|
}
|
|
|
|
|
|
|
|
class MockStream<T> implements Stream<T> {
|
|
|
|
@override
|
|
|
|
Stream<S> transform<S>(StreamTransformer<T, S> streamTransformer) => new MockStream<S>();
|
|
|
|
|
|
|
|
@override
|
|
|
|
Stream<T> where(bool test(T event)) => new MockStream<T>();
|
|
|
|
|
|
|
|
@override
|
|
|
|
StreamSubscription<T> listen(void onData(T event), {Function onError, void onDone(), bool cancelOnError}) {
|
|
|
|
return new MockStreamSubscription<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
dynamic noSuchMethod(Invocation invocation) => null;
|
|
|
|
}
|
|
|
|
|
|
|
|
class MockStreamSubscription<T> implements StreamSubscription<T> {
|
|
|
|
@override
|
|
|
|
Future<E> asFuture<E>([E futureValue]) => new Future<E>.value();
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<Null> cancel() => null;
|
|
|
|
|
|
|
|
@override
|
|
|
|
dynamic noSuchMethod(Invocation invocation) => null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-10 21:27:53 +00:00
|
|
|
class MockFileSystem extends ForwardingFileSystem {
|
|
|
|
MockFileSystem() : super(new MemoryFileSystem());
|
|
|
|
|
2017-09-01 02:35:05 +00:00
|
|
|
@override
|
|
|
|
File file(dynamic path) {
|
|
|
|
return new MockFile();
|
|
|
|
}
|
2017-12-05 22:46:39 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
Directory directory(dynamic path) {
|
|
|
|
return new MockDirectory(path);
|
|
|
|
}
|
2017-09-01 02:35:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class MockFile implements File {
|
|
|
|
@override
|
2018-06-05 06:50:40 +00:00
|
|
|
Future<RandomAccessFile> open({FileMode mode = FileMode.READ}) async { // ignore: deprecated_member_use
|
2017-09-01 02:35:05 +00:00
|
|
|
return new MockRandomAccessFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool existsSync() => true;
|
|
|
|
|
|
|
|
@override
|
|
|
|
DateTime lastModifiedSync() => new DateTime(0);
|
|
|
|
|
|
|
|
@override
|
|
|
|
dynamic noSuchMethod(Invocation invocation) => null;
|
|
|
|
}
|
|
|
|
|
2017-12-05 22:46:39 +00:00
|
|
|
class MockDirectory implements Directory {
|
|
|
|
static bool findCache = false;
|
|
|
|
|
|
|
|
MockDirectory(this.path);
|
|
|
|
|
|
|
|
@override
|
|
|
|
final String path;
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool existsSync() => findCache && path.endsWith('.pub-cache');
|
|
|
|
|
|
|
|
@override
|
|
|
|
dynamic noSuchMethod(Invocation invocation) => null;
|
|
|
|
}
|
|
|
|
|
2017-09-01 02:35:05 +00:00
|
|
|
class MockRandomAccessFile extends Mock implements RandomAccessFile {}
|