| // Copyright 2014 The Flutter 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 'dart:convert'; |
| import 'dart:io'; |
| |
| import 'package:flutter_driver/flutter_driver.dart'; |
| import 'package:path/path.dart' as p; |
| import 'package:test/test.dart' hide TypeMatcher, isInstanceOf; |
| |
| void main() { |
| group('semantics performance test', () { |
| late FlutterDriver driver; |
| |
| setUpAll(() async { |
| // Turn off any accessibility services that may be running. The purpose of |
| // the test is to measure the time it takes to create the initial |
| // semantics tree in isolation. If accessibility services are on, the |
| // semantics tree gets generated during the first frame and we can't |
| // measure it in isolation. |
| final Process run = await Process.start(_adbPath(), const <String>[ |
| 'shell', |
| 'settings', |
| 'put', |
| 'secure', |
| 'enabled_accessibility_services', |
| 'null', |
| ]); |
| await run.exitCode; |
| |
| driver = await FlutterDriver.connect(printCommunication: true); |
| }); |
| |
| tearDownAll(() async { |
| if (driver != null) { |
| driver.close(); |
| } |
| }); |
| |
| test('initial tree creation', () async { |
| // Let app become fully idle. |
| await Future<void>.delayed(const Duration(seconds: 2)); |
| |
| await driver.forceGC(); |
| |
| final Timeline timeline = await driver.traceAction(() async { |
| expect( |
| await driver.setSemantics(true), |
| isTrue, |
| reason: 'Could not toggle semantics to on because semantics were already ' |
| 'on, but the test needs to toggle semantics to measure the initial ' |
| 'semantics tree generation in isolation.' |
| ); |
| }); |
| |
| final Iterable<TimelineEvent>? semanticsEvents = timeline.events?.where((TimelineEvent event) => event.name == 'SEMANTICS'); |
| if (semanticsEvents?.length != 2) { |
| fail('Expected exactly two "SEMANTICS" events, got ${semanticsEvents?.length}:\n$semanticsEvents'); |
| } |
| final Duration semanticsTreeCreation = Duration(microseconds: semanticsEvents!.last.timestampMicros! - semanticsEvents.first.timestampMicros!); |
| |
| final String jsonEncoded = json.encode(<String, dynamic>{'initialSemanticsTreeCreation': semanticsTreeCreation.inMilliseconds}); |
| File(p.join(testOutputsDirectory, 'complex_layout_semantics_perf.json')).writeAsStringSync(jsonEncoded); |
| }, timeout: Timeout.none); |
| }); |
| } |
| |
| String _adbPath() { |
| final String? androidHome = Platform.environment['ANDROID_HOME'] ?? Platform.environment['ANDROID_SDK_ROOT']; |
| if (androidHome == null) { |
| return 'adb'; |
| } else { |
| return p.join(androidHome, 'platform-tools', 'adb'); |
| } |
| } |