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
9d364043
Unverified
Commit
9d364043
authored
Apr 26, 2019
by
Jonah Williams
Committed by
GitHub
Apr 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor the test compiler into a separate library (#31642)
parent
d121df99
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
311 additions
and
196 deletions
+311
-196
flutter_platform.dart
packages/flutter_tools/lib/src/test/flutter_platform.dart
+42
-196
test_compiler.dart
packages/flutter_tools/lib/src/test/test_compiler.dart
+184
-0
test_compiler_test.dart
packages/flutter_tools/test/test_compiler_test.dart
+85
-0
No files found.
packages/flutter_tools/lib/src/test/flutter_platform.dart
View file @
9d364043
This diff is collapsed.
Click to expand it.
packages/flutter_tools/lib/src/test/test_compiler.dart
0 → 100644
View file @
9d364043
// 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
'dart:async'
;
import
'package:meta/meta.dart'
;
import
'../artifacts.dart'
;
import
'../base/file_system.dart'
;
import
'../base/terminal.dart'
;
import
'../build_info.dart'
;
import
'../bundle.dart'
;
import
'../codegen.dart'
;
import
'../compile.dart'
;
import
'../dart/package_map.dart'
;
import
'../globals.dart'
;
import
'../project.dart'
;
/// A request to the [TestCompiler] for recompilation.
class
_CompilationRequest
{
_CompilationRequest
(
this
.
path
,
this
.
result
);
String
path
;
Completer
<
String
>
result
;
}
/// A frontend_server wrapper for the flutter test runner.
///
/// This class is a wrapper around compiler that allows multiple isolates to
/// enqueue compilation requests, but ensures only one compilation at a time.
class
TestCompiler
{
/// Creates a new [TestCompiler] which acts as a frontend_server proxy.
///
/// [trackWidgetCreation] configures whether the kernel transform is applied
/// to the output. This also changes the output file to include a '.track`
/// extension.
///
/// [flutterProject] is the project for which we are running tests.
TestCompiler
(
this
.
trackWidgetCreation
,
this
.
flutterProject
,
)
:
testFilePath
=
getKernelPathForTransformerOptions
(
fs
.
path
.
join
(
flutterProject
.
directory
.
path
,
getBuildDirectory
(),
'testfile.dill'
),
trackWidgetCreation:
trackWidgetCreation
,
)
{
// Compiler maintains and updates single incremental dill file.
// Incremental compilation requests done for each test copy that file away
// for independent execution.
final
Directory
outputDillDirectory
=
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_test_compiler.'
);
outputDill
=
outputDillDirectory
.
childFile
(
'output.dill'
);
printTrace
(
'Compiler will use the following file as its incremental dill file:
${outputDill.path}
'
);
printTrace
(
'Listening to compiler controller...'
);
compilerController
.
stream
.
listen
(
_onCompilationRequest
,
onDone:
()
{
printTrace
(
'Deleting
${outputDillDirectory.path}
...'
);
outputDillDirectory
.
deleteSync
(
recursive:
true
);
});
}
final
StreamController
<
_CompilationRequest
>
compilerController
=
StreamController
<
_CompilationRequest
>();
final
List
<
_CompilationRequest
>
compilationQueue
=
<
_CompilationRequest
>[];
final
FlutterProject
flutterProject
;
final
bool
trackWidgetCreation
;
final
String
testFilePath
;
ResidentCompiler
compiler
;
File
outputDill
;
// Whether to report compiler messages.
bool
_suppressOutput
=
false
;
Future
<
String
>
compile
(
String
mainDart
)
{
final
Completer
<
String
>
completer
=
Completer
<
String
>();
compilerController
.
add
(
_CompilationRequest
(
mainDart
,
completer
));
return
completer
.
future
;
}
Future
<
void
>
_shutdown
()
async
{
// Check for null in case this instance is shut down before the
// lazily-created compiler has been created.
if
(
compiler
!=
null
)
{
await
compiler
.
shutdown
();
compiler
=
null
;
}
}
Future
<
void
>
dispose
()
async
{
await
compilerController
.
close
();
}
/// Create the resident compiler used to compile the test.
@visibleForTesting
Future
<
ResidentCompiler
>
createCompiler
()
async
{
if
(
flutterProject
.
hasBuilders
)
{
return
CodeGeneratingResidentCompiler
.
create
(
flutterProject:
flutterProject
,
trackWidgetCreation:
trackWidgetCreation
,
compilerMessageConsumer:
_reportCompilerMessage
,
initializeFromDill:
testFilePath
,
// We already ran codegen once at the start, we only need to
// configure builders.
runCold:
true
,
);
}
return
ResidentCompiler
(
artifacts
.
getArtifactPath
(
Artifact
.
flutterPatchedSdkPath
),
packagesPath:
PackageMap
.
globalPackagesPath
,
trackWidgetCreation:
trackWidgetCreation
,
compilerMessageConsumer:
_reportCompilerMessage
,
initializeFromDill:
testFilePath
,
unsafePackageSerialization:
false
,
);
}
// Handle a compilation request.
Future
<
void
>
_onCompilationRequest
(
_CompilationRequest
request
)
async
{
final
bool
isEmpty
=
compilationQueue
.
isEmpty
;
compilationQueue
.
add
(
request
);
// Only trigger processing if queue was empty - i.e. no other requests
// are currently being processed. This effectively enforces "one
// compilation request at a time".
if
(!
isEmpty
)
{
return
;
}
while
(
compilationQueue
.
isNotEmpty
)
{
final
_CompilationRequest
request
=
compilationQueue
.
first
;
printTrace
(
'Compiling
${request.path}
'
);
final
Stopwatch
compilerTime
=
Stopwatch
()..
start
();
bool
firstCompile
=
false
;
if
(
compiler
==
null
)
{
compiler
=
await
createCompiler
();
firstCompile
=
true
;
}
_suppressOutput
=
false
;
final
CompilerOutput
compilerOutput
=
await
compiler
.
recompile
(
request
.
path
,
<
Uri
>[
Uri
.
parse
(
request
.
path
)],
outputPath:
outputDill
.
path
,
);
final
String
outputPath
=
compilerOutput
?.
outputFilename
;
// In case compiler didn't produce output or reported compilation
// errors, pass [null] upwards to the consumer and shutdown the
// compiler to avoid reusing compiler that might have gotten into
// a weird state.
if
(
outputPath
==
null
||
compilerOutput
.
errorCount
>
0
)
{
request
.
result
.
complete
(
null
);
await
_shutdown
();
}
else
{
final
File
outputFile
=
fs
.
file
(
outputPath
);
final
File
kernelReadyToRun
=
await
outputFile
.
copy
(
'
${request.path}
.dill'
);
final
File
testCache
=
fs
.
file
(
testFilePath
);
if
(
firstCompile
||
!
testCache
.
existsSync
()
||
(
testCache
.
lengthSync
()
<
outputFile
.
lengthSync
()))
{
// The idea is to keep the cache file up-to-date and include as
// much as possible in an effort to re-use as many packages as
// possible.
ensureDirectoryExists
(
testFilePath
);
await
outputFile
.
copy
(
testFilePath
);
}
request
.
result
.
complete
(
kernelReadyToRun
.
path
);
compiler
.
accept
();
compiler
.
reset
();
}
printTrace
(
'Compiling
${request.path}
took
${compilerTime.elapsedMilliseconds}
ms'
);
// Only remove now when we finished processing the element
compilationQueue
.
removeAt
(
0
);
}
}
void
_reportCompilerMessage
(
String
message
,
{
bool
emphasis
,
TerminalColor
color
})
{
if
(
_suppressOutput
)
{
return
;
}
if
(
message
.
startsWith
(
'Error: Could not resolve the package
\'
flutter_test
\'
'
))
{
printTrace
(
message
);
printError
(
'
\n\n
Failed to load test harness. Are you missing a dependency on flutter_test?
\n
'
,
emphasis:
emphasis
,
color:
color
,
);
_suppressOutput
=
true
;
return
;
}
printError
(
'
$message
'
);
}
}
packages/flutter_tools/test/test_compiler_test.dart
0 → 100644
View file @
9d364043
// 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:file/memory.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/compile.dart'
;
import
'package:flutter_tools/src/project.dart'
;
import
'package:flutter_tools/src/test/test_compiler.dart'
;
import
'package:mockito/mockito.dart'
;
import
'src/common.dart'
;
import
'src/context.dart'
;
void
main
(
)
{
group
(
'TestCompiler'
,
()
{
testUsingContext
(
'compiles test file with no errors'
,
()
async
{
fs
.
file
(
'pubspec.yaml'
).
createSync
();
fs
.
file
(
'.packages'
).
createSync
();
fs
.
file
(
'test/foo.dart'
).
createSync
(
recursive:
true
);
final
MockResidentCompiler
residentCompiler
=
MockResidentCompiler
();
final
TestCompiler
testCompiler
=
FakeTestCompiler
(
false
,
await
FlutterProject
.
current
(),
residentCompiler
,
);
when
(
residentCompiler
.
recompile
(
'test/foo.dart'
,
<
Uri
>[
Uri
.
parse
(
'test/foo.dart'
)],
outputPath:
testCompiler
.
outputDill
.
path
,
)).
thenAnswer
((
Invocation
invocation
)
async
{
fs
.
file
(
'abc.dill'
).
createSync
();
return
CompilerOutput
(
'abc.dill'
,
0
,
<
Uri
>[]);
});
expect
(
await
testCompiler
.
compile
(
'test/foo.dart'
),
'test/foo.dart.dill'
);
expect
(
fs
.
file
(
'test/foo.dart.dill'
).
existsSync
(),
true
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
});
testUsingContext
(
'does not compile test file with errors'
,
()
async
{
fs
.
file
(
'pubspec.yaml'
).
createSync
();
fs
.
file
(
'.packages'
).
createSync
();
fs
.
file
(
'test/foo.dart'
).
createSync
(
recursive:
true
);
final
MockResidentCompiler
residentCompiler
=
MockResidentCompiler
();
final
TestCompiler
testCompiler
=
FakeTestCompiler
(
false
,
await
FlutterProject
.
current
(),
residentCompiler
,
);
when
(
residentCompiler
.
recompile
(
'test/foo.dart'
,
<
Uri
>[
Uri
.
parse
(
'test/foo.dart'
)],
outputPath:
testCompiler
.
outputDill
.
path
,
)).
thenAnswer
((
Invocation
invocation
)
async
{
fs
.
file
(
'abc.dill'
).
createSync
();
return
CompilerOutput
(
'abc.dill'
,
1
,
<
Uri
>[]);
});
expect
(
await
testCompiler
.
compile
(
'test/foo.dart'
),
null
);
expect
(
fs
.
file
(
'test/foo.dart.dill'
).
existsSync
(),
false
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
});
});
}
/// Override the creation of the Resident Compiler to simplify testing.
class
FakeTestCompiler
extends
TestCompiler
{
FakeTestCompiler
(
bool
trackWidgetCreation
,
FlutterProject
flutterProject
,
this
.
residentCompiler
,
)
:
super
(
trackWidgetCreation
,
flutterProject
);
final
MockResidentCompiler
residentCompiler
;
@override
Future
<
ResidentCompiler
>
createCompiler
()
async
{
return
residentCompiler
;
}
}
class
MockResidentCompiler
extends
Mock
implements
ResidentCompiler
{}
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