Unverified Commit a871d591 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Apply basic log filtering and formatting to fuchsia logs. (#24143)

parent c8ccd692
// Copyright 2018 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 'context.dart';
/// The current system clock instance.
SystemClock get systemClock => context[SystemClock];
/// A class for making time based operations testable.
class SystemClock {
/// A const constructor to allow subclasses to be const.
const SystemClock();
/// Create a clock with a fixed current time.
const factory SystemClock.fixed(DateTime time) = _FixedTimeClock;
/// Retrieve the current time.
DateTime now() => DateTime.now();
/// Compute the time a given duration ago.
DateTime ago(Duration duration) {
return now().subtract(duration);
}
}
class _FixedTimeClock extends SystemClock {
const _FixedTimeClock(this._fixedTime);
final DateTime _fixedTime;
@override
DateTime now() => _fixedTime;
}
......@@ -8,7 +8,6 @@ import 'dart:math' show Random, max;
import 'package:crypto/crypto.dart';
import 'package:intl/intl.dart';
import 'package:quiver/time.dart';
import '../globals.dart';
import 'context.dart';
......@@ -251,8 +250,6 @@ Map<String, dynamic> castStringKeyedMap(dynamic untyped) {
return map.cast<String, dynamic>();
}
Clock get clock => context[Clock];
typedef AsyncCallback = Future<void> Function();
/// A [Timer] inspired class that:
......
......@@ -6,6 +6,7 @@ import 'dart:async';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/time.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
......@@ -300,7 +301,7 @@ class RunCommand extends RunCommandBase {
} catch (error) {
throwToolExit(error.toString());
}
final DateTime appStartedTime = clock.now();
final DateTime appStartedTime = systemClock.now();
final int result = await app.runner.waitForAppToFinish();
if (result != 0)
throwToolExit(null, exitCode: result);
......@@ -391,7 +392,7 @@ class RunCommand extends RunCommandBase {
final Completer<void> appStartedTimeRecorder = Completer<void>.sync();
// This callback can't throw.
appStartedTimeRecorder.future.then<void>( // ignore: unawaited_futures
(_) { appStartedTime = clock.now(); }
(_) { appStartedTime = systemClock.now(); }
);
final int result = await runner.run(
......
......@@ -4,8 +4,6 @@
import 'dart:async';
import 'package:quiver/time.dart';
import 'android/android_sdk.dart';
import 'android/android_studio.dart';
import 'android/android_workflow.dart';
......@@ -19,6 +17,7 @@ import 'base/io.dart';
import 'base/logger.dart';
import 'base/os.dart';
import 'base/platform.dart';
import 'base/time.dart';
import 'base/utils.dart';
import 'cache.dart';
import 'compile.dart';
......@@ -55,7 +54,6 @@ Future<T> runInContext<T>(
AssetBundleFactory: () => AssetBundleFactory.defaultInstance,
BotDetector: () => const BotDetector(),
Cache: () => Cache(),
Clock: () => const Clock(),
CocoaPods: () => CocoaPods(),
CocoaPodsValidator: () => const CocoaPodsValidator(),
Config: () => Config(),
......@@ -68,7 +66,7 @@ Future<T> runInContext<T>(
FuchsiaArtifacts: () => FuchsiaArtifacts(),
FuchsiaWorkflow: () => FuchsiaWorkflow(),
Flags: () => const EmptyFlags(),
FlutterVersion: () => FlutterVersion(const Clock()),
FlutterVersion: () => FlutterVersion(const SystemClock()),
GenSnapshot: () => const GenSnapshot(),
HotRunnerConfig: () => HotRunnerConfig(),
IMobileDevice: () => const IMobileDevice(),
......@@ -80,6 +78,7 @@ Future<T> runInContext<T>(
OperatingSystemUtils: () => OperatingSystemUtils(),
PlistBuddy: () => const PlistBuddy(),
SimControl: () => SimControl(),
SystemClock: () => const SystemClock(),
Stdio: () => const Stdio(),
Usage: () => Usage(),
Xcode: () => Xcode(),
......
......@@ -12,6 +12,7 @@ import '../base/io.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
import '../base/time.dart';
import '../build_info.dart';
import '../device.dart';
import '../globals.dart';
......@@ -25,23 +26,48 @@ final String _ipv6Loopback = InternetAddress.loopbackIPv6.address;
/// Read the log for a particular device.
class _FuchsiaLogReader extends DeviceLogReader {
_FuchsiaLogReader(this._device);
_FuchsiaLogReader(this._device, [this._app]);
// TODO(jonahwilliams): handle filtering log output from different modules.
static final Pattern flutterLogOutput = RegExp(r'\[\d+\.\d+\]\[\d+\]\[\d+\]\[klog\] INFO: \w+\(flutter\): ');
static final RegExp _flutterLogOutput = RegExp(r'INFO: \w+\(flutter\): ');
static final RegExp _utcDateOutput = RegExp(r'\d+\-\d+\-\d+ \d+:\d+:\d+');
FuchsiaDevice _device;
ApplicationPackage _app;
@override String get name => _device.name;
Stream<String> _logLines;
@override
Stream<String> get logLines {
_logLines ??= fuchsiaSdk.syslogs()
.where((String line) => flutterLogOutput.matchAsPrefix(line) != null);
_logLines ??= _processLogs(fuchsiaSdk.syslogs());
return _logLines;
}
Stream<String> _processLogs(Stream<String> lines) async* {
// Get the starting time of the log processor to filter logs from before
// the process attached.
final DateTime startTime = systemClock.now();
// Determine if line comes from flutter, and optionally whether it matches
// the correct fuchsia module.
final RegExp matchRegExp = _app == null
? _flutterLogOutput
: RegExp('INFO: ${_app.name}\\(flutter\\): ');
await for (String line in lines.where(matchRegExp.hasMatch)) {
// Read out the date string from the log and compare it to the current time:
// Example: 2018-11-09 01:27:45
final String rawDate = _utcDateOutput.firstMatch(line)?.group(0);
if (rawDate == null) {
continue;
}
final DateTime logTime = DateTime.parse(rawDate);
if (logTime.millisecondsSinceEpoch < startTime.millisecondsSinceEpoch) {
continue;
}
// Format log into a useful string:
yield '[${logTime.toLocal()}] Flutter: ${line.split(matchRegExp).last}';
}
}
@override
String toString() => name;
}
......@@ -152,7 +178,7 @@ class FuchsiaDevice extends Device {
Future<String> get sdkNameAndVersion async => 'Fuchsia';
@override
DeviceLogReader getLogReader({ApplicationPackage app}) => _logReader ??= _FuchsiaLogReader(this);
DeviceLogReader getLogReader({ApplicationPackage app}) => _logReader ??= _FuchsiaLogReader(this, app);
_FuchsiaLogReader _logReader;
@override
......@@ -279,6 +305,13 @@ class _FuchsiaPortForwarder extends DevicePortForwarder {
}
}
class FuchsiaModulePackage extends ApplicationPackage {
FuchsiaModulePackage({@required this.name}) : super(id: name);
@override
final String name;
}
/// Parses output from `dart.services` output on a fuchsia device.
///
/// Example output:
......
......@@ -12,7 +12,6 @@ import '../base/io.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
import '../globals.dart';
/// The [FuchsiaSdk] instance.
FuchsiaSdk get fuchsiaSdk => context[FuchsiaSdk];
......@@ -27,7 +26,7 @@ FuchsiaArtifacts get fuchsiaArtifacts => context[FuchsiaArtifacts];
class FuchsiaSdk {
static const List<String> _netaddrCommand = <String>['fx', 'netaddr', '--fuchsia', '--nowait'];
static const List<String> _netlsCommand = <String>['fx', 'netls', '--nowait'];
static const List<String> _syslogCommand = <String>['fx', 'syslog'];
static const List<String> _syslogCommand = <String>['fx', 'syslog', '--clock', 'Local'];
/// Invokes the `netaddr` command.
///
......@@ -57,12 +56,11 @@ class FuchsiaSdk {
process.kill();
});
processManager.start(_syslogCommand).then((Process newProcess) {
printTrace('Running logs');
if (controller.isClosed) {
return;
}
process = newProcess;
process.exitCode.then((_) => controller.close);
process.exitCode.whenComplete(controller.close);
controller.addStream(process.stdout.transform(utf8.decoder).transform(const LineSplitter()));
});
return controller.stream;
......
......@@ -13,6 +13,7 @@ import '../application_package.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/time.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../bundle.dart' as bundle;
......@@ -320,7 +321,7 @@ abstract class FlutterCommand extends Command<void> {
/// so that this method can record and report the overall time to analytics.
@override
Future<void> run() {
final DateTime startTime = clock.now();
final DateTime startTime = systemClock.now();
return context.run<void>(
name: 'command',
......@@ -336,7 +337,7 @@ abstract class FlutterCommand extends Command<void> {
commandResult = const FlutterCommandResult(ExitStatus.fail);
rethrow;
} finally {
final DateTime endTime = clock.now();
final DateTime endTime = systemClock.now();
printTrace('"flutter $name" took ${getElapsedAsMilliseconds(endTime.difference(startTime))}.');
// This is checking the result of the call to 'usagePath'
// (a Future<String>), and not the result of evaluating the Future.
......
......@@ -6,7 +6,6 @@ import 'dart:async';
import 'dart:convert';
import 'package:meta/meta.dart';
import 'package:quiver/time.dart';
import 'base/common.dart';
import 'base/context.dart';
......@@ -14,12 +13,13 @@ import 'base/file_system.dart';
import 'base/io.dart';
import 'base/process.dart';
import 'base/process_manager.dart';
import 'base/time.dart';
import 'cache.dart';
import 'globals.dart';
class FlutterVersion {
@visibleForTesting
FlutterVersion([this._clock = const Clock()]) {
FlutterVersion([this._clock = const SystemClock()]) {
_channel = _runGit('git rev-parse --abbrev-ref --symbolic @{u}');
final String branch = _runGit('git rev-parse --abbrev-ref HEAD');
_branch = branch == 'HEAD' ? _channel : branch;
......@@ -38,7 +38,7 @@ class FlutterVersion {
_frameworkVersion = GitTagVersion.determine().frameworkVersionFor(_frameworkRevision);
}
final Clock _clock;
final SystemClock _clock;
String _repositoryUrl;
String get repositoryUrl => _repositoryUrl;
......@@ -273,7 +273,7 @@ class FlutterVersion {
// Do not load the stamp before the above server check as it may modify the stamp file.
final VersionCheckStamp stamp = await VersionCheckStamp.load();
final DateTime lastTimeWarningWasPrinted = stamp.lastTimeWarningWasPrinted ?? _clock.agoBy(kMaxTimeSinceLastWarning * 2);
final DateTime lastTimeWarningWasPrinted = stamp.lastTimeWarningWasPrinted ?? _clock.ago(kMaxTimeSinceLastWarning * 2);
final bool beenAWhileSinceWarningWasPrinted = _clock.now().difference(lastTimeWarningWasPrinted) > kMaxTimeSinceLastWarning;
// We show a warning if either we know there is a new remote version, or we couldn't tell but the local
......
......@@ -3,8 +3,8 @@
// found in the LICENSE file.
import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:mockito/mockito.dart';
import 'package:quiver/time.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/cache.dart';
......@@ -56,7 +56,7 @@ void main() {
await runner.run(<String>['doctor']);
expect(count, 0);
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(const Clock()),
FlutterVersion: () => FlutterVersion(const SystemClock()),
Usage: () => Usage(configDirOverride: tempDir.path),
});
......@@ -75,14 +75,14 @@ void main() {
await runner.run(<String>['config']);
expect(count, 0);
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(const Clock()),
FlutterVersion: () => FlutterVersion(const SystemClock()),
Usage: () => Usage(configDirOverride: tempDir.path),
});
});
group('analytics with mocks', () {
Usage mockUsage;
Clock mockClock;
SystemClock mockClock;
Doctor mockDoctor;
List<int> mockTimes;
......@@ -110,7 +110,7 @@ void main() {
<dynamic>['flutter', 'doctor', const Duration(milliseconds: 1000), 'success']
);
}, overrides: <Type, Generator>{
Clock: () => mockClock,
SystemClock: () => mockClock,
Doctor: () => mockDoctor,
Usage: () => mockUsage,
});
......@@ -129,7 +129,7 @@ void main() {
<dynamic>['flutter', 'doctor', const Duration(milliseconds: 1000), 'warning']
);
}, overrides: <Type, Generator>{
Clock: () => mockClock,
SystemClock: () => mockClock,
Doctor: () => mockDoctor,
Usage: () => mockUsage,
});
......
......@@ -2,7 +2,16 @@
// 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 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_device.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import '../src/common.dart';
import '../src/context.dart';
......@@ -34,5 +43,102 @@ d 2 0 .
expect(ports.length, 1);
expect(ports.single, 36780);
});
group('device logs', () {
const String exampleUtcLogs = '''
[2018-11-09 01:27:45][3][297950920][log] INFO: example_app(flutter): Error doing thing
[2018-11-09 01:27:58][46257][46269][foo] INFO: Using a thing
[2018-11-09 01:29:58][46257][46269][foo] INFO: Blah blah blah
[2018-11-09 01:29:58][46257][46269][foo] INFO: other_app(flutter): Do thing
[2018-11-09 01:30:02][41175][41187][bar] INFO: Invoking a bar
[2018-11-09 01:30:12][52580][52983][log] INFO: example_app(flutter): Did thing this time
''';
final MockProcessManager mockProcessManager = MockProcessManager();
final MockProcess mockProcess = MockProcess();
Completer<int> exitCode;
StreamController<List<int>> stdout;
StreamController<List<int>> stderr;
when(mockProcessManager.start(any)).thenAnswer((Invocation _) => Future<Process>.value(mockProcess));
when(mockProcess.exitCode).thenAnswer((Invocation _) => exitCode.future);
when(mockProcess.stdout).thenAnswer((Invocation _) => stdout.stream);
when(mockProcess.stderr).thenAnswer((Invocation _) => stderr.stream);
setUp(() {
stdout = StreamController<List<int>>(sync: true);
stderr = StreamController<List<int>>(sync: true);
exitCode = Completer<int>();
});
tearDown(() {
exitCode.complete(0);
});
testUsingContext('can be parsed for an app', () async {
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final DeviceLogReader reader = device.getLogReader(app: FuchsiaModulePackage(name: 'example_app'));
final List<String> logLines = <String>[];
reader.logLines.listen(logLines.add);
expect(logLines, isEmpty);
stdout.add(utf8.encode(exampleUtcLogs));
await stdout.close();
expect(logLines, <String>[
'[2018-11-09 01:27:45.000] Flutter: Error doing thing',
'[2018-11-09 01:30:12.000] Flutter: Did thing this time',
]);
}, overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 25, 45)),
});
testUsingContext('cuts off prior logs', () async {
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final DeviceLogReader reader = device.getLogReader(app: FuchsiaModulePackage(name: 'example_app'));
final List<String> logLines = <String>[];
final Completer<void> lock = Completer<void>();
reader.logLines.listen((String line) {
logLines.add(line);
lock.complete();
});
expect(logLines, isEmpty);
stdout.add(utf8.encode(exampleUtcLogs));
await stdout.close();
await lock.future;
expect(logLines, <String>[
'[2018-11-09 01:30:12.000] Flutter: Did thing this time',
]);
}, overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 29, 45)),
});
testUsingContext('can be parsed for all apps', () async {
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final DeviceLogReader reader = device.getLogReader();
final List<String> logLines = <String>[];
reader.logLines.listen(logLines.add);
expect(logLines, isEmpty);
stdout.add(utf8.encode(exampleUtcLogs));
await stdout.close();
expect(logLines, <String>[
'[2018-11-09 01:27:45.000] Flutter: Error doing thing',
'[2018-11-09 01:29:58.000] Flutter: Do thing',
'[2018-11-09 01:30:12.000] Flutter: Did thing this time',
]);
}, overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 25, 45)),
});
});
});
}
class MockProcessManager extends Mock implements ProcessManager {}
class MockProcess extends Mock implements Process {}
......@@ -5,15 +5,14 @@
import 'dart:async';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/usage.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:mockito/mockito.dart';
import 'package:quiver/time.dart';
import '../src/common.dart';
import '../src/context.dart';
void main() {
group('Flutter Command', () {
......@@ -67,7 +66,7 @@ void main() {
);
},
overrides: <Type, Generator>{
Clock: () => clock,
SystemClock: () => clock,
Usage: () => usage,
});
......@@ -84,7 +83,7 @@ void main() {
label: anyNamed('label')));
},
overrides: <Type, Generator>{
Clock: () => clock,
SystemClock: () => clock,
Usage: () => usage,
});
......@@ -117,7 +116,7 @@ void main() {
);
},
overrides: <Type, Generator>{
Clock: () => clock,
SystemClock: () => clock,
Usage: () => usage,
});
......@@ -153,7 +152,7 @@ void main() {
}
},
overrides: <Type, Generator>{
Clock: () => clock,
SystemClock: () => clock,
Usage: () => usage,
});
......
......@@ -19,11 +19,11 @@ import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/ios/simulators.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/usage.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:quiver/time.dart';
import 'common.dart';
......@@ -300,7 +300,7 @@ class MockXcodeProjectInterpreter implements XcodeProjectInterpreter {
class MockFlutterVersion extends Mock implements FlutterVersion {}
class MockClock extends Mock implements Clock {}
class MockClock extends Mock implements SystemClock {}
class MockHttpClient extends Mock implements HttpClient {}
......
// Copyright 2018 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 'package:flutter_tools/src/base/time.dart';
import 'src/common.dart';
void main() {
group(SystemClock, () {
test('can set a fixed time', () {
final SystemClock clock = SystemClock.fixed(DateTime(1991, 8, 23));
expect(clock.now(), DateTime(1991, 8, 23));
});
test('can find a time ago', () {
final SystemClock clock = SystemClock.fixed(DateTime(1991, 8, 23));
expect(clock.ago(Duration(days: 10)), DateTime(1991, 8, 13));
});
});
}
......@@ -5,9 +5,9 @@
import 'dart:convert';
import 'package:collection/collection.dart' show ListEquality;
import 'package:flutter_tools/src/base/time.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:quiver/time.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/io.dart';
......@@ -18,11 +18,11 @@ import 'package:flutter_tools/src/version.dart';
import 'src/common.dart';
import 'src/context.dart';
final Clock _testClock = Clock.fixed(DateTime(2015, 1, 1));
final DateTime _upToDateVersion = _testClock.agoBy(FlutterVersion.kVersionAgeConsideredUpToDate ~/ 2);
final DateTime _outOfDateVersion = _testClock.agoBy(FlutterVersion.kVersionAgeConsideredUpToDate * 2);
final DateTime _stampUpToDate = _testClock.agoBy(FlutterVersion.kCheckAgeConsideredUpToDate ~/ 2);
final DateTime _stampOutOfDate = _testClock.agoBy(FlutterVersion.kCheckAgeConsideredUpToDate * 2);
final SystemClock _testClock = SystemClock.fixed(DateTime(2015, 1, 1));
final DateTime _upToDateVersion = _testClock.ago(FlutterVersion.kVersionAgeConsideredUpToDate ~/ 2);
final DateTime _outOfDateVersion = _testClock.ago(FlutterVersion.kVersionAgeConsideredUpToDate * 2);
final DateTime _stampUpToDate = _testClock.ago(FlutterVersion.kCheckAgeConsideredUpToDate ~/ 2);
final DateTime _stampOutOfDate = _testClock.ago(FlutterVersion.kCheckAgeConsideredUpToDate * 2);
void main() {
MockProcessManager mockProcessManager;
......@@ -161,7 +161,7 @@ void main() {
localCommitDate: _outOfDateVersion,
stamp: VersionCheckStamp(
lastTimeVersionWasChecked: _stampOutOfDate,
lastKnownRemoteVersion: _testClock.ago(days: 2),
lastKnownRemoteVersion: _testClock.ago(const Duration(days: 2)),
),
remoteCommitDate: _upToDateVersion,
expectSetStamp: true,
......@@ -287,15 +287,15 @@ void main() {
testUsingContext('loads valid JSON', () async {
fakeData(mockProcessManager, mockCache, stampJson: '''
{
"lastKnownRemoteVersion": "${_testClock.ago(days: 1)}",
"lastTimeVersionWasChecked": "${_testClock.ago(days: 2)}",
"lastKnownRemoteVersion": "${_testClock.ago(const Duration(days: 1))}",
"lastTimeVersionWasChecked": "${_testClock.ago(const Duration(days: 2))}",
"lastTimeWarningWasPrinted": "${_testClock.now()}"
}
''');
final VersionCheckStamp stamp = await VersionCheckStamp.load();
expect(stamp.lastKnownRemoteVersion, _testClock.ago(days: 1));
expect(stamp.lastTimeVersionWasChecked, _testClock.ago(days: 2));
expect(stamp.lastKnownRemoteVersion, _testClock.ago(const Duration(days: 1)));
expect(stamp.lastTimeVersionWasChecked, _testClock.ago(const Duration(days: 2)));
expect(stamp.lastTimeWarningWasPrinted, _testClock.now());
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(_testClock),
......@@ -309,15 +309,15 @@ void main() {
_expectDefault(await VersionCheckStamp.load());
final VersionCheckStamp stamp = VersionCheckStamp(
lastKnownRemoteVersion: _testClock.ago(days: 1),
lastTimeVersionWasChecked: _testClock.ago(days: 2),
lastKnownRemoteVersion: _testClock.ago(const Duration(days: 1)),
lastTimeVersionWasChecked: _testClock.ago(const Duration(days: 2)),
lastTimeWarningWasPrinted: _testClock.now(),
);
await stamp.store();
final VersionCheckStamp storedStamp = await VersionCheckStamp.load();
expect(storedStamp.lastKnownRemoteVersion, _testClock.ago(days: 1));
expect(storedStamp.lastTimeVersionWasChecked, _testClock.ago(days: 2));
expect(storedStamp.lastKnownRemoteVersion, _testClock.ago(const Duration(days: 1)));
expect(storedStamp.lastTimeVersionWasChecked, _testClock.ago(const Duration(days: 2)));
expect(storedStamp.lastTimeWarningWasPrinted, _testClock.now());
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(_testClock),
......@@ -331,19 +331,19 @@ void main() {
_expectDefault(await VersionCheckStamp.load());
final VersionCheckStamp stamp = VersionCheckStamp(
lastKnownRemoteVersion: _testClock.ago(days: 10),
lastTimeVersionWasChecked: _testClock.ago(days: 9),
lastTimeWarningWasPrinted: _testClock.ago(days: 8),
lastKnownRemoteVersion: _testClock.ago(const Duration(days: 10)),
lastTimeVersionWasChecked: _testClock.ago(const Duration(days: 9)),
lastTimeWarningWasPrinted: _testClock.ago(const Duration(days: 8)),
);
await stamp.store(
newKnownRemoteVersion: _testClock.ago(days: 1),
newTimeVersionWasChecked: _testClock.ago(days: 2),
newKnownRemoteVersion: _testClock.ago(const Duration(days: 1)),
newTimeVersionWasChecked: _testClock.ago(const Duration(days: 2)),
newTimeWarningWasPrinted: _testClock.now(),
);
final VersionCheckStamp storedStamp = await VersionCheckStamp.load();
expect(storedStamp.lastKnownRemoteVersion, _testClock.ago(days: 1));
expect(storedStamp.lastTimeVersionWasChecked, _testClock.ago(days: 2));
expect(storedStamp.lastKnownRemoteVersion, _testClock.ago(const Duration(days: 1)));
expect(storedStamp.lastTimeVersionWasChecked, _testClock.ago(const Duration(days: 2)));
expect(storedStamp.lastTimeWarningWasPrinted, _testClock.now());
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(_testClock),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment