@@ -10,6 +10,16 @@ import '../framework/devices.dart';
1010import '../framework/framework.dart' ;
1111import '../framework/task_result.dart' ;
1212import '../framework/utils.dart' ;
13+ import 'build_test_task.dart' ;
14+
15+ final Directory galleryDirectory = dir ('${flutterDirectory .path }/dev/integration_tests/flutter_gallery' );
16+
17+ /// Temp function during gallery tests transition to build+test model.
18+ ///
19+ /// https://github.com/flutter/flutter/issues/103542
20+ TaskFunction createGalleryTransitionBuildTest (List <String > args, {bool semanticsEnabled = false }) {
21+ return GalleryTransitionBuildTest (args, semanticsEnabled: semanticsEnabled);
22+ }
1323
1424TaskFunction createGalleryTransitionTest ({bool semanticsEnabled = false }) {
1525 return GalleryTransitionTest (semanticsEnabled: semanticsEnabled);
@@ -176,6 +186,137 @@ class GalleryTransitionTest {
176186 }
177187}
178188
189+ class GalleryTransitionBuildTest extends BuildTestTask {
190+ GalleryTransitionBuildTest (
191+ super .args, {
192+ this .semanticsEnabled = false ,
193+ this .testFile = 'transitions_perf' ,
194+ this .needFullTimeline = true ,
195+ this .timelineSummaryFile = 'transitions.timeline_summary' ,
196+ this .timelineTraceFile = 'transitions.timeline' ,
197+ this .transitionDurationFile = 'transition_durations.timeline' ,
198+ this .driverFile,
199+ this .measureCpuGpu = true ,
200+ this .measureMemory = true ,
201+ }) : super (workingDirectory: galleryDirectory);
202+
203+ final bool semanticsEnabled;
204+ final bool needFullTimeline;
205+ final bool measureCpuGpu;
206+ final bool measureMemory;
207+ final String testFile;
208+ final String timelineSummaryFile;
209+ final String ? timelineTraceFile;
210+ final String ? transitionDurationFile;
211+ final String ? driverFile;
212+
213+ final String testOutputDirectory = Platform .environment['FLUTTER_TEST_OUTPUTS_DIR' ] ?? '${galleryDirectory .path }/build' ;
214+
215+ @override
216+ List <String > getBuildArgs (DeviceOperatingSystem deviceOperatingSystem) {
217+ return < String > [
218+ 'apk' ,
219+ '--no-android-gradle-daemon' ,
220+ '--profile' ,
221+ '-t' ,
222+ 'test_driver/$testFile .dart' ,
223+ '--target-platform' ,
224+ 'android-arm,android-arm64' ,
225+ ];
226+ }
227+
228+ @override
229+ List <String > getTestArgs (DeviceOperatingSystem deviceOperatingSystem, String deviceId) {
230+ final String testDriver = driverFile ?? (semanticsEnabled ? '${testFile }_with_semantics_test' : '${testFile }_test' );
231+ return < String > [
232+ '--profile' ,
233+ if (needFullTimeline) '--trace-startup' ,
234+ '-t' ,
235+ 'test_driver/$testFile .dart' ,
236+ '--use-application-binary=${getApplicationBinaryPath ()}' ,
237+ '--driver' ,
238+ 'test_driver/$testDriver .dart' ,
239+ '-d' ,
240+ deviceId,
241+ ];
242+ }
243+
244+ @override
245+ Future <TaskResult > parseTaskResult () async {
246+ final Map <String , dynamic > summary = json.decode (
247+ file ('$testOutputDirectory /$timelineSummaryFile .json' ).readAsStringSync (),
248+ ) as Map <String , dynamic >;
249+
250+ if (transitionDurationFile != null ) {
251+ final Map <String , dynamic > original = json.decode (
252+ file ('$testOutputDirectory /$transitionDurationFile .json' ).readAsStringSync (),
253+ ) as Map <String , dynamic >;
254+ final Map <String , List <int >> transitions = < String , List <int >> {};
255+ for (final String key in original.keys) {
256+ transitions[key] = List <int >.from (original[key] as List <dynamic >);
257+ }
258+ summary['transitions' ] = transitions;
259+ summary['missed_transition_count' ] = _countMissedTransitions (transitions);
260+ }
261+
262+ final bool isAndroid = deviceOperatingSystem == DeviceOperatingSystem .android;
263+ return TaskResult .success (
264+ summary,
265+ detailFiles: < String > [
266+ if (transitionDurationFile != null ) '$testOutputDirectory /$transitionDurationFile .json' ,
267+ if (timelineTraceFile != null ) '$testOutputDirectory /$timelineTraceFile .json' ,
268+ ],
269+ benchmarkScoreKeys: < String > [
270+ if (transitionDurationFile != null ) 'missed_transition_count' ,
271+ 'average_frame_build_time_millis' ,
272+ 'worst_frame_build_time_millis' ,
273+ '90th_percentile_frame_build_time_millis' ,
274+ '99th_percentile_frame_build_time_millis' ,
275+ 'average_frame_rasterizer_time_millis' ,
276+ 'worst_frame_rasterizer_time_millis' ,
277+ '90th_percentile_frame_rasterizer_time_millis' ,
278+ '99th_percentile_frame_rasterizer_time_millis' ,
279+ 'average_layer_cache_count' ,
280+ '90th_percentile_layer_cache_count' ,
281+ '99th_percentile_layer_cache_count' ,
282+ 'worst_layer_cache_count' ,
283+ 'average_layer_cache_memory' ,
284+ '90th_percentile_layer_cache_memory' ,
285+ '99th_percentile_layer_cache_memory' ,
286+ 'worst_layer_cache_memory' ,
287+ 'average_picture_cache_count' ,
288+ '90th_percentile_picture_cache_count' ,
289+ '99th_percentile_picture_cache_count' ,
290+ 'worst_picture_cache_count' ,
291+ 'average_picture_cache_memory' ,
292+ '90th_percentile_picture_cache_memory' ,
293+ '99th_percentile_picture_cache_memory' ,
294+ 'worst_picture_cache_memory' ,
295+ if (measureCpuGpu && ! isAndroid) ...< String > [
296+ // See https://github.com/flutter/flutter/issues/68888
297+ if (summary['average_cpu_usage' ] != null ) 'average_cpu_usage' ,
298+ if (summary['average_gpu_usage' ] != null ) 'average_gpu_usage' ,
299+ ],
300+ if (measureMemory && ! isAndroid) ...< String > [
301+ // See https://github.com/flutter/flutter/issues/68888
302+ if (summary['average_memory_usage' ] != null ) 'average_memory_usage' ,
303+ if (summary['90th_percentile_memory_usage' ] != null ) '90th_percentile_memory_usage' ,
304+ if (summary['99th_percentile_memory_usage' ] != null ) '99th_percentile_memory_usage' ,
305+ ],
306+ ],
307+ );
308+ }
309+
310+ @override
311+ String getApplicationBinaryPath () {
312+ if (applicationBinaryPath != null ) {
313+ return applicationBinaryPath! ;
314+ }
315+
316+ return 'build/app/outputs/flutter-apk/app-profile.apk' ;
317+ }
318+ }
319+
179320int _countMissedTransitions (Map <String , List <int >> transitions) {
180321 const int kTransitionBudget = 100000 ; // µs
181322 int count = 0 ;
0 commit comments