service_extensions_test.dart 4.6 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 11
// 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_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/utils.dart';
12
import 'package:path/path.dart' as path;
13
import 'package:vm_service_client/vm_service_client.dart';
14 15 16 17 18 19 20 21 22

void main() {
  task(() async {
    int vmServicePort;

    final Device device = await devices.workingDevice;
    await device.unlock();
    final Directory appDir = dir(path.join(flutterDirectory.path, 'dev/integration_tests/ui'));
    await inDirectory(appDir, () async {
23
      final Completer<void> ready = Completer<void>();
24 25 26 27
      bool ok;
      print('run: starting...');
      final Process run = await startProcess(
        path.join(flutterDirectory.path, 'bin', 'flutter'),
28
        <String>['run', '--verbose', '--disable-service-auth-codes', '-d', device.deviceId, 'lib/main.dart'],
29 30
      );
      run.stdout
31 32
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
33 34
          .listen((String line) {
        print('run:stdout: $line');
35
        if (vmServicePort == null) {
36
          vmServicePort = parseServicePort(line);
37 38 39 40 41 42
          if (vmServicePort != null) {
            print('service protocol connection available at port $vmServicePort');
            print('run: ready!');
            ready.complete();
            ok ??= true;
          }
43 44 45
        }
      });
      run.stderr
46 47
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
48 49 50
          .listen((String line) {
        stderr.writeln('run:stderr: $line');
      });
51
      run.exitCode.then<void>((int exitCode) { ok = false; });
52 53 54 55
      await Future.any<dynamic>(<Future<dynamic>>[ ready.future, run.exitCode ]);
      if (!ok)
        throw 'Failed to run test app.';

56
      final VMServiceClient client = VMServiceClient.connect('ws://localhost:$vmServicePort/ws');
57
      final VM vm = await client.getVM();
58
      final VMIsolateRef isolate = vm.isolates.first;
59

60 61 62 63
      final StreamController<VMExtensionEvent> frameEventsController = StreamController<VMExtensionEvent>();
      final StreamController<VMExtensionEvent> navigationEventsController = StreamController<VMExtensionEvent>();
      isolate.onExtensionEvent.listen((VMExtensionEvent event) {
        if (event.kind == 'Flutter.Frame') {
64
          frameEventsController.add(event);
65
        } else if (event.kind == 'Flutter.Navigation') {
66 67 68 69
          navigationEventsController.add(event);
        }
      });

70 71
      final Stream<VMExtensionEvent> frameEvents = frameEventsController.stream;
      final Stream<VMExtensionEvent> navigationEvents = navigationEventsController.stream;
72 73

      print('reassembling app...');
74 75
      final Future<VMExtensionEvent> frameFuture = frameEvents.first;
      await isolate.invokeExtension('ext.flutter.reassemble');
76 77

      // ensure we get an event
78 79
      final VMExtensionEvent event = await frameFuture;
      print('${event.kind}: ${event.data}');
80 81

      // validate the fields
82
      // {number: 8, startTime: 0, elapsed: 1437, build: 600, raster: 800}
83 84 85 86 87 88 89 90 91 92 93 94
      expect(event.data['number'] is int);
      expect(event.data['number'] >= 0);
      expect(event.data['startTime'] is int);
      expect(event.data['startTime'] >= 0);
      expect(event.data['elapsed'] is int);
      expect(event.data['elapsed'] >= 0);
      expect(event.data['build'] is int);
      expect(event.data['build'] >= 0);
      expect(event.data['raster'] is int);
      expect(event.data['raster'] >= 0);

      final Future<VMExtensionEvent> navigationFuture = navigationEvents.first;
95
      // This tap triggers a navigation event.
96
      device.tap(100, 200);
97

98
      final VMExtensionEvent navigationEvent = await navigationFuture;
99
      // validate the fields
100 101
      expect(navigationEvent.data['route'] is Map<dynamic, dynamic>);
      final Map<dynamic, dynamic> route = navigationEvent.data['route'];
102 103 104 105 106
      expect(route['description'] is String);
      expect(route['settings'] is Map<dynamic, dynamic>);
      final Map<dynamic, dynamic> settings = route['settings'];
      expect(settings.containsKey('name'));
      expect(settings['isInitialRoute'] is bool);
107

108 109 110 111 112
      run.stdin.write('q');
      final int result = await run.exitCode;
      if (result != 0)
        throw 'Received unexpected exit code $result from run process.';
    });
113
    return TaskResult.success(null);
114 115 116 117 118 119 120
  });
}

void expect(bool value) {
  if (!value)
    throw 'failed assertion in service extensions test';
}