Enable avoid_print lint. (#91332)

This commit is contained in:
Ian Hickson 2021-10-07 09:53:03 -07:00 committed by GitHub
parent 3c6c2aa50a
commit cb378edc9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
85 changed files with 359 additions and 246 deletions

View file

@ -71,8 +71,8 @@ linter:
- avoid_init_to_null
# - avoid_js_rounded_ints # only useful when targeting JS runtime
- avoid_null_checks_in_equality_operators
# - avoid_positional_boolean_parameters # not yet tested
# - avoid_print # not yet tested
# - avoid_positional_boolean_parameters # would have been nice to enable this but by now there's too many places that break it
- avoid_print
# - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
# - avoid_redundant_argument_values # not yet tested
- avoid_relative_lib_imports

View file

@ -0,0 +1,5 @@
include: ../analysis_options.yaml
linter:
rules:
avoid_print: false # We use prints as debugging tools here all the time.

View file

@ -0,0 +1,7 @@
[0-9]+:[0-9]+ [+]0: Local passes non-existent baseline for new test, null expectation *
*No expectations provided by Skia Gold for test: library.flutter.new_golden_test.1. This may be a new test. If this is an unexpected result, check https://flutter-gold.skia.org.
*Validate image output found at flutter/test/library/
[0-9]+:[0-9]+ [+]0 ~1: Local passes non-existent baseline for new test, empty expectation *
*No expectations provided by Skia Gold for test: library.flutter.new_golden_test.2. This may be a new test. If this is an unexpected result, check https://flutter-gold.skia.org.
*Validate image output found at flutter/test/library/
[0-9]+:[0-9]+ [+]0 ~2: All tests skipped. *

View file

@ -0,0 +1,77 @@
// 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.
// See also packages/flutter_goldens/test/flutter_goldens_test.dart
import 'dart:typed_data';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_goldens/flutter_goldens.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform/platform.dart';
// 1x1 colored pixel
const List<int> _kFailPngBytes = <int>[137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0,
13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137,
0, 0, 0, 13, 73, 68, 65, 84, 120, 1, 99, 249, 207, 240, 255, 63, 0, 7, 18, 3,
2, 164, 147, 160, 197, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130];
void main() {
final MemoryFileSystem fs = MemoryFileSystem();
final Directory basedir = fs.directory('flutter/test/library/')
..createSync(recursive: true);
final FakeSkiaGoldClient fakeSkiaClient = FakeSkiaGoldClient()
..expectationForTestValues['flutter.new_golden_test.1'] = '';
final FlutterLocalFileComparator comparator = FlutterLocalFileComparator(
basedir.uri,
fakeSkiaClient,
fs: fs,
platform: FakePlatform(
environment: <String, String>{'FLUTTER_ROOT': '/flutter'},
operatingSystem: 'macos'
),
);
test('Local passes non-existent baseline for new test, null expectation', () async {
expect(
await comparator.compare(
Uint8List.fromList(_kFailPngBytes),
Uri.parse('flutter.new_golden_test.1'),
),
isTrue,
);
});
test('Local passes non-existent baseline for new test, empty expectation', () async {
expect(
await comparator.compare(
Uint8List.fromList(_kFailPngBytes),
Uri.parse('flutter.new_golden_test.2'),
),
isTrue,
);
});
}
// See also packages/flutter_goldens/test/flutter_goldens_test.dart
class FakeSkiaGoldClient extends Fake implements SkiaGoldClient {
Map<String, String> expectationForTestValues = <String, String>{};
Object? getExpectationForTestThrowable;
@override
Future<String> getExpectationForTest(String testName) async {
if (getExpectationForTestThrowable != null) {
throw getExpectationForTestThrowable!;
}
return expectationForTestValues[testName] ?? '';
}
Map<String, List<int>> imageBytesValues = <String, List<int>>{};
@override
Future<List<int>> getImageBytes(String imageHash) async => imageBytesValues[imageHash]!;
Map<String, String> cleanTestNameValues = <String, String>{};
@override
String cleanTestName(String fileName) => cleanTestNameValues[fileName] ?? '';
}

View file

@ -8,5 +8,5 @@ import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
void main() {
test('working directory is the root of this package', () {
expect(Directory.current.path, endsWith('automated_tests'));
});
});
}

View file

@ -8,6 +8,8 @@ dependencies:
sdk: flutter
flutter_test:
sdk: flutter
flutter_goldens:
sdk: flutter
integration_test:
sdk: flutter
test: 1.17.12

View file

@ -1,12 +1,10 @@
# Use the analysis options settings from the top level of the repo (not
# the ones from above, which include the `public_member_api_docs` rule).
include: ../../../analysis_options.yaml
include: ../../analysis_options.yaml
analyzer:
exclude:
# Ignore protoc generated files
# Ignore protoc generated files
- "lib/src/proto/*"
linter:
rules:
avoid_catches_without_on_clauses: true

View file

@ -1,7 +1,4 @@
# Use the analysis options settings from the top level of the repo (not
# the ones from above, which include the `public_member_api_docs` rule).
include: ../../../analysis_options.yaml
include: ../../analysis_options.yaml
linter:
rules:

View file

@ -1,4 +1,4 @@
include: ../../analysis_options.yaml
include: ../analysis_options.yaml
linter:
rules:

View file

@ -1,7 +1,4 @@
# Take our settings from the repo's main analysis_options.yaml file, but add
# an exclude for the build directory.
include: ../../../analysis_options.yaml
include: ../../analysis_options.yaml
analyzer:
exclude:

View file

@ -47,7 +47,7 @@ class AutocompleteBasicExample extends StatelessWidget {
});
},
onSelected: (String selection) {
print('You just selected $selection');
debugPrint('You just selected $selection');
},
);
}

View file

@ -79,7 +79,7 @@ class AutocompleteBasicUserExample extends StatelessWidget {
});
},
onSelected: (User selection) {
print('You just selected ${_displayStringForOption(selection)}');
debugPrint('You just selected ${_displayStringForOption(selection)}');
},
);
}

View file

@ -35,7 +35,7 @@ class MyStatelessWidget extends StatelessWidget {
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
debugPrint('Card tapped.');
},
child: const SizedBox(
width: 300,

View file

@ -59,7 +59,7 @@ class LinkedLabelCheckbox extends StatelessWidget {
),
recognizer: TapGestureRecognizer()
..onTap = () {
print('Label has been tapped.');
debugPrint('Label has been tapped.');
},
),
),

View file

@ -45,7 +45,7 @@ class MyStatelessWidget extends StatelessWidget {
),
floatingActionButton: FloatingActionButton(
onPressed: () {
print('FAB pressed.');
debugPrint('FAB pressed.');
},
tooltip: 'Increment',
child: const Icon(Icons.add),

View file

@ -34,7 +34,7 @@ class MyStatelessWidget extends StatelessWidget {
Widget build(BuildContext context) {
return OutlinedButton(
onPressed: () {
print('Received click');
debugPrint('Received click');
},
child: const Text('Click Me'),
);

View file

@ -64,7 +64,7 @@ class LinkedLabelRadio extends StatelessWidget {
),
recognizer: TapGestureRecognizer()
..onTap = () {
print('Label has been tapped.');
debugPrint('Label has been tapped.');
},
),
),

View file

@ -59,7 +59,7 @@ class LinkedLabelSwitch extends StatelessWidget {
),
recognizer: TapGestureRecognizer()
..onTap = () {
print('Label has been tapped.');
debugPrint('Label has been tapped.');
},
),
),

View file

@ -54,7 +54,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
constraints: BoxConstraints.tight(const Size(200, 50)),
child: TextFormField(
onSaved: (String? value) {
print('Value for field $index saved as "$value"');
debugPrint('Value for field $index saved as "$value"');
},
),
),

View file

@ -92,13 +92,13 @@ class MyAction extends Action<MyIntent> {
@override
void addActionListener(ActionListenerCallback listener) {
super.addActionListener(listener);
print('Action Listener was added');
debugPrint('Action Listener was added');
}
@override
void removeActionListener(ActionListenerCallback listener) {
super.removeActionListener(listener);
print('Action Listener was removed');
debugPrint('Action Listener was removed');
}
@override

View file

@ -34,7 +34,7 @@ class Model {
int save() {
if (isDirty.value) {
print('Saved Data: ${data.value}');
debugPrint('Saved Data: ${data.value}');
isDirty.value = false;
}
return data.value;

View file

@ -57,21 +57,21 @@ class _ColorfulButtonState extends State<ColorfulButton> {
KeyEventResult _handleKeyPress(FocusNode node, RawKeyEvent event) {
if (event is RawKeyDownEvent) {
print('Focus node ${node.debugLabel} got key event: ${event.logicalKey}');
debugPrint('Focus node ${node.debugLabel} got key event: ${event.logicalKey}');
if (event.logicalKey == LogicalKeyboardKey.keyR) {
print('Changing color to red.');
debugPrint('Changing color to red.');
setState(() {
_color = Colors.red;
});
return KeyEventResult.handled;
} else if (event.logicalKey == LogicalKeyboardKey.keyG) {
print('Changing color to green.');
debugPrint('Changing color to green.');
setState(() {
_color = Colors.green;
});
return KeyEventResult.handled;
} else if (event.logicalKey == LogicalKeyboardKey.keyB) {
print('Changing color to blue.');
debugPrint('Changing color to blue.');
setState(() {
_color = Colors.blue;
});

View file

@ -38,21 +38,21 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
KeyEventResult _handleKeyPress(FocusNode node, RawKeyEvent event) {
if (event is RawKeyDownEvent) {
print('Focus node ${node.debugLabel} got key event: ${event.logicalKey}');
debugPrint('Focus node ${node.debugLabel} got key event: ${event.logicalKey}');
if (event.logicalKey == LogicalKeyboardKey.keyR) {
print('Changing color to red.');
debugPrint('Changing color to red.');
setState(() {
_color = Colors.red;
});
return KeyEventResult.handled;
} else if (event.logicalKey == LogicalKeyboardKey.keyG) {
print('Changing color to green.');
debugPrint('Changing color to green.');
setState(() {
_color = Colors.green;
});
return KeyEventResult.handled;
} else if (event.logicalKey == LogicalKeyboardKey.keyB) {
print('Changing color to blue.');
debugPrint('Changing color to blue.');
setState(() {
_color = Colors.blue;
});

View file

@ -115,7 +115,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
// This button would be not visible, but still focusable from
// the foreground pane without the FocusScope.
ElevatedButton(
onPressed: () => print('You pressed the other button!'),
onPressed: () => debugPrint('You pressed the other button!'),
child: const Text('ANOTHER BUTTON TO FOCUS'),
),
DefaultTextStyle(

View file

@ -68,7 +68,7 @@ class _OrderedButtonState<T> extends State<OrderedButton<T>> {
void _handleOnPressed() {
focusNode.requestFocus();
print('Button ${widget.name} pressed.');
debugPrint('Button ${widget.name} pressed.');
debugDumpFocusTree();
}

View file

@ -40,7 +40,7 @@ class DemoButton extends StatelessWidget {
final double order;
void _handleOnPressed() {
print('Button $name pressed.');
debugPrint('Button $name pressed.');
debugDumpFocusTree();
}

View file

@ -122,10 +122,10 @@ class _IVBuilderExampleState extends State<_IVBuilderExample> {
cellWidth: _cellWidth,
builder: (BuildContext context, int row, int column) {
if (!_isCellVisible(row, column, viewport)) {
print('removing cell ($row, $column)');
debugPrint('removing cell ($row, $column)');
return Container(height: _cellHeight);
}
print('building cell ($row, $column)');
debugPrint('building cell ($row, $column)');
return Container(
height: _cellHeight,
color: row % 2 + column % 2 == 1

View file

@ -45,9 +45,9 @@ class MyStatelessWidget extends StatelessWidget {
body: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollNotification) {
if (scrollNotification is ScrollStartNotification) {
print('Scrolling has started');
debugPrint('Scrolling has started');
} else if (scrollNotification is ScrollEndNotification) {
print('Scrolling has ended');
debugPrint('Scrolling has ended');
}
// Return true to cancel the notification bubbling.
return true;

View file

@ -98,7 +98,7 @@ Future<void> main() async {
final HttpServer httpServer =
await HttpServer.bindSecure('localhost', 0, serverContext);
final int port = httpServer.port;
print('Listening on port $port.');
debugPrint('Listening on port $port.');
// Initializes bindings before using any platform channels.
WidgetsFlutterBinding.ensureInitialized();
@ -193,7 +193,7 @@ class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
).toList();
final DateTime started = DateTime.now();
Future.wait(futures).then((_) {
print(
debugPrint(
'===image_list=== all loaded in ${DateTime.now().difference(started).inMilliseconds}ms.',
);
});

View file

@ -47,8 +47,8 @@ class Calculator {
final int n = result.length;
onResultListener('Decoded $n results');
} catch (e, stack) {
print('Invalid JSON file: $e');
print(stack);
debugPrint('Invalid JSON file: $e');
debugPrint('$stack');
}
}

View file

@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file implements debugPrint in terms of print, so avoiding
// calling "print" is sort of a non-starter here...
// ignore_for_file: avoid_print
import 'dart:async';
import 'dart:collection';

View file

@ -42,6 +42,7 @@ class FakeTextChannel implements MethodChannel {
void validateOutgoingMethodCalls(List<MethodCall> calls) {
expect(outgoingCalls.length, calls.length);
final StringBuffer output = StringBuffer();
bool hasError = false;
for (int i = 0; i < calls.length; i++) {
final ByteData outgoingData = codec.encodeMethodCall(outgoingCalls[i]);
@ -50,7 +51,7 @@ class FakeTextChannel implements MethodChannel {
final String expectedString = utf8.decode(expectedData.buffer.asUint8List());
if (outgoingString != expectedString) {
print(
output.writeln(
'Index $i did not match:\n'
' actual: $outgoingString\n'
' expected: $expectedString',
@ -59,7 +60,7 @@ class FakeTextChannel implements MethodChannel {
}
}
if (hasError) {
fail('Calls did not match.');
fail('Calls did not match:\n$output');
}
}
}

View file

@ -26,7 +26,7 @@ void checkTree(WidgetTester tester, List<BoxDecoration> expectedDecorations) {
}
expect(child, isNull);
} catch (e) {
print(renderObject.toStringDeep());
debugPrint(renderObject.toStringDeep());
rethrow;
}
}

View file

@ -41,7 +41,7 @@ void checkTree(WidgetTester tester, List<TestParentData> expectedParentData) {
}
expect(child, isNull);
} catch (e) {
print(renderObject.toStringDeep());
debugPrint(renderObject.toStringDeep());
rethrow;
}
}

View file

@ -0,0 +1,5 @@
include: ../analysis_options.yaml
linter:
rules:
avoid_print: false # This is a CLI tool, so printing to the console is fine.

View file

@ -50,7 +50,7 @@ class VMServiceFlutterDriver extends FlutterDriver {
// TODO(awdavies): Use something other than print. On fuchsia
// `stderr`/`stdout` appear to have issues working correctly.
driverLog = (String source, String message) {
print('$source: $message');
print('$source: $message'); // ignore: avoid_print
};
fuchsiaModuleTarget ??= Platform.environment['FUCHSIA_MODULE_TARGET'];
if (fuchsiaModuleTarget == null) {

View file

@ -222,11 +222,7 @@ class WebFlutterDriver extends FlutterDriver {
class FlutterWebConnection {
/// Creates a FlutterWebConnection with WebDriver
/// and whether the WebDriver supports timeline action.
FlutterWebConnection(this._driver, this.supportsTimelineAction) {
_driver.logs.get(async_io.LogType.browser).listen((async_io.LogEntry entry) {
print('[${entry.level}]: ${entry.message}');
});
}
FlutterWebConnection(this._driver, this.supportsTimelineAction);
final async_io.WebDriver _driver;

View file

@ -20,7 +20,7 @@ void tryToDelete(Directory directory) {
try {
directory.deleteSync(recursive: true);
} on FileSystemException catch (error) {
print('Failed to delete ${directory.path}: $error');
driverLog('test', 'Failed to delete ${directory.path}: $error');
}
}

View file

@ -385,9 +385,7 @@ class FlutterSkippingFileComparator extends FlutterGoldenFileComparator {
@override
Future<bool> compare(Uint8List imageBytes, Uri golden) async {
print(
'Skipping "$golden" test : $reason'
);
markTestSkipped('Skipping "$golden" test: $reason');
return true;
}
@ -502,8 +500,9 @@ class FlutterLocalFileComparator extends FlutterGoldenFileComparator with LocalC
testExpectation = await skiaClient.getExpectationForTest(testName);
if (testExpectation == null || testExpectation.isEmpty) {
// There is no baseline for this test
print('No expectations provided by Skia Gold for test: $golden. '
// There is no baseline for this test.
markTestSkipped(
'No expectations provided by Skia Gold for test: $golden. '
'This may be a new test. If this is an unexpected result, check '
'https://flutter-gold.skia.org.\n'
'Validate image output found at $basedir'

View file

@ -8,18 +8,19 @@
// Fails with "flutter test --test-randomize-ordering-seed=123"
@Tags(<String>['no-shuffle'])
// See also dev/automated_tests/flutter_test/flutter_gold_test.dart
import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'dart:io' hide Directory;
import 'dart:typed_data';
import 'dart:ui' show hashValues, hashList;
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_goldens/flutter_goldens.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';
@ -41,17 +42,6 @@ const List<int> _kFailPngBytes =
120, 1, 99, 249, 207, 240, 255, 63, 0, 7, 18, 3, 2, 164, 147, 160, 197, 0,
0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130];
Future<void> testWithOutput(String name, Future<void> Function() body, String expectedOutput) async {
test(name, () async {
final StringBuffer output = StringBuffer();
void _recordPrint(Zone self, ZoneDelegate parent, Zone zone, String line) {
output.write(line);
}
await runZoned<Future<void>>(body, zoneSpecification: ZoneSpecification(print: _recordPrint));
expect(output.toString(), expectedOutput);
});
}
void main() {
late MemoryFileSystem fs;
late FakePlatform platform;
@ -569,7 +559,6 @@ void main() {
const String hash = '55109a4bed52acc780530f7a9aeff6c0';
fakeSkiaClient.expectationForTestValues['flutter.golden_test.1'] = hash;
fakeSkiaClient.expectationForTestValues['flutter.new_golden_test.1'] = '';
fakeSkiaClient.imageBytesValues[hash] =_kTestPngBytes;
fakeSkiaClient.cleanTestNameValues['library.flutter.golden_test.1.png'] = 'flutter.golden_test.1';
});
@ -584,32 +573,6 @@ void main() {
);
});
testWithOutput('passes non-existent baseline for new test, null expectation', () async {
expect(
await comparator.compare(
Uint8List.fromList(_kFailPngBytes),
Uri.parse('flutter.new_golden_test.1'),
),
isTrue,
);
}, 'No expectations provided by Skia Gold for test: library.flutter.new_golden_test.1. '
'This may be a new test. If this is an unexpected result, check https://flutter-gold.skia.org.\n'
'Validate image output found at flutter/test/library/'
);
testWithOutput('passes non-existent baseline for new test, empty expectation', () async {
expect(
await comparator.compare(
Uint8List.fromList(_kFailPngBytes),
Uri.parse('flutter.new_golden_test.2'),
),
isTrue,
);
}, 'No expectations provided by Skia Gold for test: library.flutter.new_golden_test.2. '
'This may be a new test. If this is an unexpected result, check https://flutter-gold.skia.org.\n'
'Validate image output found at flutter/test/library/'
);
test('compare properly awaits validation & output before failing.', () async {
final Completer<bool> completer = Completer<bool>();
final Future<bool> result = comparator.compare(
@ -713,14 +676,14 @@ class FakeProcessManager extends Fake implements ProcessManager {
workingDirectories.add(workingDirectory);
final ProcessResult? result = processResults[RunInvocation(command.cast<String>(), workingDirectory)];
if (result == null && fallbackProcessResult == null) {
// Throwing here might gobble up the exception message if a test fails.
print('ProcessManager.run was called with $command ($workingDirectory) unexpectedly - $processResults.');
printOnFailure('ProcessManager.run was called with $command ($workingDirectory) unexpectedly - $processResults.');
fail('See above.');
}
return result ?? fallbackProcessResult!;
}
}
// See also dev/automated_tests/flutter_test/flutter_gold_test.dart
class FakeSkiaGoldClient extends Fake implements SkiaGoldClient {
Map<String, String> expectationForTestValues = <String, String>{};
Object? getExpectationForTestThrowable;

View file

@ -183,9 +183,10 @@ class SkiaGoldClient {
if (result.exitCode != 0) {
// We do not want to throw for non-zero exit codes here, as an intentional
// change or new golden file test expect non-zero exit codes. Logging here
// is meant to inform when an unexpected result occurs.
print('goldctl imgtest add stdout: ${result.stdout}');
print('goldctl imgtest add stderr: ${result.stderr}');
// is meant to help debugging in CI when an unexpected result occurs.
// See also: https://github.com/flutter/flutter/issues/91285
print('goldctl imgtest add stdout: ${result.stdout}'); // ignore: avoid_print
print('goldctl imgtest add stderr: ${result.stderr}'); // ignore: avoid_print
}
return true;
@ -301,7 +302,10 @@ class SkiaGoldClient {
throw const FormatException('Skia gold expectations do not match expected format.');
expectation = jsonResponse['digest'] as String?;
} on FormatException catch (error) {
print(
// Ideally we'd use something like package:test's printOnError, but best reliabilty
// in getting logs on CI for now we're just using print.
// See also: https://github.com/flutter/flutter/issues/91285
print( // ignore: avoid_print
'Formatting error detected requesting expectations from Flutter Gold.\n'
'error: $error\n'
'url: $requestForExpectations\n'

View file

@ -6,6 +6,8 @@ import 'dart:typed_data';
import 'dart:ui';
import 'package:path/path.dart' as path;
import 'package:test_api/test_api.dart'; // ignore: deprecated_member_use
import '_goldens_io.dart' if (dart.library.html) '_goldens_web.dart' as _goldens;
/// Compares image pixels against a golden image file.
@ -268,7 +270,7 @@ class TrivialComparator implements GoldenFileComparator {
@override
Future<bool> compare(Uint8List imageBytes, Uri golden) {
print('Golden file comparison requested for "$golden"; skipping...');
markTestSkipped('Golden file comparison requested for "$golden"; skipping...');
return Future<bool>.value(true);
}
@ -288,7 +290,7 @@ class _TrivialWebGoldenComparator implements WebGoldenComparator {
@override
Future<bool> compare(double width, double height, Uri golden) {
print('Golden comparison requested for "$golden"; skipping...');
markTestSkipped('Golden comparison requested for "$golden"; skipping...');
return Future<bool>.value(true);
}

View file

@ -96,7 +96,7 @@ Future<void> _runLiveTest(Suite suiteConfig, LiveTest liveTest, _Reporter report
Future<void> _runSkippedTest(Suite suiteConfig, Test test, List<Group> parents, _Reporter reporter) async {
final LocalTest skipped = LocalTest(test.name, test.metadata, () { }, trace: test.trace);
if (skipped.metadata.skipReason != null) {
print('Skip: ${skipped.metadata.skipReason}');
reporter.log('Skip: ${skipped.metadata.skipReason}');
}
final LiveTest liveTest = skipped.load(suiteConfig);
reporter._onTestStarted(liveTest);
@ -334,7 +334,7 @@ class _Reporter {
if (message.type == MessageType.skip) {
text = ' $_yellow$text$_noColor';
}
print(text);
log(text);
}));
}
@ -351,8 +351,8 @@ class _Reporter {
return;
}
_progressLine(_description(liveTest), suffix: ' $_bold$_red[E]$_noColor');
print(_indent(error.toString()));
print(_indent('$stackTrace'));
log(_indent(error.toString()));
log(_indent('$stackTrace'));
}
/// A callback called when the engine is finished running tests.
@ -421,7 +421,7 @@ class _Reporter {
buffer.write(message);
buffer.write(_noColor);
print(buffer.toString());
log(buffer.toString());
}
/// Returns a representation of [duration] as `MM:SS`.
@ -442,6 +442,13 @@ class _Reporter {
}
return name;
}
/// Print the message to the console.
void log(String message) {
// We centralize all the prints in this file through this one method so that
// in principle we can reroute the output easily should we need to.
print(message); // ignore: avoid_print
}
}
String _indent(String string, { int? size, String? first }) {

View file

@ -416,7 +416,7 @@ Future<void> benchmarkWidgets(
assert(() {
if (mayRunWithAsserts)
return true;
print(kDebugWarning);
debugPrint(kDebugWarning);
return true;
}());
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;

View file

@ -1,12 +1,11 @@
# Use the analysis options settings from the top level of the repo (not
# the ones from above, which include the `public_member_api_docs` rule).
include: ../../analysis_options.yaml
include: ../analysis_options.yaml
linter:
rules:
avoid_catches_without_on_clauses: true
curly_braces_in_flow_control_structures: true
library_private_types_in_public_api: false # Tool does not have any public API
library_private_types_in_public_api: false # Tool does not have any public API.
no_runtimeType_toString: false # We use runtimeType for debugging in the tool.
prefer_relative_imports: true
public_member_api_docs: false # Tool does not have any public API.
unawaited_futures: true

View file

@ -0,0 +1,5 @@
include: ../analysis_options.yaml
linter:
rules:
avoid_print: false # These are CLI tools which print as a matter of course.

View file

@ -25,6 +25,12 @@
/// about any additional exports that you add to this file, as doing so will
/// increase the API surface that we have to test in Flutter tools, and the APIs
/// in `dart:io` can sometimes be hard to use in tests.
// We allow `print()` in this file as a fallback for writing to the terminal via
// regular stdout/stderr/stdio paths. Everything else in the flutter_tools
// library should route terminal I/O through the [Stdio] class defined below.
// ignore_for_file: avoid_print
import 'dart:async';
import 'dart:io' as io
show

View file

@ -247,6 +247,7 @@ class Cache {
}
} on Exception catch (error) {
// There is currently no logger attached since this is computed at startup.
// ignore: avoid_print
print(userMessages.runnerNoRoot('$error'));
}
return normalize('.');

View file

@ -307,6 +307,7 @@ class DaemonDomain extends Domain {
if (message.level == 'status') {
// We use `print()` here instead of `stdout.writeln()` in order to
// capture the print output for testing.
// ignore: avoid_print
print(message.message);
} else if (message.level == 'error') {
globals.stdio.stderrWrite('${message.message}\n');

View file

@ -96,7 +96,7 @@ class MacOSDevice extends DesktopDevice {
'open', package.applicationBundle(buildMode),
]).then((ProcessResult result) {
if (result.exitCode != 0) {
print('Failed to foreground app; open returned ${result.exitCode}');
_logger.printError('Failed to foreground app; open returned ${result.exitCode}');
}
});
}

View file

@ -2668,10 +2668,9 @@ Future<void> _ensureFlutterToolsSnapshot() async {
'../../bin/cache/dart-sdk/bin/dart',
snapshotArgs,
);
if (snapshotResult.exitCode != 0) {
print(snapshotResult.stdout);
print(snapshotResult.stderr);
}
printOnFailure('Results of generating snapshot:');
printOnFailure(snapshotResult.stdout.toString());
printOnFailure(snapshotResult.stderr.toString());
expect(snapshotResult.exitCode, 0);
}
@ -2713,10 +2712,9 @@ Future<void> _analyzeProject(String workingDir, { List<String> expectedFailures
workingDirectory: workingDir,
);
if (expectedFailures.isEmpty) {
if (exec.exitCode != 0) {
print(exec.stdout);
print(exec.stderr);
}
printOnFailure('Results of running analyzer:');
printOnFailure(exec.stdout.toString());
printOnFailure(exec.stderr.toString());
expect(exec.exitCode, 0);
return;
}
@ -2770,10 +2768,9 @@ Future<void> _runFlutterTest(Directory workingDir, { String target }) async {
args,
workingDirectory: workingDir.path,
);
if (exec.exitCode != 0) {
print(exec.stdout);
print(exec.stderr);
}
printOnFailure('Output of running flutter test:');
printOnFailure(exec.stdout.toString());
printOnFailure(exec.stderr.toString());
expect(exec.exitCode, 0);
}

View file

@ -179,7 +179,6 @@ void main() {
expect(logContents, contains('String: an exception % --'));
expect(logContents, contains('CrashingFlutterCommand.runCommand'));
expect(logContents, contains('[✓] Flutter'));
print(globals.crashReporter.runtimeType);
final CrashDetails sentDetails = (globals.crashReporter as WaitingCrashReporter)._details;
expect(sentDetails.command, 'flutter crash');

View file

@ -28,8 +28,9 @@ void main() {
'--no-color',
...arguments,
], workingDirectory: projectPath);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of flutter ${arguments.join(" ")}');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.exitCode, exitCode, reason: 'Expected to exit with non-zero exit code.');
assertContains(result.stdout.toString(), statusTextContains);
assertContains(result.stdout.toString(), errorTextContains);

View file

@ -31,8 +31,9 @@ void main() {
'--target-platform=android-arm64'
], workingDirectory: workingDirectory);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of flutter build apk:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.stdout.toString(), contains('app-release.apk (total compressed)'));
final String line = result.stdout.toString()
@ -67,8 +68,9 @@ void main() {
'--no-codesign',
], workingDirectory: workingDirectory);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of flutter build ios:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.stdout.toString(), contains('Dart AOT symbols accounted decompressed size'));
final String line = result.stdout.toString()
@ -102,8 +104,9 @@ void main() {
'--enable-macos-desktop',
], workingDirectory: workingDirectory);
print(configResult.stdout);
print(configResult.stderr);
printOnFailure('Output of flutter config:');
printOnFailure(configResult.stdout.toString());
printOnFailure(configResult.stderr.toString());
final ProcessResult result = await processManager.run(<String>[
flutterBin,
@ -113,8 +116,9 @@ void main() {
'--code-size-directory=${codeSizeDir.path}',
], workingDirectory: workingDirectory);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of flutter build macos:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.stdout.toString(), contains('Dart AOT symbols accounted decompressed size'));
final String line = result.stdout.toString()
@ -147,8 +151,9 @@ void main() {
'--debug',
], workingDirectory: fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world'));
print(result.stdout);
print(result.stderr);
printOnFailure('Output of flutter build apk:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.stderr.toString(), contains('"--analyze-size" can only be used on release builds'));
expect(result.exitCode, 1);

View file

@ -34,7 +34,7 @@ void main() {
final Completer<void> sawBackgroundMessage = Completer<void>.sync();
final Completer<void> sawNewBackgroundMessage = Completer<void>.sync();
final StreamSubscription<String> subscription = flutter.stdout.listen((String line) {
print('[LOG]:"$line"');
printOnFailure('[LOG]:"$line"');
if (line.contains('Main thread') && !sawForegroundMessage.isCompleted) {
sawForegroundMessage.complete();
}
@ -68,7 +68,7 @@ void main() {
final Completer<void> sawBackgroundMessage = Completer<void>.sync();
final Completer<void> sawNewBackgroundMessage = Completer<void>.sync();
final StreamSubscription<String> subscription = flutter.stdout.listen((String line) {
print('[LOG]:"$line"');
printOnFailure('[LOG]:"$line"');
if (line.contains('Isolate thread') && !sawBackgroundMessage.isCompleted) {
sawBackgroundMessage.complete();
}

View file

@ -33,8 +33,9 @@ void main() {
'--no-codesign',
], workingDirectory: workingDirectory);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of flutter build ios:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.exitCode, 0);

View file

@ -64,11 +64,7 @@ Future<void> main(List<String> args) async {
await cache.lock();
process.kill(io.ProcessSignal.sigkill);
} finally {
try {
tempDir.deleteSync(recursive: true);
} on FileSystemException {
// Ignore filesystem exceptions when trying to delete tempdir.
}
tryToDelete(tempDir);
Cache.flutterRoot = oldRoot;
}
expect(logger.statusText, isEmpty);

View file

@ -26,8 +26,10 @@ void main() {
'--target-platform', 'android-arm',
'--verbose',
], workingDirectory: woringDirectory);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of flutter build apk:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.exitCode, 0);

View file

@ -38,11 +38,7 @@ void main() {
});
tearDown(() {
try {
parentDirectory.deleteSync(recursive: true);
} on FileSystemException {
print('Failed to delete test directory');
}
tryToDelete(parentDirectory);
});
testWithoutContext('Can upgrade and downgrade a Flutter checkout', () async {
@ -56,7 +52,7 @@ void main() {
'git', 'config', '--system', 'core.longpaths', 'true',
]);
print('Step 1 - clone the $_kBranch of flutter into the test directory');
printOnFailure('Step 1 - clone the $_kBranch of flutter into the test directory');
exitCode = await processUtils.stream(<String>[
'git',
'clone',
@ -64,7 +60,7 @@ void main() {
], workingDirectory: parentDirectory.path, trace: true);
expect(exitCode, 0);
print('Step 2 - switch to the $_kBranch');
printOnFailure('Step 2 - switch to the $_kBranch');
exitCode = await processUtils.stream(<String>[
'git',
'checkout',
@ -75,7 +71,7 @@ void main() {
], workingDirectory: testDirectory.path, trace: true);
expect(exitCode, 0);
print('Step 3 - revert back to $_kInitialVersion');
printOnFailure('Step 3 - revert back to $_kInitialVersion');
exitCode = await processUtils.stream(<String>[
'git',
'reset',
@ -84,7 +80,7 @@ void main() {
], workingDirectory: testDirectory.path, trace: true);
expect(exitCode, 0);
print('Step 4 - upgrade to the newest $_kBranch');
printOnFailure('Step 4 - upgrade to the newest $_kBranch');
// This should update the persistent tool state with the sha for HEAD
exitCode = await processUtils.stream(<String>[
flutterBin,
@ -94,7 +90,7 @@ void main() {
], workingDirectory: testDirectory.path, trace: true);
expect(exitCode, 0);
print('Step 5 - verify that the version is different');
printOnFailure('Step 5 - verify that the version is different');
final RunResult versionResult = await processUtils.run(<String>[
'git',
'describe',
@ -104,10 +100,9 @@ void main() {
'--tags',
], workingDirectory: testDirectory.path);
expect(versionResult.stdout, isNot(contains(_kInitialVersion)));
print('current version is ${versionResult.stdout.trim()}\ninitial was $_kInitialVersion');
printOnFailure('current version is ${versionResult.stdout.trim()}\ninitial was $_kInitialVersion');
print('Step 6 - downgrade back to the initial version');
// Step 6. Downgrade back to initial version.
printOnFailure('Step 6 - downgrade back to the initial version');
exitCode = await processUtils.stream(<String>[
flutterBin,
'downgrade',
@ -116,8 +111,7 @@ void main() {
], workingDirectory: testDirectory.path, trace: true);
expect(exitCode, 0);
print('Step 7 - verify downgraded version matches original version');
// Step 7. Verify downgraded version matches original version.
printOnFailure('Step 7 - verify downgraded version matches original version');
final RunResult oldVersionResult = await processUtils.run(<String>[
'git',
'describe',
@ -127,6 +121,6 @@ void main() {
'--tags',
], workingDirectory: testDirectory.path);
expect(oldVersionResult.stdout, contains(_kInitialVersion));
print('current version is ${oldVersionResult.stdout.trim()}\ninitial was $_kInitialVersion');
printOnFailure('current version is ${oldVersionResult.stdout.trim()}\ninitial was $_kInitialVersion');
});
}

View file

@ -36,8 +36,9 @@ void main() {
fileSystem.path.join(tempDir.path, 'main.dart'),
]);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of dart main.dart:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.exitCode, 0);
});
@ -55,8 +56,9 @@ void main() {
fileSystem.path.join(tempDir.path, 'main.dart'),
]);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of dart main.dart:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.exitCode, 1);
});
}

View file

@ -67,7 +67,6 @@ String unsafeString = null;
for (final String targetPlatform in targetPlatforms) {
testWithoutContext('flutter build $targetPlatform --no-sound-null-safety', () {
print(tempDir);
final ProcessResult result = processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),

View file

@ -138,10 +138,9 @@ Future<void> _ensureFlutterToolsSnapshot() async {
'../../bin/cache/dart-sdk/bin/dart',
snapshotArgs,
);
if (snapshotResult.exitCode != 0) {
print(snapshotResult.stdout);
print(snapshotResult.stderr);
}
printOnFailure('Output of dart ${snapshotArgs.join(" ")}:');
printOnFailure(snapshotResult.stdout.toString());
printOnFailure(snapshotResult.stderr.toString());
expect(snapshotResult.exitCode, 0);
}
@ -237,9 +236,8 @@ Future<void> _analyzeProject(Directory workingDir) async {
args,
workingDirectory: workingDir.path,
);
if (exec.exitCode != 0) {
print(exec.stdout);
print(exec.stderr);
}
printOnFailure('Output of flutter analyze:');
printOnFailure(exec.stdout.toString());
printOnFailure(exec.stderr.toString());
expect(exec.exitCode, 0);
}

View file

@ -108,8 +108,14 @@ void main() {
await flutter.resume(); // we start paused so we can set up our TICK 1 listener before the app starts
unawaited(sawTick1.future.timeout(
const Duration(seconds: 5),
onTimeout: () { print('The test app is taking longer than expected to print its synchronization line...'); },
onTimeout: () {
// This print is useful for people debugging this test. Normally we would avoid printing in
// a test but this is an exception because it's useful ambient information.
// ignore: avoid_print
print('The test app is taking longer than expected to print its synchronization line...');
},
));
printOnFailure('waiting for synchronization line...');
await sawTick1.future; // after this, app is in steady state
await flutter.addBreakpoint(
project.scheduledBreakpointUri,
@ -126,19 +132,19 @@ void main() {
);
bool reloaded = false;
final Future<void> reloadFuture = flutter.hotReload().then((void value) { reloaded = true; });
print('waiting for pause...');
printOnFailure('waiting for pause...');
isolate = await flutter.waitForPause();
expect(isolate.pauseEvent.kind, equals(EventKind.kPauseBreakpoint));
print('waiting for debugger message...');
printOnFailure('waiting for debugger message...');
await sawDebuggerPausedMessage.future;
expect(reloaded, isFalse);
print('waiting for resume...');
printOnFailure('waiting for resume...');
await flutter.resume();
print('waiting for reload future...');
printOnFailure('waiting for reload future...');
await reloadFuture;
expect(reloaded, isTrue);
reloaded = false;
print('subscription cancel...');
printOnFailure('subscription cancel...');
await subscription.cancel();
});
@ -148,7 +154,7 @@ void main() {
final Completer<void> sawDebuggerPausedMessage2 = Completer<void>();
final StreamSubscription<String> subscription = flutter.stdout.listen(
(String line) {
print('[LOG]:"$line"');
printOnFailure('[LOG]:"$line"');
if (line.contains('(((TICK 1)))')) {
expect(sawTick1.isCompleted, isFalse);
sawTick1.complete();

View file

@ -47,7 +47,7 @@ void main() {
onSecondLoad.complete();
}
});
flutter.stdout.listen(print);
flutter.stdout.listen(printOnFailure);
await flutter.run();
await onFirstLoad.future;
@ -74,7 +74,7 @@ void main() {
onSecondLoad.complete();
}
});
flutter.stdout.listen(print);
flutter.stdout.listen(printOnFailure);
await flutter.run();
await onFirstLoad.future;

View file

@ -29,7 +29,7 @@ void main() {
'flutter',
);
final ProcessResult createResult = processManager.runSync(<String>[
processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'create',
@ -39,7 +39,6 @@ void main() {
'objc',
'hello',
], workingDirectory: tempDir.path);
print(createResult.stdout);
projectRoot = tempDir.childDirectory('hello').path;
});
@ -59,7 +58,7 @@ void main() {
File outputAppFrameworkBinary;
setUpAll(() {
final ProcessResult buildResult = processManager.runSync(<String>[
processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'build',
@ -70,7 +69,6 @@ void main() {
'--obfuscate',
'--split-debug-info=foo debug info/',
], workingDirectory: projectRoot);
print(buildResult.stdout);
buildPath = fileSystem.directory(fileSystem.path.join(
projectRoot,
@ -125,7 +123,6 @@ void main() {
infoPlistPath,
],
);
print(bonjourServices.stdout);
final bool bonjourServicesFound = (bonjourServices.stdout as String).contains('_dartobservatory._tcp');
expect(bonjourServicesFound, buildMode == BuildMode.debug);
@ -140,7 +137,6 @@ void main() {
infoPlistPath,
],
);
print(localNetworkUsage.stdout);
final bool localNetworkUsageFound = localNetworkUsage.exitCode == 0;
expect(localNetworkUsageFound, buildMode == BuildMode.debug);
});
@ -155,7 +151,6 @@ void main() {
'arm64',
],
);
print(symbols.stdout);
final bool aotSymbolsFound = (symbols.stdout as String).contains('_kDartVmSnapshot');
expect(aotSymbolsFound, buildMode != BuildMode.debug);
});
@ -197,7 +192,9 @@ void main() {
// Skip bitcode stripping since we just checked that above.
},
);
print(xcodeBackendResult.stdout);
printOnFailure('Output of xcode_backend.sh:');
printOnFailure(xcodeBackendResult.stdout.toString());
printOnFailure(xcodeBackendResult.stderr.toString());
expect(xcodeBackendResult.exitCode, 0);
expect(outputFlutterFrameworkBinary.existsSync(), isTrue);
@ -211,7 +208,6 @@ void main() {
'hello',
outputAppFrameworkBinary.path,
]);
print(grepResult.stdout);
expect(grepResult.stdout, isNot(contains('matches')));
});
});
@ -233,7 +229,6 @@ void main() {
'FLUTTER_XCODE_ONLY_ACTIVE_ARCH': 'NO',
},
);
print(buildSimulator.stdout);
// This test case would fail if arm64 or x86_64 simulators could not build.
expect(buildSimulator.exitCode, 0);
@ -251,7 +246,6 @@ void main() {
final ProcessResult archs = processManager.runSync(
<String>['file', simulatorAppFrameworkBinary.path],
);
print(archs.stdout);
expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library x86_64'));
expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library arm64'));
});

View file

@ -53,8 +53,9 @@ void main() {
];
final ProcessResult result = processManager.runSync(buildCommand, workingDirectory: workingDirectory);
print(result.stdout);
print(result.stderr);
printOnFailure('Output of flutter build macos:');
printOnFailure(result.stdout.toString());
printOnFailure(result.stderr.toString());
expect(result.exitCode, 0);
expect(result.stdout, contains('Running pod install'));
@ -134,8 +135,9 @@ void main() {
// Build again without cleaning.
final ProcessResult secondBuild = processManager.runSync(buildCommand, workingDirectory: workingDirectory);
print(secondBuild.stdout);
print(secondBuild.stderr);
printOnFailure('Output of second build:');
printOnFailure(secondBuild.stdout.toString());
printOnFailure(secondBuild.stderr.toString());
expect(secondBuild.exitCode, 0);
expect(secondBuild.stdout, isNot(contains('Running pod install')));

View file

@ -27,7 +27,7 @@ Future<void> waitForObservatoryMessage(Process process, int port) async {
process.stdout
.transform(utf8.decoder)
.listen((String line) {
print(line);
printOnFailure(line);
if (line.contains('An Observatory debugger and profiler on Flutter test device is available at')) {
if (line.contains('http://127.0.0.1:$port')) {
completer.complete();
@ -38,7 +38,7 @@ Future<void> waitForObservatoryMessage(Process process, int port) async {
});
process.stderr
.transform(utf8.decoder)
.listen(print);
.listen(printOnFailure);
return completer.future;
}

View file

@ -43,6 +43,13 @@ const ProcessManager processManager = LocalProcessManager();
final String flutterRoot = getFlutterRoot();
final String flutterBin = fileSystem.path.join(flutterRoot, 'bin', 'flutter');
void debugPrint(String message) {
// This is called to intentionally print debugging output when a test is
// either taking too long or has failed.
// ignore: avoid_print
print(message);
}
typedef LineHandler = String/*?*/ Function(String line);
abstract class Transition {
@ -136,7 +143,7 @@ class LogLine {
String toString() => '$stamp $channel: $message';
void printClearly() {
print('$stamp $channel: ${clarify(message)}');
debugPrint('$stamp $channel: ${clarify(message)}');
}
static String clarify(String line) {
@ -197,9 +204,9 @@ Future<ProcessTestResult> runFlutter(
int nextTransition = 0;
void describeStatus() {
if (transitions.isNotEmpty) {
print('Expected state transitions:');
debugPrint('Expected state transitions:');
for (int index = 0; index < transitions.length; index += 1) {
print(
debugPrint(
'${index.toString().padLeft(5)} '
'${index < nextTransition ? 'ALREADY MATCHED ' :
index == nextTransition ? 'NOW WAITING FOR>' :
@ -207,9 +214,9 @@ Future<ProcessTestResult> runFlutter(
}
}
if (logs.isEmpty) {
print('So far nothing has been logged${ debug ? "" : "; use debug:true to print all output" }.');
debugPrint('So far nothing has been logged${ debug ? "" : "; use debug:true to print all output" }.');
} else {
print('Log${ debug ? "" : " (only contains logged lines; use debug:true to print all output)" }:');
debugPrint('Log${ debug ? "" : " (only contains logged lines; use debug:true to print all output)" }:');
for (final LogLine log in logs) {
log.printClearly();
}
@ -221,12 +228,12 @@ Future<ProcessTestResult> runFlutter(
if (!streamingLogs) {
streamingLogs = true;
if (!debug) {
print('Test is taking a long time (${clock.elapsed.inSeconds} seconds so far).');
debugPrint('Test is taking a long time (${clock.elapsed.inSeconds} seconds so far).');
}
describeStatus();
print('(streaming all logs from this point on...)');
debugPrint('(streaming all logs from this point on...)');
} else {
print('(taking a long time...)');
debugPrint('(taking a long time...)');
}
}
String stamp() => '[${(clock.elapsed.inMilliseconds / 1000.0).toStringAsFixed(1).padLeft(5, " ")}s]';
@ -240,7 +247,7 @@ Future<ProcessTestResult> runFlutter(
}
if (nextTransition < transitions.length && transitions[nextTransition].matches(line)) {
if (streamingLogs) {
print('(matched ${transitions[nextTransition]})');
debugPrint('(matched ${transitions[nextTransition]})');
}
if (transitions[nextTransition].logging != null) {
if (!logging && transitions[nextTransition].logging/*!*/) {
@ -249,9 +256,9 @@ Future<ProcessTestResult> runFlutter(
logging = transitions[nextTransition].logging/*!*/;
if (streamingLogs) {
if (logging) {
print('(enabled logging)');
debugPrint('(enabled logging)');
} else {
print('(disabled logging)');
debugPrint('(disabled logging)');
}
}
}
@ -286,8 +293,8 @@ Future<ProcessTestResult> runFlutter(
process.stdout.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen(processStdout);
process.stderr.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen(processStderr);
unawaited(process.exitCode.timeout(expectedMaxDuration, onTimeout: () { // This is a failure timeout, must not be short.
print('${stamp()} (process is not quitting, trying to send a "q" just in case that helps)');
print('(a functional test should never reach this point)');
debugPrint('${stamp()} (process is not quitting, trying to send a "q" just in case that helps)');
debugPrint('(a functional test should never reach this point)');
final LogLine inLog = LogLine('stdin', stamp(), 'q');
logs.add(inLog);
if (streamingLogs) {
@ -298,24 +305,24 @@ Future<ProcessTestResult> runFlutter(
}).catchError((Object error) { /* ignore errors here, they will be reported on the next line */ }));
final int exitCode = await process.exitCode;
if (streamingLogs) {
print('${stamp()} (process terminated with exit code $exitCode)');
debugPrint('${stamp()} (process terminated with exit code $exitCode)');
}
timeout?.cancel();
if (nextTransition < transitions.length) {
print('The subprocess terminated before all the expected transitions had been matched.');
debugPrint('The subprocess terminated before all the expected transitions had been matched.');
if (logs.any((LogLine line) => line.couldBeCrash)) {
print('The subprocess may in fact have crashed. Check the stderr logs below.');
debugPrint('The subprocess may in fact have crashed. Check the stderr logs below.');
}
print('The transition that we were hoping to see next but that we never saw was:');
print('${nextTransition.toString().padLeft(5)} NOW WAITING FOR> ${transitions[nextTransition]}');
debugPrint('The transition that we were hoping to see next but that we never saw was:');
debugPrint('${nextTransition.toString().padLeft(5)} NOW WAITING FOR> ${transitions[nextTransition]}');
if (!streamingLogs) {
describeStatus();
print('(process terminated with exit code $exitCode)');
debugPrint('(process terminated with exit code $exitCode)');
}
throw TestFailure('Missed some expected transitions.');
}
if (streamingLogs) {
print('${stamp()} (completed execution successfully!)');
debugPrint('${stamp()} (completed execution successfully!)');
}
return ProcessTestResult(exitCode, logs);
}

View file

@ -79,6 +79,10 @@ abstract class FlutterTestDriver {
lastTime = time;
}
if (_printDebugOutputToStdOut) {
// This is the one place in this file that can call print. It is gated by
// _printDebugOutputToStdOut which should not be set to true in CI; it is
// intended only for use in local debugging.
// ignore: avoid_print
print('$time$_logPrefix$line');
}
}

View file

@ -215,6 +215,10 @@ void main() {
}
expect(result.exitCode, 0);
});
testWithoutContext('flutter gold skips tests where the expectations are missing', () async {
return _testFile('flutter_gold', automatedTestsDirectory, flutterTestDirectory, exitCode: isZero);
});
}
Future<void> _testFile(

View file

@ -40,6 +40,8 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/79498
testWithoutContext('Can connect to the timeline without getting ANR from the application', () async {
final Timer timer = Timer(const Duration(minutes: 5), () {
// This message is intended to show up in CI logs.
// ignore: avoid_print
print(
'Warning: test isolate is still active after 5 minutes. This is likely an '
'app-not-responding error and not a flake. See https://github.com/flutter/flutter/issues/79498 '

View file

@ -4,5 +4,6 @@
// Not a test file, invoked by `variable_expansion_windows_test.dart`.
void main(List<String> args) {
print('args: $args');
// This print is used for communicating with the test host.
print('args: $args'); // ignore: avoid_print
}

View file

@ -27,6 +27,9 @@ void tryToDelete(Directory directory) {
directory.deleteSync(recursive: true);
}
} on FileSystemException catch (error) {
// We print this so that it's visible in the logs, to get an idea of how
// common this problem is, and if any patterns are ever noticed by anyone.
// ignore: avoid_print
print('Failed to delete ${directory.path}: $error');
}
}

View file

@ -127,7 +127,7 @@ void testUsingContext(
},
body: () {
final String flutterRoot = getFlutterRoot();
return runZoned<Future<dynamic>>(() {
return runZonedGuarded<Future<dynamic>>(() {
try {
return context.run<dynamic>(
// Apply the overrides to the test context in the zone since their
@ -148,9 +148,10 @@ void testUsingContext(
_printBufferedErrors(context);
rethrow;
}
}, onError: (Object error, StackTrace stackTrace) { // ignore: deprecated_member_use
print(error);
print(stackTrace);
}, (Object error, StackTrace stackTrace) {
// When things fail, it's ok to print to the console!
print(error); // ignore: avoid_print
print(stackTrace); // ignore: avoid_print
_printBufferedErrors(context);
throw error;
});
@ -176,7 +177,9 @@ void _printBufferedErrors(AppContext testContext) {
if (testContext.get<Logger>() is BufferLogger) {
final BufferLogger bufferLogger = testContext.get<Logger>() as BufferLogger;
if (bufferLogger.errorText.isNotEmpty) {
print(bufferLogger.errorText);
// This is where the logger outputting errors is implemented, so it has
// to use `print`.
print(bufferLogger.errorText); // ignore: avoid_print
}
bufferLogger.clear();
}

View file

@ -38,7 +38,6 @@ void main() {
testWithoutContext('newly added code executes during hot restart', () async {
final Completer<void> completer = Completer<void>();
final StreamSubscription<String> subscription = flutter.stdout.listen((String line) {
print(line);
if (line.contains('(((((RELOAD WORKED)))))')) {
completer.complete();
}
@ -56,7 +55,6 @@ void main() {
testWithoutContext('newly added code executes during hot restart - canvaskit', () async {
final Completer<void> completer = Completer<void>();
final StreamSubscription<String> subscription = flutter.stdout.listen((String line) {
print(line);
if (line.contains('(((((RELOAD WORKED)))))')) {
completer.complete();
}

View file

@ -0,0 +1,5 @@
include: ../analysis_options.yaml
linter:
rules:
avoid_print: false # These are CLI tools which print as a matter of course.

View file

@ -51,6 +51,7 @@ typedef LoggingFunction = void Function(LogMessage log);
///
/// Exits with status code 1 if the `log` is [LoggingLevel.severe].
void defaultLoggingFunction(LogMessage log) {
// ignore: avoid_print
print('[${log.levelName}]::${log.tag}--${log.time}: ${log.message}');
if (log.level == LoggingLevel.severe) {
exit(1);

View file

@ -64,7 +64,7 @@ class IntegrationTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding
},
);
} on MissingPluginException {
print(r'''
debugPrint(r'''
Warning: integration_test plugin was not detected.
If you're running the tests with `flutter drive`, please make sure your tests
@ -391,7 +391,7 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab
count++;
await Future<void>.delayed(const Duration(seconds: 2));
if (count > 20) {
print('delayForFrameTimings is taking longer than expected...');
debugPrint('delayForFrameTimings is taking longer than expected...');
}
}
}

View file

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This is a CLI library; we use prints as part of the interface.
// ignore_for_file: avoid_print
import 'dart:async';
import 'dart:convert';
import 'dart:io';

View file

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This is a CLI library; we use prints as part of the interface.
// ignore_for_file: avoid_print
import 'dart:async';
import 'dart:io';

View file

@ -104,7 +104,6 @@ Future<void> main() async {
testWidgets('Test traceAction', (WidgetTester tester) async {
await integrationBinding.enableTimeline(vmService: fakeVM);
await integrationBinding.traceAction(() async {});
print(integrationBinding.reportData);
expect(integrationBinding.reportData, isNotNull);
expect(integrationBinding.reportData!.containsKey('timeline'), true);
expect(

View file

@ -10,6 +10,8 @@ import 'package:integration_test/integration_test.dart';
Future<void> main() async {
final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;
binding.allTestsPassed.future.then((_) {
// We use this print to communicate with ../binding_fail_test.dart
// ignore: avoid_print
print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}');
});

View file

@ -10,6 +10,8 @@ import 'package:integration_test/integration_test.dart';
Future<void> main() async {
final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;
binding.allTestsPassed.future.then((_) {
// We use this print to communicate with ../binding_fail_test.dart
// ignore: avoid_print
print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}');
});

View file

@ -10,6 +10,8 @@ import 'package:integration_test/integration_test.dart';
Future<void> main() async {
final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;
binding.allTestsPassed.future.then((_) {
// We use this print to communicate with ../binding_fail_test.dart
// ignore: avoid_print
print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}');
});

View file

@ -10,6 +10,8 @@ import 'package:integration_test/integration_test.dart';
Future<void> main() async {
final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() as IntegrationTestWidgetsFlutterBinding;
binding.allTestsPassed.future.then((_) {
// We use this print to communicate with ../binding_fail_test.dart
// ignore: avoid_print
print('IntegrationTestWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}');
});