Filter out '\n' from terminal input. (#10220) * Remove '\n' from terminal input. * Use trim instead of replaceAll * Add unit test * Cleanup the test * Fixed lint * Style adjustments * Forgotten @override * Revert "Forgotten @override" Accidently added extra files. This reverts commit 0aba24fc8ea321b3a4d0cd8aed7f589378393d96. * Just @override change
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 9194e17..300d4ff 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -624,6 +624,8 @@ } Future<Null> processTerminalInput(String command) async { + // When terminal doesn't support line mode, '\n' can sneak into the input. + command = command.trim(); if (_processingUserRequest) { printTrace('Ignoring terminal input: "$command" because we are busy.'); return;
diff --git a/packages/flutter_tools/test/resident_runner_test.dart b/packages/flutter_tools/test/resident_runner_test.dart new file mode 100644 index 0000000..62cf116 --- /dev/null +++ b/packages/flutter_tools/test/resident_runner_test.dart
@@ -0,0 +1,82 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'package:flutter_tools/src/device.dart'; +import 'package:flutter_tools/src/resident_runner.dart'; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; + +import 'src/context.dart'; + +class TestRunner extends ResidentRunner { + TestRunner(List<FlutterDevice> devices) + : super(devices); + + bool hasHelpBeenPrinted = false; + String receivedCommand; + + @override + Future<Null> cleanupAfterSignal() => null; + + @override + Future<Null> cleanupAtFinish() => null; + + @override + Future<Null> handleTerminalCommand(String code) async { + receivedCommand = code; + } + + @override + void printHelp({ bool details }) { + hasHelpBeenPrinted = true; + } + + @override + Future<int> run({ + Completer<DebugConnectionInfo> connectionInfoCompleter, + Completer<dynamic> appStartedCompleter, + String route, + bool shouldBuild: true, + }) => null; +} + +void main() { + TestRunner testRunner; + + setUp(() { + testRunner = new TestRunner( + <FlutterDevice>[new FlutterDevice(new MockDevice())] + ); + }); + + group('keyboard input handling', () { + testUsingContext('single help character', () async { + expect(testRunner.hasHelpBeenPrinted, isFalse); + await testRunner.processTerminalInput('h'); + expect(testRunner.hasHelpBeenPrinted, isTrue); + }); + testUsingContext('help character surrounded with newlines', () async { + expect(testRunner.hasHelpBeenPrinted, isFalse); + await testRunner.processTerminalInput('\nh\n'); + expect(testRunner.hasHelpBeenPrinted, isTrue); + }); + testUsingContext('reload character with trailing newline', () async { + expect(testRunner.receivedCommand, isNull); + await testRunner.processTerminalInput('r\n'); + expect(testRunner.receivedCommand, equals('r')); + }); + testUsingContext('newlines', () async { + expect(testRunner.receivedCommand, isNull); + await testRunner.processTerminalInput('\n\n'); + expect(testRunner.receivedCommand, equals('')); + }); + }); +} + +class MockDevice extends Mock implements Device { + MockDevice() { + when(isSupported()).thenReturn(true); + } +}