mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Consider all non-interactive terminals to be bots (#34179)
This commit is contained in:
parent
0bbac72558
commit
1b3fc53595
@ -26,7 +26,7 @@
|
||||
/// 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.
|
||||
import 'dart:async';
|
||||
import 'dart:io' as io show exit, IOSink, ProcessSignal, stderr, stdin, stdout;
|
||||
import 'dart:io' as io show exit, IOSink, ProcessSignal, stderr, stdin, Stdout, stdout;
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
@ -72,6 +72,7 @@ export 'dart:io'
|
||||
Stdin,
|
||||
StdinException,
|
||||
// stdout, NO! Use `io.dart`
|
||||
Stdout,
|
||||
Socket,
|
||||
SocketException,
|
||||
systemEncoding,
|
||||
@ -156,7 +157,7 @@ class Stdio {
|
||||
const Stdio();
|
||||
|
||||
Stream<List<int>> get stdin => io.stdin;
|
||||
io.IOSink get stdout => io.stdout;
|
||||
io.Stdout get stdout => io.stdout;
|
||||
io.IOSink get stderr => io.stderr;
|
||||
|
||||
bool get hasTerminal => io.stdout.hasTerminal;
|
||||
@ -165,7 +166,7 @@ class Stdio {
|
||||
bool get supportsAnsiEscapes => hasTerminal ? io.stdout.supportsAnsiEscapes : false;
|
||||
}
|
||||
|
||||
Stdio get stdio => context.get<Stdio>();
|
||||
io.IOSink get stdout => stdio.stdout;
|
||||
Stdio get stdio => context.get<Stdio>() ?? const Stdio();
|
||||
io.Stdout get stdout => stdio.stdout;
|
||||
Stream<List<int>> get stdin => stdio.stdin;
|
||||
io.IOSink get stderr => stdio.stderr;
|
||||
|
||||
@ -21,8 +21,20 @@ class BotDetector {
|
||||
const BotDetector();
|
||||
|
||||
bool get isRunningOnBot {
|
||||
return platform.environment['BOT'] != 'false'
|
||||
&& (platform.environment['BOT'] == 'true'
|
||||
if (
|
||||
// Explicitly stated to not be a bot.
|
||||
platform.environment['BOT'] == 'false'
|
||||
|
||||
// Set by the IDEs to the IDE name, so a strong signal that this is not a bot.
|
||||
|| platform.environment.containsKey('FLUTTER_HOST')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return platform.environment['BOT'] == 'true'
|
||||
|
||||
// Non-interactive terminals are assumed to be bots.
|
||||
|| !io.stdout.hasTerminal
|
||||
|
||||
// https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
|
||||
|| platform.environment['TRAVIS'] == 'true'
|
||||
@ -43,7 +55,8 @@ class BotDetector {
|
||||
|
||||
// Properties on Flutter's Chrome Infra bots.
|
||||
|| platform.environment['CHROME_HEADLESS'] == '1'
|
||||
|| platform.environment.containsKey('BUILDBOT_BUILDERNAME'));
|
||||
|| platform.environment.containsKey('BUILDBOT_BUILDERNAME')
|
||||
|| platform.environment.containsKey('SWARMING_TASK_ID');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
56
packages/flutter_tools/test/base/utils_test.dart
Normal file
56
packages/flutter_tools/test/base/utils_test.dart
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2019 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/io.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/base/utils.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/mocks.dart';
|
||||
|
||||
void main() {
|
||||
group('BotDetector', () {
|
||||
FakePlatform fakePlatform;
|
||||
MockStdio mockStdio;
|
||||
BotDetector botDetector;
|
||||
|
||||
setUp(() {
|
||||
fakePlatform = FakePlatform()..environment = <String, String>{};
|
||||
mockStdio = MockStdio();
|
||||
botDetector = const BotDetector();
|
||||
});
|
||||
|
||||
group('isRunningOnBot', () {
|
||||
testUsingContext('returns false unconditionally if BOT=false is set', () async {
|
||||
fakePlatform.environment['BOT'] = 'false';
|
||||
fakePlatform.environment['TRAVIS'] = 'true';
|
||||
expect(botDetector.isRunningOnBot, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
Stdio: () => mockStdio,
|
||||
Platform: () => fakePlatform,
|
||||
});
|
||||
|
||||
testUsingContext('returns false unconditionally if FLUTTER_HOST is set', () async {
|
||||
fakePlatform.environment['FLUTTER_HOST'] = 'foo';
|
||||
fakePlatform.environment['TRAVIS'] = 'true';
|
||||
expect(botDetector.isRunningOnBot, isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
Stdio: () => mockStdio,
|
||||
Platform: () => fakePlatform,
|
||||
});
|
||||
|
||||
testUsingContext('returns true for non-interactive terminals', () async {
|
||||
mockStdio.stdout.hasTerminal = true;
|
||||
expect(botDetector.isRunningOnBot, isFalse);
|
||||
mockStdio.stdout.hasTerminal = false;
|
||||
expect(botDetector.isRunningOnBot, isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
Stdio: () => mockStdio,
|
||||
Platform: () => fakePlatform,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io' as io show IOSink, ProcessSignal;
|
||||
import 'dart:io' as io show IOSink, ProcessSignal, Stdout, StdoutException;
|
||||
|
||||
import 'package:flutter_tools/src/android/android_device.dart';
|
||||
import 'package:flutter_tools/src/android/android_sdk.dart' show AndroidSdk;
|
||||
@ -342,17 +342,56 @@ class MemoryIOSink implements IOSink {
|
||||
Future<void> flush() async { }
|
||||
}
|
||||
|
||||
class MemoryStdout extends MemoryIOSink implements io.Stdout {
|
||||
@override
|
||||
bool get hasTerminal => _hasTerminal;
|
||||
set hasTerminal(bool value) {
|
||||
assert(value != null);
|
||||
_hasTerminal = value;
|
||||
}
|
||||
bool _hasTerminal = true;
|
||||
|
||||
@override
|
||||
io.IOSink get nonBlocking => this;
|
||||
|
||||
@override
|
||||
bool get supportsAnsiEscapes => _supportsAnsiEscapes;
|
||||
set supportsAnsiEscapes(bool value) {
|
||||
assert(value != null);
|
||||
_supportsAnsiEscapes = value;
|
||||
}
|
||||
bool _supportsAnsiEscapes = true;
|
||||
|
||||
@override
|
||||
int get terminalColumns {
|
||||
if (_terminalColumns != null)
|
||||
return _terminalColumns;
|
||||
throw const io.StdoutException('unspecified mock value');
|
||||
}
|
||||
set terminalColumns(int value) => _terminalColumns = value;
|
||||
int _terminalColumns;
|
||||
|
||||
@override
|
||||
int get terminalLines {
|
||||
if (_terminalLines != null)
|
||||
return _terminalLines;
|
||||
throw const io.StdoutException('unspecified mock value');
|
||||
}
|
||||
set terminalLines(int value) => _terminalLines = value;
|
||||
int _terminalLines;
|
||||
}
|
||||
|
||||
/// A Stdio that collects stdout and supports simulated stdin.
|
||||
class MockStdio extends Stdio {
|
||||
final MemoryIOSink _stdout = MemoryIOSink();
|
||||
final MemoryStdout _stdout = MemoryStdout();
|
||||
final MemoryIOSink _stderr = MemoryIOSink();
|
||||
final StreamController<List<int>> _stdin = StreamController<List<int>>();
|
||||
|
||||
@override
|
||||
IOSink get stdout => _stdout;
|
||||
MemoryStdout get stdout => _stdout;
|
||||
|
||||
@override
|
||||
IOSink get stderr => _stderr;
|
||||
MemoryIOSink get stderr => _stderr;
|
||||
|
||||
@override
|
||||
Stream<List<int>> get stdin => _stdin.stream;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user