semantics_perf_test.dart 2.74 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8 9 10
// 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;
11
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
12 13 14

void main() {
  group('semantics performance test', () {
15
    late FlutterDriver driver;
16 17

    setUpAll(() async {
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
      // 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;

33 34 35 36
      driver = await FlutterDriver.connect(printCommunication: true);
    });

    tearDownAll(() async {
37
      if (driver != null) {
38
        driver.close();
39
      }
40 41
    });

42
    test('initial tree creation', () async {
43
      // Let app become fully idle.
44
      await Future<void>.delayed(const Duration(seconds: 2));
45

46 47
      await driver.forceGC();

48
      final Timeline timeline = await driver.traceAction(() async {
49 50 51 52 53 54 55
        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.'
        );
56 57
      });

58
      final Iterable<TimelineEvent>? semanticsEvents = timeline.events?.where((TimelineEvent event) => event.name == 'SEMANTICS');
59
      if (semanticsEvents?.length != 2) {
60
        fail('Expected exactly two "SEMANTICS" events, got ${semanticsEvents?.length}:\n$semanticsEvents');
61
      }
62
      final Duration semanticsTreeCreation = Duration(microseconds: semanticsEvents!.last.timestampMicros! - semanticsEvents.first.timestampMicros!);
63

64
      final String jsonEncoded = json.encode(<String, dynamic>{'initialSemanticsTreeCreation': semanticsTreeCreation.inMilliseconds});
65
      File(p.join(testOutputsDirectory, 'complex_layout_semantics_perf.json')).writeAsStringSync(jsonEncoded);
66
    }, timeout: Timeout.none);
67 68
  });
}
69 70 71 72 73 74 75 76 77

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');
  }
}