service_extensions_test.dart 30.7 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
// @dart = 2.8

7 8 9 10 11 12 13 14 15 16 17
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
18
import '../flutter_test_alternative.dart';
19 20

class TestServiceExtensionsBinding extends BindingBase
21 22
  with SchedulerBinding,
       ServicesBinding,
23
       GestureBinding,
24
       PaintingBinding,
25
       SemanticsBinding,
26 27 28 29 30
       RendererBinding,
       WidgetsBinding {

  final Map<String, ServiceExtensionCallback> extensions = <String, ServiceExtensionCallback>{};

31 32
  final Map<String, List<Map<String, dynamic>>> eventsDispatched = <String, List<Map<String, dynamic>>>{};

33 34 35
  @override
  void registerServiceExtension({
    @required String name,
36
    @required ServiceExtensionCallback callback,
37 38 39 40 41
  }) {
    expect(extensions.containsKey(name), isFalse);
    extensions[name] = callback;
  }

42
  @override
43
  void postEvent(String eventKind, Map<String, dynamic> eventData) {
44 45 46 47 48 49 50 51 52 53 54 55
    getEventsDispatched(eventKind).add(eventData);
  }

  List<Map<String, dynamic>> getEventsDispatched(String eventKind) {
    return eventsDispatched.putIfAbsent(eventKind, () => <Map<String, dynamic>>[]);
  }

  Iterable<Map<String, dynamic>> getServiceExtensionStateChangedEvents(String extensionName) {
    return getEventsDispatched('Flutter.ServiceExtensionStateChanged')
      .where((Map<String, dynamic> event) => event['extension'] == extensionName);
  }

56
  Future<Map<String, dynamic>> testExtension(String name, Map<String, String> arguments) {
57 58 59 60 61
    expect(extensions.containsKey(name), isTrue);
    return extensions[name](arguments);
  }

  int reassembled = 0;
62
  bool pendingReassemble = false;
63
  @override
64
  Future<void> performReassemble() {
65
    reassembled += 1;
66
    pendingReassemble = true;
67
    return super.performReassemble();
68 69 70 71 72
  }

  bool frameScheduled = false;
  @override
  void scheduleFrame() {
73
    ensureFrameCallbacksRegistered();
74 75
    frameScheduled = true;
  }
76
  Future<void> doFrame() async {
77 78
    frameScheduled = false;
    if (ui.window.onBeginFrame != null)
79
      ui.window.onBeginFrame(Duration.zero);
80 81 82
    await flushMicrotasks();
    if (ui.window.onDrawFrame != null)
      ui.window.onDrawFrame();
83 84
    if (ui.window.onReportTimings != null)
      ui.window.onReportTimings(<ui.FrameTiming>[]);
85 86
  }

87 88 89 90 91 92 93 94 95 96 97
  @override
  void scheduleForcedFrame() {
    expect(true, isFalse);
  }

  @override
  void scheduleWarmUpFrame() {
    expect(pendingReassemble, isTrue);
    pendingReassemble = false;
  }

98 99
  Future<void> flushMicrotasks() {
    final Completer<void> completer = Completer<void>();
100
    Timer.run(completer.complete);
101 102 103 104
    return completer.future;
  }
}

105 106
TestServiceExtensionsBinding binding;

107
Future<Map<String, dynamic>> hasReassemble(Future<Map<String, dynamic>> pendingResult) async {
108 109 110 111 112 113
  bool completed = false;
  pendingResult.whenComplete(() { completed = true; });
  expect(binding.frameScheduled, isFalse);
  await binding.flushMicrotasks();
  expect(binding.frameScheduled, isTrue);
  expect(completed, isFalse);
114
  await binding.flushMicrotasks();
115
  await binding.doFrame();
116 117 118 119 120 121
  await binding.flushMicrotasks();
  expect(completed, isTrue);
  expect(binding.frameScheduled, isFalse);
  return pendingResult;
}

122
void main() {
123
  final List<String> console = <String>[];
124

125
  setUpAll(() async {
126
    binding = TestServiceExtensionsBinding()..scheduleFrame();
127
    expect(binding.frameScheduled, isTrue);
128 129 130 131 132 133

    // We need to test this service extension here because the result is true
    // after the first binding.doFrame() call.
    Map<String, dynamic> firstFrameResult;
    expect(binding.debugDidSendFirstFrameEvent, isFalse);
    firstFrameResult = await binding.testExtension('didSendFirstFrameEvent', <String, String>{});
134
    expect(firstFrameResult, <String, String>{'enabled': 'false'});
135

136 137 138 139
    expect(binding.firstFrameRasterized, isFalse);
    firstFrameResult = await binding.testExtension('didSendFirstFrameRasterizedEvent', <String, String>{});
    expect(firstFrameResult, <String, String>{'enabled': 'false'});

140
    await binding.doFrame();
141 142 143

    expect(binding.debugDidSendFirstFrameEvent, isTrue);
    firstFrameResult = await binding.testExtension('didSendFirstFrameEvent', <String, String>{});
144
    expect(firstFrameResult, <String, String>{'enabled': 'true'});
145

146 147 148 149
    expect(binding.firstFrameRasterized, isTrue);
    firstFrameResult = await binding.testExtension('didSendFirstFrameRasterizedEvent', <String, String>{});
    expect(firstFrameResult, <String, String>{'enabled': 'true'});

150 151 152 153 154 155 156 157
    expect(binding.frameScheduled, isFalse);

    expect(debugPrint, equals(debugPrintThrottled));
    debugPrint = (String message, { int wrapWidth }) {
      console.add(message);
    };
  });

158 159 160
  tearDownAll(() async {
    // See widget_inspector_test.dart for tests of the ext.flutter.inspector
    // service extensions included in this count.
161
    int widgetInspectorExtensionCount = 16;
162 163 164 165 166 167
    if (WidgetInspectorService.instance.isWidgetCreationTracked()) {
      // Some inspector extensions are only exposed if widget creation locations
      // are tracked.
      widgetInspectorExtensionCount += 2;
    }

168 169
    // The following service extensions are disabled in web:
    // 1. exit
170 171
    // 2. showPerformanceOverlay
    const int disabledExtensions = kIsWeb ? 2 : 0;
172 173
    // If you add a service extension... TEST IT! :-)
    // ...then increment this number.
174
    expect(binding.extensions.length, 28 + widgetInspectorExtensionCount - disabledExtensions);
175 176 177 178 179

    expect(console, isEmpty);
    debugPrint = debugPrintThrottled;
  });

180 181 182
  // The following list is alphabetical, one test per extension.

  test('Service extensions - debugAllowBanner', () async {
183
    Map<String, dynamic> result;
184 185 186 187

    expect(binding.frameScheduled, isFalse);
    expect(WidgetsApp.debugAllowBannerOverride, true);
    result = await binding.testExtension('debugAllowBanner', <String, String>{});
188
    expect(result, <String, String>{'enabled': 'true'});
189
    expect(WidgetsApp.debugAllowBannerOverride, true);
190 191
    result = await binding.testExtension('debugAllowBanner', <String, String>{'enabled': 'false'});
    expect(result, <String, String>{'enabled': 'false'});
192 193
    expect(WidgetsApp.debugAllowBannerOverride, false);
    result = await binding.testExtension('debugAllowBanner', <String, String>{});
194
    expect(result, <String, String>{'enabled': 'false'});
195
    expect(WidgetsApp.debugAllowBannerOverride, false);
196 197
    result = await binding.testExtension('debugAllowBanner', <String, String>{'enabled': 'true'});
    expect(result, <String, String>{'enabled': 'true'});
198 199
    expect(WidgetsApp.debugAllowBannerOverride, true);
    result = await binding.testExtension('debugAllowBanner', <String, String>{});
200
    expect(result, <String, String>{'enabled': 'true'});
201 202 203 204
    expect(WidgetsApp.debugAllowBannerOverride, true);
    expect(binding.frameScheduled, isFalse);
  });

205 206 207 208 209 210 211 212 213
  test('Service extensions - debugCheckElevationsEnabled', () async {
    expect(binding.frameScheduled, isFalse);
    expect(debugCheckElevationsEnabled, false);

    bool lastValue = false;
    Future<void> _updateAndCheck(bool newValue) async {
      Map<String, dynamic> result;
      binding.testExtension(
        'debugCheckElevationsEnabled',
214
        <String, String>{'enabled': '$newValue'},
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
      ).then((Map<String, dynamic> answer) => result = answer);
      await binding.flushMicrotasks();
      expect(binding.frameScheduled, lastValue != newValue);
      await binding.doFrame();
      await binding.flushMicrotasks();
      expect(result, <String, String>{'enabled': '$newValue'});
      expect(debugCheckElevationsEnabled, newValue);
      lastValue = newValue;
    }

    await _updateAndCheck(false);
    await _updateAndCheck(true);
    await _updateAndCheck(true);
    await _updateAndCheck(false);
    await _updateAndCheck(false);
    expect(binding.frameScheduled, isFalse);
  });

233
  test('Service extensions - debugDumpApp', () async {
234
    Map<String, dynamic> result;
235 236 237 238 239 240 241 242

    result = await binding.testExtension('debugDumpApp', <String, String>{});
    expect(result, <String, String>{});
    expect(console, <String>['TestServiceExtensionsBinding - CHECKED MODE', '<no tree currently mounted>']);
    console.clear();
  });

  test('Service extensions - debugDumpRenderTree', () async {
243
    Map<String, dynamic> result;
244

245
    await binding.doFrame();
246 247
    result = await binding.testExtension('debugDumpRenderTree', <String, String>{});
    expect(result, <String, String>{});
248 249
    expect(console, <Matcher>[
      matches(
250
        r'^'
251
        r'RenderView#[0-9a-f]{5}\n'
252
        r'   debug mode enabled - [a-zA-Z]+\n'
253 254 255
        r'   window size: Size\(2400\.0, 1800\.0\) \(in physical pixels\)\n'
        r'   device pixel ratio: 3\.0 \(physical pixels per logical pixel\)\n'
        r'   configuration: Size\(800\.0, 600\.0\) at 3\.0x \(in logical pixels\)\n'
256
        r'$'
257
      ),
258 259 260 261
    ]);
    console.clear();
  });

262
  test('Service extensions - debugDumpLayerTree', () async {
263
    Map<String, dynamic> result;
264 265 266 267 268 269 270

    await binding.doFrame();
    result = await binding.testExtension('debugDumpLayerTree', <String, String>{});
    expect(result, <String, String>{});
    expect(console, <Matcher>[
      matches(
        r'^'
271 272
        r'TransformLayer#[0-9a-f]{5}\n'
        r'   owner: RenderView#[0-9a-f]{5}\n'
273
        r'   creator: RenderView\n'
274
        r'   engine layer: (TransformEngineLayer|PersistedTransform)#[0-9a-f]{5}\n'
275 276
        r'   offset: Offset\(0\.0, 0\.0\)\n'
        r'   transform:\n'
277 278
        r'     \[0] 3\.0,0\.0,0\.0,0\.0\n'
        r'     \[1] 0\.0,3\.0,0\.0,0\.0\n'
279 280 281 282 283 284 285 286
        r'     \[2] 0\.0,0\.0,1\.0,0\.0\n'
        r'     \[3] 0\.0,0\.0,0\.0,1\.0\n'
        r'$'
      ),
    ]);
    console.clear();
  });

287
  test('Service extensions - debugDumpSemanticsTreeInTraversalOrder', () async {
288
    Map<String, dynamic> result;
289 290

    await binding.doFrame();
291
    result = await binding.testExtension('debugDumpSemanticsTreeInTraversalOrder', <String, String>{});
292 293 294 295 296 297
    expect(result, <String, String>{});
    expect(console, <String>['Semantics not collected.']);
    console.clear();
  });

  test('Service extensions - debugDumpSemanticsTreeInInverseHitTestOrder', () async {
298
    Map<String, dynamic> result;
299 300 301

    await binding.doFrame();
    result = await binding.testExtension('debugDumpSemanticsTreeInInverseHitTestOrder', <String, String>{});
302 303 304 305 306
    expect(result, <String, String>{});
    expect(console, <String>['Semantics not collected.']);
    console.clear();
  });

307
  test('Service extensions - debugPaint', () async {
308 309
    final Iterable<Map<String, dynamic>> extensionChangedEvents = binding.getServiceExtensionStateChangedEvents('ext.flutter.debugPaint');
    Map<String, dynamic> extensionChangedEvent;
310 311
    Map<String, dynamic> result;
    Future<Map<String, dynamic>> pendingResult;
312 313 314 315 316
    bool completed;

    expect(binding.frameScheduled, isFalse);
    expect(debugPaintSizeEnabled, false);
    result = await binding.testExtension('debugPaint', <String, String>{});
317
    expect(result, <String, String>{'enabled': 'false'});
318
    expect(debugPaintSizeEnabled, false);
319
    expect(extensionChangedEvents, isEmpty);
320
    expect(binding.frameScheduled, isFalse);
321
    pendingResult = binding.testExtension('debugPaint', <String, String>{'enabled': 'true'});
322 323 324 325 326
    completed = false;
    pendingResult.whenComplete(() { completed = true; });
    await binding.flushMicrotasks();
    expect(binding.frameScheduled, isTrue);
    expect(completed, isFalse);
327
    await binding.doFrame();
328 329 330 331
    await binding.flushMicrotasks();
    expect(completed, isTrue);
    expect(binding.frameScheduled, isFalse);
    result = await pendingResult;
332
    expect(result, <String, String>{'enabled': 'true'});
333
    expect(debugPaintSizeEnabled, true);
334 335 336 337
    expect(extensionChangedEvents.length, 1);
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.debugPaint');
    expect(extensionChangedEvent['value'], 'true');
338
    result = await binding.testExtension('debugPaint', <String, String>{});
339
    expect(result, <String, String>{'enabled': 'true'});
340
    expect(debugPaintSizeEnabled, true);
341
    expect(extensionChangedEvents.length, 1);
342
    expect(binding.frameScheduled, isFalse);
343
    pendingResult = binding.testExtension('debugPaint', <String, String>{'enabled': 'false'});
344 345
    await binding.flushMicrotasks();
    expect(binding.frameScheduled, isTrue);
346
    await binding.doFrame();
347 348
    expect(binding.frameScheduled, isFalse);
    result = await pendingResult;
349
    expect(result, <String, String>{'enabled': 'false'});
350
    expect(debugPaintSizeEnabled, false);
351 352 353 354
    expect(extensionChangedEvents.length, 2);
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.debugPaint');
    expect(extensionChangedEvent['value'], 'false');
355
    result = await binding.testExtension('debugPaint', <String, String>{});
356
    expect(result, <String, String>{'enabled': 'false'});
357
    expect(debugPaintSizeEnabled, false);
358
    expect(extensionChangedEvents.length, 2);
359 360 361
    expect(binding.frameScheduled, isFalse);
  });

362
  test('Service extensions - debugPaintBaselinesEnabled', () async {
363 364
    Map<String, dynamic> result;
    Future<Map<String, dynamic>> pendingResult;
365 366 367 368 369
    bool completed;

    expect(binding.frameScheduled, isFalse);
    expect(debugPaintBaselinesEnabled, false);
    result = await binding.testExtension('debugPaintBaselinesEnabled', <String, String>{});
370
    expect(result, <String, String>{'enabled': 'false'});
371 372
    expect(debugPaintBaselinesEnabled, false);
    expect(binding.frameScheduled, isFalse);
373
    pendingResult = binding.testExtension('debugPaintBaselinesEnabled', <String, String>{'enabled': 'true'});
374 375 376 377 378 379 380 381 382 383
    completed = false;
    pendingResult.whenComplete(() { completed = true; });
    await binding.flushMicrotasks();
    expect(binding.frameScheduled, isTrue);
    expect(completed, isFalse);
    await binding.doFrame();
    await binding.flushMicrotasks();
    expect(completed, isTrue);
    expect(binding.frameScheduled, isFalse);
    result = await pendingResult;
384
    expect(result, <String, String>{'enabled': 'true'});
385 386
    expect(debugPaintBaselinesEnabled, true);
    result = await binding.testExtension('debugPaintBaselinesEnabled', <String, String>{});
387
    expect(result, <String, String>{'enabled': 'true'});
388 389
    expect(debugPaintBaselinesEnabled, true);
    expect(binding.frameScheduled, isFalse);
390
    pendingResult = binding.testExtension('debugPaintBaselinesEnabled', <String, String>{'enabled': 'false'});
391 392 393 394 395
    await binding.flushMicrotasks();
    expect(binding.frameScheduled, isTrue);
    await binding.doFrame();
    expect(binding.frameScheduled, isFalse);
    result = await pendingResult;
396
    expect(result, <String, String>{'enabled': 'false'});
397 398
    expect(debugPaintBaselinesEnabled, false);
    result = await binding.testExtension('debugPaintBaselinesEnabled', <String, String>{});
399
    expect(result, <String, String>{'enabled': 'false'});
400 401 402 403
    expect(debugPaintBaselinesEnabled, false);
    expect(binding.frameScheduled, isFalse);
  });

404 405 406 407 408 409 410
  test('Service extensions - profileWidgetBuilds', () async {
    Map<String, dynamic> result;

    expect(binding.frameScheduled, isFalse);
    expect(debugProfileBuildsEnabled, false);

    result = await binding.testExtension('profileWidgetBuilds', <String, String>{});
411
    expect(result, <String, String>{'enabled': 'false'});
412 413
    expect(debugProfileBuildsEnabled, false);

414 415
    result = await binding.testExtension('profileWidgetBuilds', <String, String>{'enabled': 'true'});
    expect(result, <String, String>{'enabled': 'true'});
416 417 418
    expect(debugProfileBuildsEnabled, true);

    result = await binding.testExtension('profileWidgetBuilds', <String, String>{});
419
    expect(result, <String, String>{'enabled': 'true'});
420 421
    expect(debugProfileBuildsEnabled, true);

422 423
    result = await binding.testExtension('profileWidgetBuilds', <String, String>{'enabled': 'false'});
    expect(result, <String, String>{'enabled': 'false'});
424 425 426
    expect(debugProfileBuildsEnabled, false);

    result = await binding.testExtension('profileWidgetBuilds', <String, String>{});
427
    expect(result, <String, String>{'enabled': 'false'});
428 429 430 431 432
    expect(debugProfileBuildsEnabled, false);

    expect(binding.frameScheduled, isFalse);
  });

433
  test('Service extensions - evict', () async {
434
    Map<String, dynamic> result;
435 436 437
    bool completed;

    completed = false;
438
    ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData message) async {
439
      expect(utf8.decode(message.buffer.asUint8List()), 'test');
440
      completed = true;
441
      return ByteData(5); // 0x0000000000
442 443
    });
    bool data;
444 445 446 447
    data = await rootBundle.loadStructuredData<bool>('test', (String value) async {
      expect(value, '\x00\x00\x00\x00\x00');
      return true;
    });
448 449 450
    expect(data, isTrue);
    expect(completed, isTrue);
    completed = false;
451 452 453 454
    data = await rootBundle.loadStructuredData('test', (String value) async {
      expect(true, isFalse);
      return null;
    });
455 456
    expect(data, isTrue);
    expect(completed, isFalse);
457 458
    result = await binding.testExtension('evict', <String, String>{'value': 'test'});
    expect(result, <String, String>{'value': ''});
459
    expect(completed, isFalse);
460 461 462 463
    data = await rootBundle.loadStructuredData<bool>('test', (String value) async {
      expect(value, '\x00\x00\x00\x00\x00');
      return false;
    });
464 465
    expect(data, isFalse);
    expect(completed, isTrue);
466
    ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', null);
467 468 469 470
  });

  test('Service extensions - exit', () async {
    // no test for _calling_ 'exit', because that should terminate the process!
471 472
    // Not expecting extension to be available for web platform.
    expect(binding.extensions.containsKey('exit'), !isBrowser);
473 474
  });

475
  test('Service extensions - platformOverride', () async {
476 477
    final Iterable<Map<String, dynamic>> extensionChangedEvents = binding.getServiceExtensionStateChangedEvents('ext.flutter.platformOverride');
    Map<String, dynamic> extensionChangedEvent;
478
    Map<String, dynamic> result;
479 480 481 482 483 484

    expect(binding.reassembled, 0);
    expect(defaultTargetPlatform, TargetPlatform.android);
    result = await binding.testExtension('platformOverride', <String, String>{});
    expect(result, <String, String>{'value': 'android'});
    expect(defaultTargetPlatform, TargetPlatform.android);
485
    expect(extensionChangedEvents, isEmpty);
486 487 488 489
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'iOS'}));
    expect(result, <String, String>{'value': 'iOS'});
    expect(binding.reassembled, 1);
    expect(defaultTargetPlatform, TargetPlatform.iOS);
490 491 492 493
    expect(extensionChangedEvents.length, 1);
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'iOS');
Dan Field's avatar
Dan Field committed
494 495 496 497 498 499 500 501
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'macOS'}));
    expect(result, <String, String>{'value': 'macOS'});
    expect(binding.reassembled, 2);
    expect(defaultTargetPlatform, TargetPlatform.macOS);
    expect(extensionChangedEvents.length, 2);
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'macOS');
502 503
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'android'}));
    expect(result, <String, String>{'value': 'android'});
Dan Field's avatar
Dan Field committed
504
    expect(binding.reassembled, 3);
505
    expect(defaultTargetPlatform, TargetPlatform.android);
Dan Field's avatar
Dan Field committed
506
    expect(extensionChangedEvents.length, 3);
507 508 509
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'android');
510 511
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'fuchsia'}));
    expect(result, <String, String>{'value': 'fuchsia'});
Dan Field's avatar
Dan Field committed
512
    expect(binding.reassembled, 4);
513
    expect(defaultTargetPlatform, TargetPlatform.fuchsia);
Dan Field's avatar
Dan Field committed
514
    expect(extensionChangedEvents.length, 4);
515 516 517
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'fuchsia');
518 519
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'default'}));
    expect(result, <String, String>{'value': 'android'});
Dan Field's avatar
Dan Field committed
520
    expect(binding.reassembled, 5);
521
    expect(defaultTargetPlatform, TargetPlatform.android);
Dan Field's avatar
Dan Field committed
522
    expect(extensionChangedEvents.length, 5);
523 524 525
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'android');
526 527
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'iOS'}));
    expect(result, <String, String>{'value': 'iOS'});
Dan Field's avatar
Dan Field committed
528
    expect(binding.reassembled, 6);
529
    expect(defaultTargetPlatform, TargetPlatform.iOS);
Dan Field's avatar
Dan Field committed
530
    expect(extensionChangedEvents.length, 6);
531 532 533
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'iOS');
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'linux'}));
    expect(result, <String, String>{'value': 'linux'});
    expect(binding.reassembled, 7);
    expect(defaultTargetPlatform, TargetPlatform.linux);
    expect(extensionChangedEvents.length, 7);
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'linux');
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'windows'}));
    expect(result, <String, String>{'value': 'windows'});
    expect(binding.reassembled, 8);
    expect(defaultTargetPlatform, TargetPlatform.windows);
    expect(extensionChangedEvents.length, 8);
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'windows');
550 551
    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'bogus'}));
    expect(result, <String, String>{'value': 'android'});
552
    expect(binding.reassembled, 9);
553
    expect(defaultTargetPlatform, TargetPlatform.android);
554
    expect(extensionChangedEvents.length, 9);
555 556 557
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
    expect(extensionChangedEvent['value'], 'android');
558 559 560
    binding.reassembled = 0;
  });

561
  test('Service extensions - repaintRainbow', () async {
562 563
    Map<String, dynamic> result;
    Future<Map<String, dynamic>> pendingResult;
564 565 566 567 568
    bool completed;

    expect(binding.frameScheduled, isFalse);
    expect(debugRepaintRainbowEnabled, false);
    result = await binding.testExtension('repaintRainbow', <String, String>{});
569
    expect(result, <String, String>{'enabled': 'false'});
570 571
    expect(debugRepaintRainbowEnabled, false);
    expect(binding.frameScheduled, isFalse);
572
    pendingResult = binding.testExtension('repaintRainbow', <String, String>{'enabled': 'true'});
573 574 575 576 577 578
    completed = false;
    pendingResult.whenComplete(() { completed = true; });
    await binding.flushMicrotasks();
    expect(completed, true);
    expect(binding.frameScheduled, isFalse);
    result = await pendingResult;
579
    expect(result, <String, String>{'enabled': 'true'});
580 581
    expect(debugRepaintRainbowEnabled, true);
    result = await binding.testExtension('repaintRainbow', <String, String>{});
582
    expect(result, <String, String>{'enabled': 'true'});
583 584
    expect(debugRepaintRainbowEnabled, true);
    expect(binding.frameScheduled, isFalse);
585
    pendingResult = binding.testExtension('repaintRainbow', <String, String>{'enabled': 'false'});
586 587 588 589 590
    completed = false;
    pendingResult.whenComplete(() { completed = true; });
    await binding.flushMicrotasks();
    expect(completed, false);
    expect(binding.frameScheduled, isTrue);
591
    await binding.doFrame();
592 593 594 595
    await binding.flushMicrotasks();
    expect(completed, true);
    expect(binding.frameScheduled, isFalse);
    result = await pendingResult;
596
    expect(result, <String, String>{'enabled': 'false'});
597 598
    expect(debugRepaintRainbowEnabled, false);
    result = await binding.testExtension('repaintRainbow', <String, String>{});
599
    expect(result, <String, String>{'enabled': 'false'});
600 601 602 603 604
    expect(debugRepaintRainbowEnabled, false);
    expect(binding.frameScheduled, isFalse);
  });

  test('Service extensions - reassemble', () async {
605 606
    Map<String, dynamic> result;
    Future<Map<String, dynamic>> pendingResult;
607 608 609 610 611 612 613 614 615
    bool completed;

    completed = false;
    expect(binding.reassembled, 0);
    pendingResult = binding.testExtension('reassemble', <String, String>{});
    pendingResult.whenComplete(() { completed = true; });
    await binding.flushMicrotasks();
    expect(binding.frameScheduled, isTrue);
    expect(completed, false);
616
    await binding.flushMicrotasks();
617
    await binding.doFrame();
618 619 620 621 622 623 624 625 626
    await binding.flushMicrotasks();
    expect(completed, true);
    expect(binding.frameScheduled, isFalse);
    result = await pendingResult;
    expect(result, <String, String>{});
    expect(binding.reassembled, 1);
  });

  test('Service extensions - showPerformanceOverlay', () async {
627
    Map<String, dynamic> result;
628

629 630 631 632 633 634
    // The performance overlay service extension is disabled on the web.
    if (kIsWeb) {
      expect(binding.extensions.containsKey('showPerformanceOverlay'), isFalse);
      return;
    }

635 636 637
    expect(binding.frameScheduled, isFalse);
    expect(WidgetsApp.showPerformanceOverlayOverride, false);
    result = await binding.testExtension('showPerformanceOverlay', <String, String>{});
638
    expect(result, <String, String>{'enabled': 'false'});
639
    expect(WidgetsApp.showPerformanceOverlayOverride, false);
640 641
    result = await binding.testExtension('showPerformanceOverlay', <String, String>{'enabled': 'true'});
    expect(result, <String, String>{'enabled': 'true'});
642 643
    expect(WidgetsApp.showPerformanceOverlayOverride, true);
    result = await binding.testExtension('showPerformanceOverlay', <String, String>{});
644
    expect(result, <String, String>{'enabled': 'true'});
645
    expect(WidgetsApp.showPerformanceOverlayOverride, true);
646 647
    result = await binding.testExtension('showPerformanceOverlay', <String, String>{'enabled': 'false'});
    expect(result, <String, String>{'enabled': 'false'});
648 649
    expect(WidgetsApp.showPerformanceOverlayOverride, false);
    result = await binding.testExtension('showPerformanceOverlay', <String, String>{});
650
    expect(result, <String, String>{'enabled': 'false'});
651 652 653 654
    expect(WidgetsApp.showPerformanceOverlayOverride, false);
    expect(binding.frameScheduled, isFalse);
  });

655 656 657 658 659
  test('Service extensions - debugWidgetInspector', () async {
    Map<String, dynamic> result;
    expect(binding.frameScheduled, isFalse);
    expect(WidgetsApp.debugShowWidgetInspectorOverride, false);
    result = await binding.testExtension('debugWidgetInspector', <String, String>{});
660
    expect(result, <String, String>{'enabled': 'false'});
661
    expect(WidgetsApp.debugShowWidgetInspectorOverride, false);
662 663
    result = await binding.testExtension('debugWidgetInspector', <String, String>{'enabled': 'true'});
    expect(result, <String, String>{'enabled': 'true'});
664 665
    expect(WidgetsApp.debugShowWidgetInspectorOverride, true);
    result = await binding.testExtension('debugWidgetInspector', <String, String>{});
666
    expect(result, <String, String>{'enabled': 'true'});
667
    expect(WidgetsApp.debugShowWidgetInspectorOverride, true);
668 669
    result = await binding.testExtension('debugWidgetInspector', <String, String>{'enabled': 'false'});
    expect(result, <String, String>{'enabled': 'false'});
670 671
    expect(WidgetsApp.debugShowWidgetInspectorOverride, false);
    result = await binding.testExtension('debugWidgetInspector', <String, String>{});
672
    expect(result, <String, String>{'enabled': 'false'});
673 674 675 676
    expect(WidgetsApp.debugShowWidgetInspectorOverride, false);
    expect(binding.frameScheduled, isFalse);
  });

677
  test('Service extensions - timeDilation', () async {
678 679
    final Iterable<Map<String, dynamic>> extensionChangedEvents = binding.getServiceExtensionStateChangedEvents('ext.flutter.timeDilation');
    Map<String, dynamic> extensionChangedEvent;
680
    Map<String, dynamic> result;
681 682 683 684

    expect(binding.frameScheduled, isFalse);
    expect(timeDilation, 1.0);
    result = await binding.testExtension('timeDilation', <String, String>{});
685
    expect(result, <String, String>{'timeDilation': 1.0.toString()});
686
    expect(timeDilation, 1.0);
687
    expect(extensionChangedEvents, isEmpty);
688
    result = await binding.testExtension('timeDilation', <String, String>{'timeDilation': '100.0'});
689
    expect(result, <String, String>{'timeDilation': 100.0.toString()});
690
    expect(timeDilation, 100.0);
691 692 693
    expect(extensionChangedEvents.length, 1);
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.timeDilation');
694
    expect(extensionChangedEvent['value'], 100.0.toString());
695
    result = await binding.testExtension('timeDilation', <String, String>{});
696
    expect(result, <String, String>{'timeDilation': 100.0.toString()});
697
    expect(timeDilation, 100.0);
698
    expect(extensionChangedEvents.length, 1);
699
    result = await binding.testExtension('timeDilation', <String, String>{'timeDilation': '1.0'});
700
    expect(result, <String, String>{'timeDilation': 1.0.toString()});
701
    expect(timeDilation, 1.0);
702 703 704
    expect(extensionChangedEvents.length, 2);
    extensionChangedEvent = extensionChangedEvents.last;
    expect(extensionChangedEvent['extension'], 'ext.flutter.timeDilation');
705
    expect(extensionChangedEvent['value'], 1.0.toString());
706
    result = await binding.testExtension('timeDilation', <String, String>{});
707
    expect(result, <String, String>{'timeDilation': 1.0.toString()});
708
    expect(timeDilation, 1.0);
709
    expect(extensionChangedEvents.length, 2);
710 711 712
    expect(binding.frameScheduled, isFalse);
  });

713
  test('Service extensions - brightnessOverride', () async {
714
    Map<String, dynamic> result;
715 716 717 718 719
    result = await binding.testExtension('brightnessOverride', <String, String>{});
    final String brightnessValue = result['value'] as String;

    expect(brightnessValue, 'Brightness.light');
  });
720 721 722 723 724 725

  test('Service extensions - fastReassemble', () async {
    Map<String, dynamic> result;
    result = await binding.testExtension('fastReassemble', <String, String>{'class': 'Foo'});

    expect(result, containsPair('Success', 'true'));
Kate Lovett's avatar
Kate Lovett committed
726
  });
727
}