Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
07161e82
Unverified
Commit
07161e82
authored
Jan 08, 2020
by
Zachary Anderson
Committed by
GitHub
Jan 08, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tool] Don't use context in ProcessUtils (#48444)
parent
4e6d649f
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
227 additions
and
154 deletions
+227
-154
runner.dart
packages/flutter_tools/lib/runner.dart
+1
-1
gradle.dart
packages/flutter_tools/lib/src/android/gradle.dart
+1
-1
application_package.dart
packages/flutter_tools/lib/src/application_package.dart
+1
-1
process.dart
packages/flutter_tools/lib/src/base/process.dart
+115
-64
context_runner.dart
packages/flutter_tools/lib/src/context_runner.dart
+5
-1
process_test.dart
...s/flutter_tools/test/general.shard/base/process_test.dart
+104
-86
No files found.
packages/flutter_tools/lib/runner.dart
View file @
07161e82
...
...
@@ -255,7 +255,7 @@ Future<int> _exit(int code) async {
}
// Run shutdown hooks before flushing logs
await
runShutdownHooks
();
await
shutdownHooks
.
runShutdownHooks
();
final
Completer
<
void
>
completer
=
Completer
<
void
>();
...
...
packages/flutter_tools/lib/src/android/gradle.dart
View file @
07161e82
...
...
@@ -907,7 +907,7 @@ Directory _getLocalEngineRepo({
.
createTempSync
(
'flutter_tool_local_engine_repo.'
);
// Remove the local engine repo before the tool exits.
addShutdownHook
(
shutdownHooks
.
addShutdownHook
(
()
=>
localEngineRepo
.
deleteSync
(
recursive:
true
),
ShutdownStage
.
CLEANUP
,
);
...
...
packages/flutter_tools/lib/src/application_package.dart
View file @
07161e82
...
...
@@ -288,7 +288,7 @@ abstract class IOSApp extends ApplicationPackage {
}
else
{
// Try to unpack as an ipa.
final
Directory
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_app.'
);
addShutdownHook
(()
async
{
shutdownHooks
.
addShutdownHook
(()
async
{
await
tempDir
.
delete
(
recursive:
true
);
},
ShutdownStage
.
STILL_RECORDING
);
os
.
unzip
(
globals
.
fs
.
file
(
applicationBinary
),
tempDir
);
...
...
packages/flutter_tools/lib/src/base/process.dart
View file @
07161e82
...
...
@@ -4,11 +4,14 @@
import
'dart:async'
;
import
'package:meta/meta.dart'
;
import
'package:process/process.dart'
;
import
'../convert.dart'
;
import
'../globals.dart'
as
globals
;
import
'common.dart'
;
import
'context.dart'
;
import
'io.dart'
;
import
'logger.dart'
;
import
'utils.dart'
;
typedef
StringConverter
=
String
Function
(
String
string
);
...
...
@@ -51,50 +54,80 @@ class ShutdownStage implements Comparable<ShutdownStage> {
int
compareTo
(
ShutdownStage
other
)
=>
priority
.
compareTo
(
other
.
priority
);
}
Map
<
ShutdownStage
,
List
<
ShutdownHook
>>
_shutdownHooks
=
<
ShutdownStage
,
List
<
ShutdownHook
>>{};
bool
_shutdownHooksRunning
=
false
;
/// Registers a [ShutdownHook] to be executed before the VM exits.
///
/// If [stage] is specified, the shutdown hook will be run during the specified
/// stage. By default, the shutdown hook will be run during the
/// [ShutdownStage.CLEANUP] stage.
void
addShutdownHook
(
ShutdownHook
shutdownHook
,
[
ShutdownStage
stage
=
ShutdownStage
.
CLEANUP
,
])
{
assert
(!
_shutdownHooksRunning
);
_shutdownHooks
.
putIfAbsent
(
stage
,
()
=>
<
ShutdownHook
>[]).
add
(
shutdownHook
);
ShutdownHooks
get
shutdownHooks
=>
ShutdownHooks
.
instance
;
abstract
class
ShutdownHooks
{
factory
ShutdownHooks
({
@required
Logger
logger
,
})
=>
_DefaultShutdownHooks
(
logger:
logger
,
);
static
ShutdownHooks
get
instance
=>
context
.
get
<
ShutdownHooks
>();
/// Registers a [ShutdownHook] to be executed before the VM exits.
///
/// If [stage] is specified, the shutdown hook will be run during the specified
/// stage. By default, the shutdown hook will be run during the
/// [ShutdownStage.CLEANUP] stage.
void
addShutdownHook
(
ShutdownHook
shutdownHook
,
[
ShutdownStage
stage
=
ShutdownStage
.
CLEANUP
,
]);
/// Runs all registered shutdown hooks and returns a future that completes when
/// all such hooks have finished.
///
/// Shutdown hooks will be run in groups by their [ShutdownStage]. All shutdown
/// hooks within a given stage will be started in parallel and will be
/// guaranteed to run to completion before shutdown hooks in the next stage are
/// started.
Future
<
void
>
runShutdownHooks
();
}
/// Runs all registered shutdown hooks and returns a future that completes when
/// all such hooks have finished.
///
/// Shutdown hooks will be run in groups by their [ShutdownStage]. All shutdown
/// hooks within a given stage will be started in parallel and will be
/// guaranteed to run to completion before shutdown hooks in the next stage are
/// started.
Future
<
void
>
runShutdownHooks
()
async
{
globals
.
printTrace
(
'Running shutdown hooks'
);
_shutdownHooksRunning
=
true
;
try
{
for
(
final
ShutdownStage
stage
in
_shutdownHooks
.
keys
.
toList
()..
sort
())
{
globals
.
printTrace
(
'Shutdown hook priority
${stage.priority}
'
);
final
List
<
ShutdownHook
>
hooks
=
_shutdownHooks
.
remove
(
stage
);
final
List
<
Future
<
dynamic
>>
futures
=
<
Future
<
dynamic
>>[];
for
(
final
ShutdownHook
shutdownHook
in
hooks
)
{
final
FutureOr
<
dynamic
>
result
=
shutdownHook
();
if
(
result
is
Future
<
dynamic
>)
{
futures
.
add
(
result
);
class
_DefaultShutdownHooks
implements
ShutdownHooks
{
_DefaultShutdownHooks
({
@required
Logger
logger
,
})
:
_logger
=
logger
;
final
Logger
_logger
;
final
Map
<
ShutdownStage
,
List
<
ShutdownHook
>>
_shutdownHooks
=
<
ShutdownStage
,
List
<
ShutdownHook
>>{};
bool
_shutdownHooksRunning
=
false
;
@override
void
addShutdownHook
(
ShutdownHook
shutdownHook
,
[
ShutdownStage
stage
=
ShutdownStage
.
CLEANUP
,
])
{
assert
(!
_shutdownHooksRunning
);
_shutdownHooks
.
putIfAbsent
(
stage
,
()
=>
<
ShutdownHook
>[]).
add
(
shutdownHook
);
}
@override
Future
<
void
>
runShutdownHooks
()
async
{
_logger
.
printTrace
(
'Running shutdown hooks'
);
_shutdownHooksRunning
=
true
;
try
{
for
(
final
ShutdownStage
stage
in
_shutdownHooks
.
keys
.
toList
()..
sort
())
{
_logger
.
printTrace
(
'Shutdown hook priority
${stage.priority}
'
);
final
List
<
ShutdownHook
>
hooks
=
_shutdownHooks
.
remove
(
stage
);
final
List
<
Future
<
dynamic
>>
futures
=
<
Future
<
dynamic
>>[];
for
(
final
ShutdownHook
shutdownHook
in
hooks
)
{
final
FutureOr
<
dynamic
>
result
=
shutdownHook
();
if
(
result
is
Future
<
dynamic
>)
{
futures
.
add
(
result
);
}
}
await
Future
.
wait
<
dynamic
>(
futures
);
}
await
Future
.
wait
<
dynamic
>(
futures
);
}
finally
{
_shutdownHooksRunning
=
false
;
}
}
finally
{
_
shutdownHooksRunning
=
false
;
assert
(
_shutdownHooks
.
isEmpty
);
_
logger
.
printTrace
(
'Shutdown hooks complete'
)
;
}
assert
(
_shutdownHooks
.
isEmpty
);
globals
.
printTrace
(
'Shutdown hooks complete'
);
}
class
ProcessExit
implements
Exception
{
...
...
@@ -150,7 +183,13 @@ typedef RunResultChecker = bool Function(int);
ProcessUtils
get
processUtils
=>
ProcessUtils
.
instance
;
abstract
class
ProcessUtils
{
factory
ProcessUtils
()
=>
_DefaultProcessUtils
();
factory
ProcessUtils
({
@required
ProcessManager
processManager
,
@required
Logger
logger
,
})
=>
_DefaultProcessUtils
(
processManager:
processManager
,
logger:
logger
,
);
static
ProcessUtils
get
instance
=>
context
.
get
<
ProcessUtils
>();
...
...
@@ -239,6 +278,16 @@ abstract class ProcessUtils {
}
class
_DefaultProcessUtils
implements
ProcessUtils
{
_DefaultProcessUtils
({
@required
ProcessManager
processManager
,
@required
Logger
logger
,
})
:
_processManager
=
processManager
,
_logger
=
logger
;
final
ProcessManager
_processManager
;
final
Logger
_logger
;
@override
Future
<
RunResult
>
run
(
List
<
String
>
cmd
,
{
...
...
@@ -259,15 +308,15 @@ class _DefaultProcessUtils implements ProcessUtils {
_traceCommand
(
cmd
,
workingDirectory:
workingDirectory
);
// When there is no timeout, there's no need to kill a running process, so
// we can just use
globals.
processManager.run().
// we can just use
_
processManager.run().
if
(
timeout
==
null
)
{
final
ProcessResult
results
=
await
globals
.
processManager
.
run
(
final
ProcessResult
results
=
await
_
processManager
.
run
(
cmd
,
workingDirectory:
workingDirectory
,
environment:
_environment
(
allowReentrantFlutter
,
environment
),
);
final
RunResult
runResult
=
RunResult
(
results
,
cmd
);
globals
.
printTrace
(
runResult
.
toString
());
_logger
.
printTrace
(
runResult
.
toString
());
if
(
throwOnError
&&
runResult
.
exitCode
!=
0
&&
(
whiteListFailures
==
null
||
!
whiteListFailures
(
runResult
.
exitCode
)))
{
runResult
.
throwException
(
'Process exited abnormally:
\n
$runResult
'
);
...
...
@@ -276,7 +325,7 @@ class _DefaultProcessUtils implements ProcessUtils {
}
// When there is a timeout, we have to kill the running process, so we have
// to use
globals.
processManager.start() through _runCommand() above.
// to use
_
processManager.start() through _runCommand() above.
while
(
true
)
{
assert
(
timeoutRetries
>=
0
);
timeoutRetries
=
timeoutRetries
-
1
;
...
...
@@ -302,7 +351,7 @@ class _DefaultProcessUtils implements ProcessUtils {
int
exitCode
;
exitCode
=
await
process
.
exitCode
.
timeout
(
timeout
,
onTimeout:
()
{
// The process timed out. Kill it.
globals
.
processManager
.
killPid
(
process
.
pid
);
_
processManager
.
killPid
(
process
.
pid
);
return
null
;
});
...
...
@@ -331,7 +380,7 @@ class _DefaultProcessUtils implements ProcessUtils {
// If the process did not timeout. We are done.
if
(
exitCode
!=
null
)
{
globals
.
printTrace
(
runResult
.
toString
());
_logger
.
printTrace
(
runResult
.
toString
());
if
(
throwOnError
&&
runResult
.
exitCode
!=
0
&&
(
whiteListFailures
==
null
||
!
whiteListFailures
(
exitCode
)))
{
runResult
.
throwException
(
'Process exited abnormally:
\n
$runResult
'
);
...
...
@@ -345,8 +394,10 @@ class _DefaultProcessUtils implements ProcessUtils {
}
// Log the timeout with a trace message in verbose mode.
globals
.
printTrace
(
'Process "
${cmd[0]}
" timed out.
$timeoutRetries
attempts left:
\n
'
'
$runResult
'
);
_logger
.
printTrace
(
'Process "
${cmd[0]}
" timed out.
$timeoutRetries
attempts left:
\n
'
'
$runResult
'
,
);
}
// Unreachable.
...
...
@@ -363,14 +414,14 @@ class _DefaultProcessUtils implements ProcessUtils {
bool
allowReentrantFlutter
=
false
,
})
{
_traceCommand
(
cmd
,
workingDirectory:
workingDirectory
);
final
ProcessResult
results
=
globals
.
processManager
.
runSync
(
final
ProcessResult
results
=
_
processManager
.
runSync
(
cmd
,
workingDirectory:
workingDirectory
,
environment:
_environment
(
allowReentrantFlutter
,
environment
),
);
final
RunResult
runResult
=
RunResult
(
results
,
cmd
);
globals
.
printTrace
(
'Exit code
${runResult.exitCode}
from:
${cmd.join(' ')}
'
);
_logger
.
printTrace
(
'Exit code
${runResult.exitCode}
from:
${cmd.join(' ')}
'
);
bool
failedExitCode
=
runResult
.
exitCode
!=
0
;
if
(
whiteListFailures
!=
null
&&
failedExitCode
)
{
...
...
@@ -379,17 +430,17 @@ class _DefaultProcessUtils implements ProcessUtils {
if
(
runResult
.
stdout
.
isNotEmpty
&&
!
hideStdout
)
{
if
(
failedExitCode
&&
throwOnError
)
{
globals
.
printStatus
(
runResult
.
stdout
.
trim
());
_logger
.
printStatus
(
runResult
.
stdout
.
trim
());
}
else
{
globals
.
printTrace
(
runResult
.
stdout
.
trim
());
_logger
.
printTrace
(
runResult
.
stdout
.
trim
());
}
}
if
(
runResult
.
stderr
.
isNotEmpty
)
{
if
(
failedExitCode
&&
throwOnError
)
{
globals
.
printError
(
runResult
.
stderr
.
trim
());
_logger
.
printError
(
runResult
.
stderr
.
trim
());
}
else
{
globals
.
printTrace
(
runResult
.
stderr
.
trim
());
_logger
.
printTrace
(
runResult
.
stderr
.
trim
());
}
}
...
...
@@ -408,7 +459,7 @@ class _DefaultProcessUtils implements ProcessUtils {
Map
<
String
,
String
>
environment
,
})
{
_traceCommand
(
cmd
,
workingDirectory:
workingDirectory
);
return
globals
.
processManager
.
start
(
return
_
processManager
.
start
(
cmd
,
workingDirectory:
workingDirectory
,
environment:
_environment
(
allowReentrantFlutter
,
environment
),
...
...
@@ -443,9 +494,9 @@ class _DefaultProcessUtils implements ProcessUtils {
if
(
line
!=
null
)
{
final
String
message
=
'
$prefix$line
'
;
if
(
trace
)
{
globals
.
printTrace
(
message
);
_logger
.
printTrace
(
message
);
}
else
{
globals
.
printStatus
(
message
,
wrap:
false
);
_logger
.
printStatus
(
message
,
wrap:
false
);
}
}
});
...
...
@@ -458,7 +509,7 @@ class _DefaultProcessUtils implements ProcessUtils {
line
=
mapFunction
(
line
);
}
if
(
line
!=
null
)
{
globals
.
printError
(
'
$prefix$line
'
,
wrap:
false
);
_logger
.
printError
(
'
$prefix$line
'
,
wrap:
false
);
}
});
...
...
@@ -487,9 +538,9 @@ class _DefaultProcessUtils implements ProcessUtils {
})
{
_traceCommand
(
cli
);
try
{
return
globals
.
processManager
.
runSync
(
cli
,
environment:
environment
).
exitCode
==
0
;
return
_
processManager
.
runSync
(
cli
,
environment:
environment
).
exitCode
==
0
;
}
catch
(
error
)
{
globals
.
printTrace
(
'
$cli
failed with
$error
'
);
_logger
.
printTrace
(
'
$cli
failed with
$error
'
);
return
false
;
}
}
...
...
@@ -501,9 +552,9 @@ class _DefaultProcessUtils implements ProcessUtils {
})
async
{
_traceCommand
(
cli
);
try
{
return
(
await
globals
.
processManager
.
run
(
cli
,
environment:
environment
)).
exitCode
==
0
;
return
(
await
_
processManager
.
run
(
cli
,
environment:
environment
)).
exitCode
==
0
;
}
catch
(
error
)
{
globals
.
printTrace
(
'
$cli
failed with
$error
'
);
_logger
.
printTrace
(
'
$cli
failed with
$error
'
);
return
false
;
}
}
...
...
@@ -525,9 +576,9 @@ class _DefaultProcessUtils implements ProcessUtils {
void
_traceCommand
(
List
<
String
>
args
,
{
String
workingDirectory
})
{
final
String
argsText
=
args
.
join
(
' '
);
if
(
workingDirectory
==
null
)
{
globals
.
printTrace
(
'executing:
$argsText
'
);
_logger
.
printTrace
(
'executing:
$argsText
'
);
}
else
{
globals
.
printTrace
(
'executing: [
$workingDirectory${globals.fs.path.separator}
]
$argsText
'
);
_logger
.
printTrace
(
'executing: [
$workingDirectory
/
]
$argsText
'
);
}
}
}
packages/flutter_tools/lib/src/context_runner.dart
View file @
07161e82
...
...
@@ -120,8 +120,12 @@ Future<T> runInContext<T>(
OperatingSystemUtils:
()
=>
OperatingSystemUtils
(),
PersistentToolState:
()
=>
PersistentToolState
(),
ProcessInfo:
()
=>
ProcessInfo
(),
ProcessUtils:
()
=>
ProcessUtils
(),
ProcessUtils:
()
=>
ProcessUtils
(
processManager:
globals
.
processManager
,
logger:
globals
.
logger
,
),
Pub:
()
=>
const
Pub
(),
ShutdownHooks:
()
=>
ShutdownHooks
(
logger:
globals
.
logger
),
Signals:
()
=>
Signals
(),
SimControl:
()
=>
SimControl
(),
Stdio:
()
=>
const
Stdio
(),
...
...
packages/flutter_tools/test/general.shard/base/process_test.dart
View file @
07161e82
...
...
@@ -6,6 +6,7 @@ import 'dart:async';
import
'package:platform/platform.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/base/process.dart'
;
import
'package:flutter_tools/src/base/terminal.dart'
;
import
'package:mockito/mockito.dart'
;
...
...
@@ -15,49 +16,59 @@ import '../../src/common.dart';
import
'../../src/context.dart'
;
import
'../../src/mocks.dart'
show
MockProcess
,
MockProcessManager
,
MockStdio
,
flakyProcessFactory
;
class
MockLogger
extends
Mock
implements
Logger
{}
void
main
(
)
{
group
(
'process exceptions'
,
()
{
ProcessManager
mockProcessManager
;
ProcessUtils
processUtils
;
setUp
(()
{
mockProcessManager
=
PlainMockProcessManager
();
processUtils
=
ProcessUtils
(
processManager:
mockProcessManager
,
logger:
MockLogger
(),
);
});
test
Using
Context
(
'runAsync throwOnError: exceptions should be ProcessException objects'
,
()
async
{
test
Without
Context
(
'runAsync throwOnError: exceptions should be ProcessException objects'
,
()
async
{
when
(
mockProcessManager
.
run
(<
String
>[
'false'
])).
thenAnswer
(
(
Invocation
invocation
)
=>
Future
<
ProcessResult
>.
value
(
ProcessResult
(
0
,
1
,
''
,
''
)));
expect
(()
async
=>
await
processUtils
.
run
(<
String
>[
'false'
],
throwOnError:
true
),
throwsA
(
isInstanceOf
<
ProcessException
>()));
}
,
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
}
);
});
});
group
(
'shutdownHooks'
,
()
{
test
Using
Context
(
'runInExpectedOrder'
,
()
async
{
test
Without
Context
(
'runInExpectedOrder'
,
()
async
{
int
i
=
1
;
int
serializeRecording1
;
int
serializeRecording2
;
int
postProcessRecording
;
int
cleanup
;
addShutdownHook
(()
async
{
final
ShutdownHooks
shutdownHooks
=
ShutdownHooks
(
logger:
MockLogger
());
shutdownHooks
.
addShutdownHook
(()
async
{
serializeRecording1
=
i
++;
},
ShutdownStage
.
SERIALIZE_RECORDING
);
addShutdownHook
(()
async
{
shutdownHooks
.
addShutdownHook
(()
async
{
cleanup
=
i
++;
},
ShutdownStage
.
CLEANUP
);
addShutdownHook
(()
async
{
shutdownHooks
.
addShutdownHook
(()
async
{
postProcessRecording
=
i
++;
},
ShutdownStage
.
POST_PROCESS_RECORDING
);
addShutdownHook
(()
async
{
shutdownHooks
.
addShutdownHook
(()
async
{
serializeRecording2
=
i
++;
},
ShutdownStage
.
SERIALIZE_RECORDING
);
await
runShutdownHooks
();
await
shutdownHooks
.
runShutdownHooks
();
expect
(
serializeRecording1
,
lessThanOrEqualTo
(
2
));
expect
(
serializeRecording2
,
lessThanOrEqualTo
(
2
));
...
...
@@ -68,30 +79,42 @@ void main() {
group
(
'output formatting'
,
()
{
MockProcessManager
mockProcessManager
;
ProcessUtils
processUtils
;
BufferLogger
mockLogger
;
setUp
(()
{
mockProcessManager
=
MockProcessManager
();
mockLogger
=
BufferLogger
(
terminal:
AnsiTerminal
(
stdio:
MockStdio
(),
platform:
FakePlatform
.
fromPlatform
(
const
LocalPlatform
())..
stdoutSupportsAnsi
=
false
,
),
outputPreferences:
OutputPreferences
(
wrapText:
true
,
wrapColumn:
40
),
);
processUtils
=
ProcessUtils
(
processManager:
mockProcessManager
,
logger:
mockLogger
,
);
});
MockProcess
Function
(
List
<
String
>)
processMetaFactory
(
List
<
String
>
stdout
,
{
List
<
String
>
stderr
=
const
<
String
>[]
})
{
final
Stream
<
List
<
int
>>
stdoutStream
=
Stream
<
List
<
int
>>.
fromIterable
(
stdout
.
map
<
List
<
int
>>((
String
s
)
=>
s
.
codeUnits
));
final
Stream
<
List
<
int
>>
stderrStream
=
Stream
<
List
<
int
>>.
fromIterable
(
stderr
.
map
<
List
<
int
>>((
String
s
)
=>
s
.
codeUnits
));
MockProcess
Function
(
List
<
String
>)
processMetaFactory
(
List
<
String
>
stdout
,
{
List
<
String
>
stderr
=
const
<
String
>[],
})
{
final
Stream
<
List
<
int
>>
stdoutStream
=
Stream
<
List
<
int
>>.
fromIterable
(
stdout
.
map
<
List
<
int
>>((
String
s
)
=>
s
.
codeUnits
,
));
final
Stream
<
List
<
int
>>
stderrStream
=
Stream
<
List
<
int
>>.
fromIterable
(
stderr
.
map
<
List
<
int
>>((
String
s
)
=>
s
.
codeUnits
,
));
return
(
List
<
String
>
command
)
=>
MockProcess
(
stdout:
stdoutStream
,
stderr:
stderrStream
);
}
test
Using
Context
(
'Command output is not wrapped.'
,
()
async
{
test
Without
Context
(
'Command output is not wrapped.'
,
()
async
{
final
List
<
String
>
testString
=
<
String
>[
'0123456789'
*
10
];
mockProcessManager
.
processFactory
=
processMetaFactory
(
testString
,
stderr:
testString
);
await
processUtils
.
stream
(<
String
>[
'command'
]);
expect
(
testLogger
.
statusText
,
equals
(
'
${testString[0]}
\n
'
));
expect
(
testLogger
.
errorText
,
equals
(
'
${testString[0]}
\n
'
));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
OutputPreferences:
()
=>
OutputPreferences
(
wrapText:
true
,
wrapColumn:
40
),
Platform:
()
=>
FakePlatform
.
fromPlatform
(
const
LocalPlatform
())..
stdoutSupportsAnsi
=
false
,
expect
(
mockLogger
.
statusText
,
equals
(
'
${testString[0]}
\n
'
));
expect
(
mockLogger
.
errorText
,
equals
(
'
${testString[0]}
\n
'
));
});
});
...
...
@@ -99,43 +122,47 @@ void main() {
const
Duration
delay
=
Duration
(
seconds:
2
);
MockProcessManager
flakyProcessManager
;
ProcessManager
mockProcessManager
;
ProcessUtils
processUtils
;
ProcessUtils
flakyProcessUtils
;
setUp
(()
{
// MockProcessManager has an implementation of start() that returns the
// result of processFactory.
flakyProcessManager
=
MockProcessManager
();
mockProcessManager
=
MockProcessManager
();
processUtils
=
ProcessUtils
(
processManager:
mockProcessManager
,
logger:
MockLogger
(),
);
flakyProcessUtils
=
ProcessUtils
(
processManager:
flakyProcessManager
,
logger:
MockLogger
(),
);
});
test
Using
Context
(
' succeeds on success'
,
()
async
{
test
Without
Context
(
' succeeds on success'
,
()
async
{
when
(
mockProcessManager
.
run
(<
String
>[
'whoohoo'
])).
thenAnswer
((
_
)
{
return
Future
<
ProcessResult
>.
value
(
ProcessResult
(
0
,
0
,
''
,
''
));
});
expect
((
await
processUtils
.
run
(<
String
>[
'whoohoo'
])).
exitCode
,
0
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' fails on failure'
,
()
async
{
test
Without
Context
(
' fails on failure'
,
()
async
{
when
(
mockProcessManager
.
run
(<
String
>[
'boohoo'
])).
thenAnswer
((
_
)
{
return
Future
<
ProcessResult
>.
value
(
ProcessResult
(
0
,
1
,
''
,
''
));
});
expect
((
await
processUtils
.
run
(<
String
>[
'boohoo'
])).
exitCode
,
1
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' throws on failure with throwOnError'
,
()
async
{
test
Without
Context
(
' throws on failure with throwOnError'
,
()
async
{
when
(
mockProcessManager
.
run
(<
String
>[
'kaboom'
])).
thenAnswer
((
_
)
{
return
Future
<
ProcessResult
>.
value
(
ProcessResult
(
0
,
1
,
''
,
''
));
});
expect
(()
=>
processUtils
.
run
(<
String
>[
'kaboom'
],
throwOnError:
true
),
throwsA
(
isA
<
ProcessException
>()));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' does not throw on failure with whitelist'
,
()
async
{
test
Without
Context
(
' does not throw on failure with whitelist'
,
()
async
{
when
(
mockProcessManager
.
run
(<
String
>[
'kaboom'
])).
thenAnswer
((
_
)
{
return
Future
<
ProcessResult
>.
value
(
ProcessResult
(
0
,
1
,
''
,
''
));
});
...
...
@@ -145,12 +172,11 @@ void main() {
throwOnError:
true
,
whiteListFailures:
(
int
c
)
=>
c
==
1
,
)).
exitCode
,
1
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
1
,
);
});
test
Using
Context
(
' throws on failure when not in whitelist'
,
()
async
{
test
Without
Context
(
' throws on failure when not in whitelist'
,
()
async
{
when
(
mockProcessManager
.
run
(<
String
>[
'kaboom'
])).
thenAnswer
((
_
)
{
return
Future
<
ProcessResult
>.
value
(
ProcessResult
(
0
,
2
,
''
,
''
));
});
...
...
@@ -160,41 +186,36 @@ void main() {
throwOnError:
true
,
whiteListFailures:
(
int
c
)
=>
c
==
1
,
),
throwsA
(
isA
<
ProcessException
>()));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
throwsA
(
isA
<
ProcessException
>()),
);
});
test
Using
Context
(
' flaky process fails without retry'
,
()
async
{
test
Without
Context
(
' flaky process fails without retry'
,
()
async
{
flakyProcessManager
.
processFactory
=
flakyProcessFactory
(
flakes:
1
,
delay:
delay
,
);
final
RunResult
result
=
await
p
rocessUtils
.
run
(
final
RunResult
result
=
await
flakyP
rocessUtils
.
run
(
<
String
>[
'dummy'
],
timeout:
delay
+
const
Duration
(
seconds:
1
),
);
expect
(
result
.
exitCode
,
-
9
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
flakyProcessManager
,
});
test
Using
Context
(
' flaky process succeeds with retry'
,
()
async
{
test
Without
Context
(
' flaky process succeeds with retry'
,
()
async
{
flakyProcessManager
.
processFactory
=
flakyProcessFactory
(
flakes:
1
,
delay:
delay
,
);
final
RunResult
result
=
await
p
rocessUtils
.
run
(
final
RunResult
result
=
await
flakyP
rocessUtils
.
run
(
<
String
>[
'dummy'
],
timeout:
delay
-
const
Duration
(
milliseconds:
500
),
timeoutRetries:
1
,
);
expect
(
result
.
exitCode
,
0
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
flakyProcessManager
,
});
test
Using
Context
(
' flaky process generates ProcessException on timeout'
,
()
async
{
test
Without
Context
(
' flaky process generates ProcessException on timeout'
,
()
async
{
final
Completer
<
List
<
int
>>
flakyStderr
=
Completer
<
List
<
int
>>();
final
Completer
<
List
<
int
>>
flakyStdout
=
Completer
<
List
<
int
>>();
flakyProcessManager
.
processFactory
=
flakyProcessFactory
(
...
...
@@ -211,52 +232,57 @@ void main() {
flakyStdout
.
complete
(<
int
>[]);
return
true
;
});
expect
(()
=>
p
rocessUtils
.
run
(
expect
(()
=>
flakyP
rocessUtils
.
run
(
<
String
>[
'dummy'
],
timeout:
delay
-
const
Duration
(
milliseconds:
500
),
timeoutRetries:
0
,
),
throwsA
(
isInstanceOf
<
ProcessException
>()));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
flakyProcessManager
,
});
});
group
(
'runSync'
,
()
{
ProcessManager
mockProcessManager
;
ProcessUtils
processUtils
;
BufferLogger
testLogger
;
setUp
(()
{
mockProcessManager
=
MockProcessManager
();
testLogger
=
BufferLogger
(
terminal:
AnsiTerminal
(
stdio:
MockStdio
(),
platform:
FakePlatform
.
fromPlatform
(
const
LocalPlatform
())..
stdoutSupportsAnsi
=
false
,
),
outputPreferences:
OutputPreferences
(
wrapText:
true
,
wrapColumn:
40
),
);
processUtils
=
ProcessUtils
(
processManager:
mockProcessManager
,
logger:
testLogger
,
);
});
test
Using
Context
(
' succeeds on success'
,
()
async
{
test
Without
Context
(
' succeeds on success'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'whoohoo'
])).
thenReturn
(
ProcessResult
(
0
,
0
,
''
,
''
)
);
expect
(
processUtils
.
runSync
(<
String
>[
'whoohoo'
]).
exitCode
,
0
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' fails on failure'
,
()
async
{
test
Without
Context
(
' fails on failure'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'boohoo'
])).
thenReturn
(
ProcessResult
(
0
,
1
,
''
,
''
)
);
expect
(
processUtils
.
runSync
(<
String
>[
'boohoo'
]).
exitCode
,
1
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' throws on failure with throwOnError'
,
()
async
{
test
Without
Context
(
' throws on failure with throwOnError'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'kaboom'
])).
thenReturn
(
ProcessResult
(
0
,
1
,
''
,
''
)
);
expect
(()
=>
processUtils
.
runSync
(<
String
>[
'kaboom'
],
throwOnError:
true
),
throwsA
(
isA
<
ProcessException
>()));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' does not throw on failure with whitelist'
,
()
async
{
test
Without
Context
(
' does not throw on failure with whitelist'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'kaboom'
])).
thenReturn
(
ProcessResult
(
0
,
1
,
''
,
''
)
);
...
...
@@ -267,11 +293,9 @@ void main() {
whiteListFailures:
(
int
c
)
=>
c
==
1
,
).
exitCode
,
1
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' throws on failure when not in whitelist'
,
()
async
{
test
Without
Context
(
' throws on failure when not in whitelist'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'kaboom'
])).
thenReturn
(
ProcessResult
(
0
,
2
,
''
,
''
)
);
...
...
@@ -282,22 +306,18 @@ void main() {
whiteListFailures:
(
int
c
)
=>
c
==
1
,
),
throwsA
(
isA
<
ProcessException
>()));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' prints stdout and stderr to trace on success'
,
()
async
{
test
Without
Context
(
' prints stdout and stderr to trace on success'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'whoohoo'
])).
thenReturn
(
ProcessResult
(
0
,
0
,
'stdout'
,
'stderr'
)
);
expect
(
processUtils
.
runSync
(<
String
>[
'whoohoo'
]).
exitCode
,
0
);
expect
(
testLogger
.
traceText
,
contains
(
'stdout'
));
expect
(
testLogger
.
traceText
,
contains
(
'stderr'
));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' prints stdout to status and stderr to error on failure with throwOnError'
,
()
async
{
test
Without
Context
(
' prints stdout to status and stderr to error on failure with throwOnError'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'kaboom'
])).
thenReturn
(
ProcessResult
(
0
,
1
,
'stdout'
,
'stderr'
)
);
...
...
@@ -305,71 +325,69 @@ void main() {
throwsA
(
isA
<
ProcessException
>()));
expect
(
testLogger
.
statusText
,
contains
(
'stdout'
));
expect
(
testLogger
.
errorText
,
contains
(
'stderr'
));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' does not print stdout with hideStdout'
,
()
async
{
test
Without
Context
(
' does not print stdout with hideStdout'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'whoohoo'
])).
thenReturn
(
ProcessResult
(
0
,
0
,
'stdout'
,
'stderr'
)
);
expect
(
processUtils
.
runSync
(<
String
>[
'whoohoo'
],
hideStdout:
true
).
exitCode
,
0
);
expect
(
testLogger
.
traceText
.
contains
(
'stdout'
),
isFalse
);
expect
(
testLogger
.
traceText
,
contains
(
'stderr'
));
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
});
group
(
'exitsHappySync'
,
()
{
ProcessManager
mockProcessManager
;
ProcessUtils
processUtils
;
setUp
(()
{
mockProcessManager
=
MockProcessManager
();
processUtils
=
ProcessUtils
(
processManager:
mockProcessManager
,
logger:
MockLogger
(),
);
});
test
Using
Context
(
' succeeds on success'
,
()
async
{
test
Without
Context
(
' succeeds on success'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'whoohoo'
])).
thenReturn
(
ProcessResult
(
0
,
0
,
''
,
''
)
);
expect
(
processUtils
.
exitsHappySync
(<
String
>[
'whoohoo'
]),
isTrue
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' fails on failure'
,
()
async
{
test
Without
Context
(
' fails on failure'
,
()
async
{
when
(
mockProcessManager
.
runSync
(<
String
>[
'boohoo'
])).
thenReturn
(
ProcessResult
(
0
,
1
,
''
,
''
)
);
expect
(
processUtils
.
exitsHappySync
(<
String
>[
'boohoo'
]),
isFalse
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
});
group
(
'exitsHappy'
,
()
{
ProcessManager
mockProcessManager
;
ProcessUtils
processUtils
;
setUp
(()
{
mockProcessManager
=
MockProcessManager
();
processUtils
=
ProcessUtils
(
processManager:
mockProcessManager
,
logger:
MockLogger
(),
);
});
test
Using
Context
(
' succeeds on success'
,
()
async
{
test
Without
Context
(
' succeeds on success'
,
()
async
{
when
(
mockProcessManager
.
run
(<
String
>[
'whoohoo'
])).
thenAnswer
((
_
)
{
return
Future
<
ProcessResult
>.
value
(
ProcessResult
(
0
,
0
,
''
,
''
));
});
expect
(
await
processUtils
.
exitsHappy
(<
String
>[
'whoohoo'
]),
isTrue
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
test
Using
Context
(
' fails on failure'
,
()
async
{
test
Without
Context
(
' fails on failure'
,
()
async
{
when
(
mockProcessManager
.
run
(<
String
>[
'boohoo'
])).
thenAnswer
((
_
)
{
return
Future
<
ProcessResult
>.
value
(
ProcessResult
(
0
,
1
,
''
,
''
));
});
expect
(
await
processUtils
.
exitsHappy
(<
String
>[
'boohoo'
]),
isFalse
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment