// 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.

// ignore_for_file: invalid_use_of_internal_member
// ignore_for_file: implementation_imports

/// @docImport 'dart:io';
///
/// @docImport 'controller.dart';
/// @docImport 'test_pointer.dart';
/// @docImport 'widget_tester.dart';
library;

import 'dart:async';
import 'dart:ui' as ui;

import 'package:clock/clock.dart';
import 'package:fake_async/fake_async.dart';
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/src/foundation/_features.dart' show isWindowingEnabled;
import 'package:flutter/src/widgets/_window.dart';
import 'package:flutter/src/widgets/_window_positioner.dart';
import 'package:flutter/widgets.dart';
import 'package:matcher/expect.dart' show fail;
import 'package:stack_trace/stack_trace.dart' as stack_trace;
import 'package:test_api/scaffolding.dart' as test_package show Timeout;
import 'package:vector_math/vector_math_64.dart';

import '_binding_io.dart' if (dart.library.js_interop) '_binding_web.dart' as binding;
import 'goldens.dart';
import 'platform.dart';
import 'restoration.dart';
import 'stack_manipulation.dart';
import 'test_async_utils.dart';
import 'test_default_binary_messenger.dart';
import 'test_exception_reporter.dart';
import 'test_text_input.dart';
import 'window.dart';

/// Phases that can be reached by [WidgetTester.pumpWidget] and
/// [TestWidgetsFlutterBinding.pump].
///
/// See [WidgetsBinding.drawFrame] for a more detailed description of some of
/// these phases.
enum EnginePhase {
  /// The build phase in the widgets library. See [BuildOwner.buildScope].
  build,

  /// The layout phase in the rendering library. See [PipelineOwner.flushLayout].
  layout,

  /// The compositing bits update phase in the rendering library. See
  /// [PipelineOwner.flushCompositingBits].
  compositingBits,

  /// The paint phase in the rendering library. See [PipelineOwner.flushPaint].
  paint,

  /// The compositing phase in the rendering library. See
  /// [RenderView.compositeFrame]. This is the phase in which data is sent to
  /// the GPU. If semantics are not enabled, then this is the last phase.
  composite,

  /// The semantics building phase in the rendering library. See
  /// [PipelineOwner.flushSemantics].
  flushSemantics,

  /// The final phase in the rendering library, wherein semantics information is
  /// sent to the embedder. See [SemanticsOwner.sendSemanticsUpdate].
  sendSemanticsUpdate,
}

/// Signature of callbacks used to intercept messages on a given channel.
///
/// See [TestDefaultBinaryMessenger.setMockDecodedMessageHandler] for more details.
typedef _MockMessageHandler = Future<void> Function(Object?);

/// Parts of the system that can generate pointer events that reach the test
/// binding.
///
/// This is used to identify how to handle events in the
/// [LiveTestWidgetsFlutterBinding]. See
/// [TestWidgetsFlutterBinding.dispatchEvent].
enum TestBindingEventSource {
  /// The pointer event came from the test framework itself, e.g. from a
  /// [TestGesture] created by [WidgetTester.startGesture].
  test,

  /// The pointer event came from the system, presumably as a result of the user
  /// interactive directly with the device while the test was running.
  device,
}

const Size _kDefaultTestViewportSize = Size(800.0, 600.0);

/// Overrides the [ServicesBinding]'s binary messenger logic to use
/// [TestDefaultBinaryMessenger].
///
/// Test bindings that are used by tests that mock message handlers for plugins
/// should mix in this binding to enable the use of the
/// [TestDefaultBinaryMessenger] APIs.
mixin TestDefaultBinaryMessengerBinding on BindingBase, ServicesBinding {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
  }

  /// The current [TestDefaultBinaryMessengerBinding], if one has been created.
  static TestDefaultBinaryMessengerBinding get instance => BindingBase.checkInstance(_instance);
  static TestDefaultBinaryMessengerBinding? _instance;

  @override
  TestDefaultBinaryMessenger get defaultBinaryMessenger =>
      super.defaultBinaryMessenger as TestDefaultBinaryMessenger;

  @override
  TestDefaultBinaryMessenger createBinaryMessenger() {
    Future<ByteData?> keyboardHandler(ByteData? message) async {
      return const StandardMethodCodec().encodeSuccessEnvelope(<int, int>{});
    }

    return TestDefaultBinaryMessenger(
      super.createBinaryMessenger(),
      outboundHandlers: <String, MessageHandler>{'flutter/keyboard': keyboardHandler},
    );
  }
}

/// Accessibility announcement data passed to [SemanticsService.sendAnnouncement] captured in a test.
///
/// This class is intended to be used by the testing API to store the announcements
/// in a structured form so that tests can verify announcement details. The fields
/// of this class correspond to parameters of the [SemanticsService.sendAnnouncement] method.
///
/// See also:
///
///  * [WidgetTester.takeAnnouncements], which is the test API that uses this class.
class CapturedAccessibilityAnnouncement {
  const CapturedAccessibilityAnnouncement._(
    this.message,
    this.viewId,
    this.textDirection,
    this.assertiveness,
  );

  /// The accessibility message announced by the framework.
  final String message;

  /// The ID of the view that the announcement was sent to.
  final int viewId;

  /// The direction in which the text of the [message] flows.
  final TextDirection textDirection;

  /// Determines the assertiveness level of the accessibility announcement.
  final Assertiveness assertiveness;
}

class _TestFlutterView implements FlutterView {
  _TestFlutterView({
    required this.controller,
    required TestPlatformDispatcher platformDispatcher,
    this.constraints,
    this.onRender,
  }) : _platformDispatcher = platformDispatcher,
       _viewId = _nextViewId++ {
    platformDispatcher.addTestView(this);
  }

  static int _nextViewId = 1;
  final BaseWindowController controller;
  final TestPlatformDispatcher _platformDispatcher;
  final BoxConstraints? constraints;
  final int _viewId;
  final void Function(Size? size)? onRender;

  @override
  double get devicePixelRatio => display.devicePixelRatio;

  @override
  ui.Display get display => platformDispatcher.displays.first;

  @override
  List<ui.DisplayFeature> get displayFeatures => List<ui.DisplayFeature>.empty();

  @override
  ui.GestureSettings get gestureSettings => const ui.GestureSettings();

  @override
  ui.ViewPadding get padding => ui.ViewPadding.zero;

  @override
  ui.ViewConstraints get physicalConstraints => constraints != null
      ? ui.ViewConstraints(
          minWidth: constraints!.minWidth * devicePixelRatio,
          maxWidth: constraints!.maxWidth * devicePixelRatio,
          minHeight: constraints!.minHeight * devicePixelRatio,
          maxHeight: constraints!.maxHeight * devicePixelRatio,
        )
      : ui.ViewConstraints.tight(physicalSize);

  @override
  ui.Size get physicalSize => controller.contentSize * devicePixelRatio;

  @override
  ui.PlatformDispatcher get platformDispatcher => _platformDispatcher;

  @override
  ui.ViewPadding get systemGestureInsets => ui.ViewPadding.zero;

  @override
  int get viewId => _viewId;

  @override
  ui.ViewPadding get viewInsets => ui.ViewPadding.zero;

  @override
  ui.ViewPadding get viewPadding => ui.ViewPadding.zero;

  @override
  ui.DisplayCornerRadii? get displayCornerRadii => null;

  @override
  void render(ui.Scene scene, {ui.Size? size}) {
    onRender?.call(size);
  }

  @override
  void updateSemantics(ui.SemanticsUpdate update) {}
}

mixin _ChildWindowHierarchyMixin {
  final List<BaseWindowController> _children = <BaseWindowController>[];

  /// Tracks a child window controller.
  void addChild(BaseWindowController child) {
    _children.add(child);
  }

  /// Stops tracking a child window controller.
  void removeChild(BaseWindowController child) {
    _children.remove(child);
  }

  /// Removes and destroys all child window controllers.
  void removeAllChildren() {
    for (final BaseWindowController child in _children) {
      child.destroy();
    }
    _children.clear();
  }

  /// Returns the first activateable window in this window's hierarchy.
  BaseWindowController getFirstActivatableChild() {
    // If there are no children, this window is the first activateable window.
    if (_children.isEmpty) {
      return this as BaseWindowController;
    }

    // Otherwise, traverse the children to find the first activateable window.
    //
    // Modal dialogs have focus precedence over popups.
    // Popups have focus precedence over regular windows.
    // Regular windows have the lowest precedence.
    // Tooltips cannot be activated at all, so they are skipped.
    var activateable = this as BaseWindowController;
    var foundPopup = false;
    for (final BaseWindowController child in _children) {
      switch (child) {
        case final WindowController regularChild:
          if (foundPopup) {
            // Already found a popup, skip anything else.
            break;
          }
          activateable = (regularChild as _TestWindowController).getFirstActivatableChild();
        case final DialogWindowController dialogChild:
          // Always return the first dialog found.
          return (dialogChild as _TestDialogWindowController).getFirstActivatableChild();
        case final TooltipWindowController _: // Tooltips cannot be activated.
          break;
        case final PopupWindowController popupChild:
          if (foundPopup) {
            // Already found a popup, skip anything else.
            break;
          }
          activateable = (popupChild as _TestPopupWindowController).getFirstActivatableChild();
          foundPopup = true;
        case final SatelliteWindowController satelliteChild:
          if (foundPopup) {
            // Already found a popup, skip anything else.
            break;
          }
          activateable = (satelliteChild as _TestSatelliteWindowController)
              .getFirstActivatableChild();
      }
    }

    return activateable;
  }
}

class _TestWindowController extends WindowController with _ChildWindowHierarchyMixin {
  _TestWindowController({
    required WindowControllerDelegate delegate,
    required TestPlatformDispatcher platformDispatcher,
    required this.windowingOwner,
    Size? size,
    BoxConstraints? constraints,
    String? title,
  }) : _delegate = delegate,
       _size = size ?? const Size(800, 600),
       _constraints = constraints ?? BoxConstraints.loose(const Size(1920, 1080)),
       _title = title ?? 'Test Window',
       super.empty() {
    _constrainToBounds();
    rootView = _TestFlutterView(
      controller: this,
      platformDispatcher: platformDispatcher,
      constraints: _constraints,
    );

    // Automatically activate the window when created.
    activate();
  }

  final WindowControllerDelegate _delegate;
  final _TestWindowingOwner windowingOwner;
  Size _size;
  BoxConstraints _constraints;
  String _title;
  bool _isMaximized = false;
  bool _isMinimized = false;
  bool _isFullscreen = false;

  @override
  Size get contentSize => isFullscreen || isMaximized ? rootView.display.size : _size;

  @override
  String get title => _title;

  @override
  bool get isActivated => windowingOwner.isWindowControllerActive(this);

  @override
  bool get isMaximized => _isMaximized;

  @override
  bool get isMinimized => _isMinimized;

  @override
  bool get isFullscreen => _isFullscreen;

  @override
  void setSize(Size size) {
    _size = size;
    _constrainToBounds();
    notifyListeners();
  }

  @override
  void setConstraints(BoxConstraints constraints) {
    _constraints = constraints;
    _constrainToBounds();
    notifyListeners();
  }

  @override
  void setTitle(String title) {
    _title = title;
    notifyListeners();
  }

  @override
  void activate() {
    final BaseWindowController activated = windowingOwner.activateWindowController(this);
    activated.notifyListeners();
  }

  @override
  void setMaximized(bool maximized) {
    _isMaximized = maximized;
    if (_isMaximized) {
      _isMinimized = false;
      _isFullscreen = false;
    }
    notifyListeners();
  }

  @override
  void setMinimized(bool minimized) {
    _isMinimized = minimized;
    if (_isMinimized) {
      windowingOwner.deactivateWindowController(this);
    }
    notifyListeners();
  }

  @override
  void setFullscreen(bool fullscreen, {ui.Display? display}) {
    _isFullscreen = fullscreen;
    if (_isFullscreen) {
      _isMaximized = false;
      _isMinimized = false;
    }
    notifyListeners();
  }

  void _constrainToBounds() {
    final double width = _constraints.constrainWidth(_size.width);
    final double height = _constraints.constrainHeight(_size.height);
    _size = Size(width, height);
  }

  @override
  bool get isDestroyed => _destroyed;
  bool _destroyed = false;

  @override
  void destroy() {
    _destroyed = true;
    _delegate.onWindowDestroyed();
    removeAllChildren();
    windowingOwner.deactivateWindowController(this);
  }
}

void _addChildToParent(BaseWindowController? parent, BaseWindowController child) {
  if (parent != null) {
    switch (parent) {
      case final DialogWindowController testParent:
        (testParent as _TestDialogWindowController).addChild(child);
      case final WindowController testParent:
        (testParent as _TestWindowController).addChild(child);
      case final PopupWindowController testParent:
        (testParent as _TestPopupWindowController).addChild(child);
      case final SatelliteWindowController testParent:
        (testParent as _TestSatelliteWindowController).addChild(child);
      case TooltipWindowController _:
        fail('TooltipWindowController cannot be a parent of another window controller.');
    }
  }
}

void _removeChildFromParent(BaseWindowController? parent, BaseWindowController child) {
  if (parent != null) {
    switch (parent) {
      case final DialogWindowController testParent:
        (testParent as _TestDialogWindowController).removeChild(child);
      case final WindowController testParent:
        (testParent as _TestWindowController).removeChild(child);
      case final PopupWindowController testParent:
        (testParent as _TestPopupWindowController).removeChild(child);
      case final SatelliteWindowController testParent:
        (testParent as _TestSatelliteWindowController).removeChild(child);
      case TooltipWindowController _:
        fail('TooltipWindowController cannot be a parent of another window controller.');
    }
  }
}

class _TestDialogWindowController extends DialogWindowController with _ChildWindowHierarchyMixin {
  _TestDialogWindowController({
    required DialogWindowControllerDelegate delegate,
    required TestPlatformDispatcher platformDispatcher,
    required this.windowingOwner,
    BaseWindowController? parent,
    Size? size,
    BoxConstraints? constraints,
    String? title,
  }) : _delegate = delegate,
       _parent = parent,
       _size = size ?? const Size(800, 600),
       _constraints = constraints ?? BoxConstraints.loose(const Size(1920, 1080)),
       _title = title ?? 'Test Window',
       super.empty() {
    _constrainToBounds();
    rootView = _TestFlutterView(
      controller: this,
      platformDispatcher: platformDispatcher,
      constraints: _constraints,
    );
    _addChildToParent(parent, this);

    // Automatically activate the window when created.
    activate();
  }

  final DialogWindowControllerDelegate _delegate;
  final BaseWindowController? _parent;
  final _TestWindowingOwner windowingOwner;
  Size _size;
  BoxConstraints _constraints;
  String _title;
  bool _isMinimized = false;

  @override
  Size get contentSize => _size;

  @override
  BaseWindowController? get parent => _parent;

  @override
  String get title => _title;

  @override
  bool get isActivated => windowingOwner.isWindowControllerActive(this);

  @override
  bool get isMinimized => _isMinimized;

  @override
  void setSize(Size size) {
    _size = size;
    _constrainToBounds();
    notifyListeners();
  }

  @override
  void setConstraints(BoxConstraints constraints) {
    _constraints = constraints;
    _constrainToBounds();
    notifyListeners();
  }

  @override
  void setTitle(String title) {
    _title = title;
    notifyListeners();
  }

  @override
  void activate() {
    final BaseWindowController activated = windowingOwner.activateWindowController(this);
    activated.notifyListeners();
  }

  @override
  void setMinimized(bool minimized) {
    if (_parent != null && minimized) {
      fail('Cannot minimize a modal dialog window.');
    }

    _isMinimized = minimized;
    if (_isMinimized) {
      windowingOwner.deactivateWindowController(this);
    }
    notifyListeners();
  }

  void _constrainToBounds() {
    final double width = _constraints.constrainWidth(_size.width);
    final double height = _constraints.constrainHeight(_size.height);
    _size = Size(width, height);
  }

  @override
  bool get isDestroyed => _destroyed;
  bool _destroyed = false;

  @override
  void destroy() {
    _destroyed = true;
    _delegate.onWindowDestroyed();
    removeAllChildren();
    windowingOwner.deactivateWindowController(this);
    _removeChildFromParent(_parent, this);
  }
}

class _TestTooltipWindowController extends TooltipWindowController with _ChildWindowHierarchyMixin {
  _TestTooltipWindowController({
    required TooltipWindowControllerDelegate delegate,
    required TestPlatformDispatcher platformDispatcher,
    required this.windowingOwner,
    required BoxConstraints constraints,
    required ui.Rect anchorRect,
    required WindowPositioner positioner,
    required BaseWindowController parent,
  }) : _delegate = delegate,
       _constraints = constraints,
       _anchorRect = anchorRect,
       _positioner = positioner,
       _parent = parent,
       super.empty() {
    rootView = _TestFlutterView(
      controller: this,
      platformDispatcher: platformDispatcher,
      constraints: _constraints,
      onRender: (size) {
        if (_lastRenderedSize != size) {
          _lastRenderedSize = size;
          scheduleMicrotask(() {
            notifyListeners();
          });
        }
      },
    );
    _addChildToParent(parent, this);
  }

  final TooltipWindowControllerDelegate _delegate;
  final _TestWindowingOwner windowingOwner;
  BoxConstraints _constraints;
  ui.Rect _anchorRect;
  WindowPositioner _positioner;
  final BaseWindowController _parent;
  Size? _lastRenderedSize;

  @override
  Size get contentSize => _lastRenderedSize != null ? _lastRenderedSize! : _constraints.biggest;

  @override
  BaseWindowController get parent => _parent;

  @override
  void setConstraints(BoxConstraints constraints) {
    _constraints = constraints;
    notifyListeners();
  }

  @override
  void updatePosition({Rect? anchorRect, WindowPositioner? positioner}) {
    _anchorRect = anchorRect ?? _anchorRect;
    _positioner = positioner ?? _positioner;
  }

  @override
  bool get isDestroyed => _destroyed;
  bool _destroyed = false;

  @override
  void destroy() {
    _destroyed = true;
    _delegate.onWindowDestroyed();
    removeAllChildren();
    windowingOwner.deactivateWindowController(this);
    _removeChildFromParent(parent, this);
  }
}

class _TestPopupWindowController extends PopupWindowController with _ChildWindowHierarchyMixin {
  _TestPopupWindowController({
    required PopupWindowControllerDelegate delegate,
    required TestPlatformDispatcher platformDispatcher,
    required this.windowingOwner,
    required BoxConstraints constraints,
    required ui.Rect anchorRect,
    required WindowPositioner positioner,
    required BaseWindowController parent,
  }) : _delegate = delegate,
       _constraints = constraints,
       _anchorRect = anchorRect,
       _positioner = positioner,
       _parent = parent,
       super.empty() {
    rootView = _TestFlutterView(
      controller: this,
      platformDispatcher: platformDispatcher,
      constraints: _constraints,
      onRender: (size) {
        if (_lastRenderedSize != size) {
          _lastRenderedSize = size;
          scheduleMicrotask(() {
            notifyListeners();
          });
        }
      },
    );
    _addChildToParent(parent, this);
  }

  final PopupWindowControllerDelegate _delegate;
  final _TestWindowingOwner windowingOwner;
  BoxConstraints _constraints;
  ui.Rect _anchorRect;
  WindowPositioner _positioner;
  final BaseWindowController _parent;
  Size? _lastRenderedSize;

  @override
  Size get contentSize => _lastRenderedSize != null ? _lastRenderedSize! : _constraints.biggest;

  @override
  BaseWindowController get parent => _parent;

  @override
  void setConstraints(BoxConstraints constraints) {
    _constraints = constraints;
    notifyListeners();
  }

  @override
  void updatePosition({Rect? anchorRect, WindowPositioner? positioner}) {
    _anchorRect = anchorRect ?? _anchorRect;
    _positioner = positioner ?? _positioner;
  }

  @override
  bool get isDestroyed => _destroyed;
  bool _destroyed = false;

  @override
  void destroy() {
    _destroyed = true;
    _delegate.onWindowDestroyed();
    removeAllChildren();
    windowingOwner.deactivateWindowController(this);
    _removeChildFromParent(parent, this);
  }

  @override
  ui.Offset get offsetFromParent => Offset.zero;
}

class _TestSatelliteWindowController extends SatelliteWindowController
    with _ChildWindowHierarchyMixin {
  _TestSatelliteWindowController({
    required SatelliteWindowControllerDelegate delegate,
    required TestPlatformDispatcher platformDispatcher,
    required this.windowingOwner,
    required BaseWindowController parent,
    ui.Rect? anchorRect,
    required WindowPositioner positioner,
    Size? size,
    BoxConstraints? constraints,
    String? title,
  }) : _delegate = delegate,
       _parent = parent,
       // ignore: unused_field
       _anchorRect = anchorRect,
       // ignore: unused_field
       _positioner = positioner,
       _size = size ?? const Size(800, 600),
       _constraints = constraints ?? BoxConstraints.loose(const Size(1920, 1080)),
       _title = title ?? 'Test Window',
       super.empty() {
    _constrainToBounds();
    rootView = _TestFlutterView(
      controller: this,
      platformDispatcher: platformDispatcher,
      constraints: _constraints,
    );
    _addChildToParent(parent, this);

    // Automatically activate the window when created.
    activate();
  }

  final SatelliteWindowControllerDelegate _delegate;
  BaseWindowController _parent;
  final _TestWindowingOwner windowingOwner;
  // ignore: unused_field
  final ui.Rect? _anchorRect;
  // ignore: unused_field
  final WindowPositioner _positioner;
  Size _size;
  BoxConstraints _constraints;
  String _title;

  @override
  Size get contentSize => _size;

  @override
  BaseWindowController get parent => _parent;

  @override
  String get title => _title;

  @override
  bool get isActivated => windowingOwner.isWindowControllerActive(this);

  @override
  void setParent(BaseWindowController parent) {
    _removeChildFromParent(_parent, this);
    _parent = parent;
    _addChildToParent(parent, this);
    notifyListeners();
  }

  @override
  void setSize(Size size) {
    _size = size;
    _constrainToBounds();
    notifyListeners();
  }

  @override
  void setConstraints(BoxConstraints constraints) {
    _constraints = constraints;
    _constrainToBounds();
    notifyListeners();
  }

  @override
  void setTitle(String title) {
    _title = title;
    notifyListeners();
  }

  @override
  void activate() {
    final BaseWindowController activated = windowingOwner.activateWindowController(this);
    activated.notifyListeners();
  }

  void _constrainToBounds() {
    final double width = _constraints.constrainWidth(_size.width);
    final double height = _constraints.constrainHeight(_size.height);
    _size = Size(width, height);
  }

  @override
  bool get isDestroyed => _destroyed;
  bool _destroyed = false;

  @override
  void destroy() {
    _destroyed = true;
    _delegate.onWindowDestroyed();
    removeAllChildren();
    windowingOwner.deactivateWindowController(this);
    _removeChildFromParent(_parent, this);
  }
}

/// A [WindowingOwner] used for tests.
///
/// This windowing owner will behave as a perfect windowing system, with no
/// delays or failures.
///
/// See also:
/// * [TestWidgetsFlutterBinding], which uses this class to create window controllers
/// for tests.
/// * [WindowingOwner], the base class.
class _TestWindowingOwner extends WindowingOwner {
  _TestWindowingOwner({required TestPlatformDispatcher platformDispatcher})
    : _platformDispatcher = platformDispatcher;

  final TestPlatformDispatcher _platformDispatcher;
  BaseWindowController? _activeWindowController;

  /// Activates the given [controller].
  ///
  /// If the controller has children, the first activateable window in its hierarchy
  /// will be activated.
  ///
  /// Tooltips cannot be activated, so if a [TooltipWindowController] is passed in,
  /// this method will throw an error.
  ///
  /// Returns the activated [BaseWindowController].
  BaseWindowController activateWindowController(BaseWindowController controller) {
    switch (controller) {
      case final WindowController regularController:
        final BaseWindowController leaf = (regularController as _TestWindowController)
            .getFirstActivatableChild();
        _activeWindowController = leaf;
        return _activeWindowController!;
      case final DialogWindowController dialogController:
        final BaseWindowController leaf = (dialogController as _TestDialogWindowController)
            .getFirstActivatableChild();
        _activeWindowController = leaf;
        return _activeWindowController!;
      case final TooltipWindowController _:
        fail('Tooltips cannot be activated. Activate the parent window instead.');
      case final PopupWindowController _:
        final BaseWindowController leaf = (controller as _TestPopupWindowController)
            .getFirstActivatableChild();
        _activeWindowController = leaf;
        return _activeWindowController!;
      case final SatelliteWindowController _:
        final BaseWindowController leaf = (controller as _TestSatelliteWindowController)
            .getFirstActivatableChild();
        _activeWindowController = leaf;
        return _activeWindowController!;
    }
  }

  bool _tryActivateParent(BaseWindowController? parent) {
    if (parent == null) {
      return false;
    }

    switch (parent) {
      case final WindowController regularParent:
        regularParent.activate();
      case final DialogWindowController dialogParent:
        dialogParent.activate();
      case final TooltipWindowController _:
        fail('TooltipWindowController cannot be a parent of another window controller.');
      case final PopupWindowController popupParent:
        popupParent.activate();
      case final SatelliteWindowController satelliteParent:
        satelliteParent.activate();
    }

    return true;
  }

  /// Deactivates the given [controller] if it is currently active.
  ///
  /// If the controller is not currently active, this method does nothing.
  ///
  /// If the controller is a [DialogWindowController] with a parent, the parent
  /// will be activated upon deactivation of the dialog.
  ///
  /// If the controller is a [TooltipWindowController], this method will throw
  /// an error, as tooltips cannot be deactivated because they cannot be activated.
  void deactivateWindowController(BaseWindowController controller) {
    if (_activeWindowController != controller) {
      return;
    }

    switch (controller) {
      case final WindowController _:
        _activeWindowController = null;
      case final DialogWindowController dialogController:
        if (!_tryActivateParent(dialogController.parent)) {
          _activeWindowController = null;
        }
      case final TooltipWindowController tooltipController:
        fail(
          'Tooltips cannot be deactivated. Deactivate the parent window instead: '
          '${tooltipController.parent}.',
        );
      case final PopupWindowController popupController:
        if (!_tryActivateParent(popupController.parent)) {
          _activeWindowController = null;
        }
      case final SatelliteWindowController satelliteController:
        if (!_tryActivateParent(satelliteController.parent)) {
          _activeWindowController = null;
        }
    }
  }

  /// Returns whether the given [controller] is the currently active window.
  bool isWindowControllerActive(BaseWindowController controller) {
    return _activeWindowController == controller;
  }

  @internal
  @override
  WindowController createWindowController({
    required WindowControllerDelegate delegate,
    Size? size,
    BoxConstraints? constraints,
    required bool resizable,
    String? title,
  }) {
    return _TestWindowController(
      delegate: delegate,
      platformDispatcher: _platformDispatcher,
      windowingOwner: this,
      size: size,
      constraints: constraints,
      title: title,
    );
  }

  @internal
  @override
  DialogWindowController createDialogWindowController({
    required DialogWindowControllerDelegate delegate,
    Size? size,
    BoxConstraints? constraints,
    required bool resizable,
    BaseWindowController? parent,
    String? title,
  }) {
    return _TestDialogWindowController(
      delegate: delegate,
      platformDispatcher: _platformDispatcher,
      windowingOwner: this,
      parent: parent,
      size: size,
      constraints: constraints,
      title: title,
    );
  }

  @override
  TooltipWindowController createTooltipWindowController({
    required TooltipWindowControllerDelegate delegate,
    required BoxConstraints constraints,
    required Rect anchorRect,
    required WindowPositioner positioner,
    required BaseWindowController parent,
  }) {
    return _TestTooltipWindowController(
      delegate: delegate,
      platformDispatcher: _platformDispatcher,
      windowingOwner: this,
      constraints: constraints,
      anchorRect: anchorRect,
      positioner: positioner,
      parent: parent,
    );
  }

  @override
  PopupWindowController createPopupWindowController({
    required PopupWindowControllerDelegate delegate,
    required BoxConstraints constraints,
    required ui.Rect anchorRect,
    required WindowPositioner positioner,
    required BaseWindowController parent,
  }) {
    return _TestPopupWindowController(
      delegate: delegate,
      platformDispatcher: _platformDispatcher,
      windowingOwner: this,
      constraints: constraints,
      anchorRect: anchorRect,
      positioner: positioner,
      parent: parent,
    );
  }

  @internal
  @override
  SatelliteWindowController createSatelliteWindowController({
    required SatelliteWindowControllerDelegate delegate,
    required BaseWindowController parent,
    required WindowPositioner initialPositioner,
    Rect? initialAnchorRect,
    Size? size,
    BoxConstraints? constraints,
    required bool resizable,
    String? title,
  }) {
    return _TestSatelliteWindowController(
      delegate: delegate,
      platformDispatcher: _platformDispatcher,
      windowingOwner: this,
      parent: parent,
      anchorRect: initialAnchorRect,
      positioner: initialPositioner,
      size: size,
      constraints: constraints,
      title: title,
    );
  }
}

// Examples can assume:
// late TestWidgetsFlutterBinding binding;
// late Size someSize;

/// Base class for bindings used by widgets library tests.
///
/// The [ensureInitialized] method creates (if necessary) and returns an
/// instance of the appropriate subclass. (If one is already created, it returns
/// that one, even if it's not the one that it would normally create. This
/// allows tests to force the use of [LiveTestWidgetsFlutterBinding] even in a
/// normal unit test environment, e.g. to test that binding.)
///
/// When using these bindings, certain features are disabled. For
/// example, [timeDilation] is reset to 1.0 on initialization.
///
/// In non-browser tests, the binding overrides `HttpClient` creation with a
/// fake client that always returns a status code of 400. This is to prevent
/// tests from making network calls, which could introduce flakiness. A test
/// that actually needs to make a network call should provide its own
/// `HttpClient` to the code making the call, so that it can appropriately mock
/// or fake responses.
///
/// ### Coordinate spaces
///
/// [TestWidgetsFlutterBinding] might be run on devices of different screen
/// sizes, while the testing widget is still told the same size to ensure
/// consistent results. Consequently, code that deals with positions (such as
/// pointer events or painting) must distinguish between two coordinate spaces:
///
///  * The _local coordinate space_ is the one used by the testing widget
///    (typically an 800 by 600 window, but can be altered by [setSurfaceSize]).
///  * The _global coordinate space_ is the one used by the device.
///
/// Positions can be transformed between coordinate spaces with [localToGlobal]
/// and [globalToLocal].
abstract class TestWidgetsFlutterBinding extends BindingBase
    with
        SchedulerBinding,
        ServicesBinding,
        GestureBinding,
        SemanticsBinding,
        RendererBinding,
        PaintingBinding,
        WidgetsBinding,
        TestDefaultBinaryMessengerBinding {
  /// Constructor for [TestWidgetsFlutterBinding].
  ///
  /// This constructor overrides the [debugPrint] global hook to point to
  /// [debugPrintOverride], which can be overridden by subclasses.
  TestWidgetsFlutterBinding()
    : platformDispatcher = TestPlatformDispatcher(platformDispatcher: PlatformDispatcher.instance) {
    platformDispatcher.defaultRouteNameTestValue = '/';
    debugPrint = debugPrintOverride;
    debugDisableShadows = disableShadows;
  }

  /// Deprecated. Will be removed in a future version of Flutter.
  ///
  /// This property has been deprecated to prepare for Flutter's upcoming
  /// support for multiple views and multiple windows.
  ///
  /// This represents a combination of a [TestPlatformDispatcher] and a singular
  /// [TestFlutterView]. Platform-specific test values can be set through
  /// [WidgetTester.platformDispatcher] instead. When testing individual widgets
  /// or applications using [WidgetTester.pumpWidget], view-specific test values
  /// can be set through [WidgetTester.view]. If multiple views are defined, the
  /// appropriate view can be found using [WidgetTester.viewOf] if a sub-view
  /// is needed.
  ///
  /// See also:
  ///
  /// * [WidgetTester.platformDispatcher] for changing platform-specific values
  ///   for testing.
  /// * [WidgetTester.view] and [WidgetTester.viewOf] for changing view-specific
  ///   values for testing.
  /// * [BindingBase.window] for guidance dealing with this property outside of
  ///   a testing context.
  @Deprecated(
    'Use WidgetTester.platformDispatcher or WidgetTester.view instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.',
  )
  @override
  late final TestWindow window;

  @override
  final TestPlatformDispatcher platformDispatcher;

  @override
  TestRestorationManager get restorationManager {
    _restorationManager ??= createRestorationManager();
    return _restorationManager!;
  }

  TestRestorationManager? _restorationManager;

  /// Called by the test framework at the beginning of a widget test to
  /// prepare the binding for the next test.
  ///
  /// If [registerTestTextInput] returns true when this method is called,
  /// the [testTextInput] is configured to simulate the keyboard.
  void reset() {
    _restorationManager?.dispose();
    _restorationManager = null;
    platformDispatcher.defaultRouteNameTestValue = '/';
    resetGestureBinding();
    testTextInput.reset();
    if (registerTestTextInput) {
      _testTextInput.register();
    }
    CustomSemanticsAction.resetForTests(); // ignore: invalid_use_of_visible_for_testing_member
    _enableFocusManagerLifecycleAwarenessIfSupported();
  }

  void _enableFocusManagerLifecycleAwarenessIfSupported() {
    if (buildOwner == null) {
      return;
    }
    buildOwner!.focusManager
        .listenToApplicationLifecycleChangesIfSupported(); // ignore: invalid_use_of_visible_for_testing_member
  }

  @override
  TestRestorationManager createRestorationManager() {
    return TestRestorationManager();
  }

  /// The value to set [debugPrint] to while tests are running.
  ///
  /// This can be used to redirect console output from the framework, or to
  /// change the behavior of [debugPrint]. For example,
  /// [AutomatedTestWidgetsFlutterBinding] uses it to make [debugPrint]
  /// synchronous, disabling its normal throttling behavior.
  ///
  /// It is also used by some other parts of the test framework (e.g.
  /// [WidgetTester.printToConsole]) to ensure that messages from the
  /// test framework are displayed to the developer rather than logged
  /// by whatever code is overriding [debugPrint].
  DebugPrintCallback get debugPrintOverride => debugPrint;

  /// The value to set [debugDisableShadows] to while tests are running.
  ///
  /// This can be used to reduce the likelihood of golden file tests being
  /// flaky, because shadow rendering is not always deterministic. The
  /// [AutomatedTestWidgetsFlutterBinding] sets this to true, so that all tests
  /// always run with shadows disabled.
  @protected
  bool get disableShadows => false;

  /// Determines whether the Dart [HttpClient] class should be overridden to
  /// always return a failure response.
  ///
  /// By default, this value is true, so that unit tests will not become flaky
  /// due to intermittent network errors. The value may be overridden by a
  /// binding intended for use in integration tests that do end to end
  /// application testing, including working with real network responses.
  @protected
  bool get overrideHttpClient => true;

  /// Determines whether the binding automatically registers [testTextInput] as
  /// a fake keyboard implementation.
  ///
  /// Unit tests make use of this to mock out text input communication for
  /// widgets. An integration test would set this to false, to test real IME
  /// or keyboard input.
  ///
  /// [TestTextInput.isRegistered] reports whether the text input mock is
  /// registered or not.
  ///
  /// Some of the properties and methods on [testTextInput] are only valid if
  /// [registerTestTextInput] returns true when a test starts. If those
  /// members are accessed when using a binding that sets this flag to false,
  /// they will throw.
  ///
  /// If this property returns true when a test ends, the [testTextInput] is
  /// unregistered.
  ///
  /// This property should not change the value it returns during the lifetime
  /// of the binding. Changing the value of this property risks very confusing
  /// behavior as the [TestTextInput] may be inconsistently registered or
  /// unregistered.
  @protected
  bool get registerTestTextInput => true;

  /// Determines whether the binding automatically registers [windowingOwner] to
  /// the fake windowing owner implementation.
  ///
  /// Unit tests make use of this to mock out windowing system communication for
  /// widgets. An integration test would set this to false, to test real windowing
  /// system input.
  ///
  /// This property should not change the value it returns during the lifetime
  /// of the binding. Changing the value of this property risks very confusing
  /// behavior as the [WindowingOwner] may be inconsistently registered or
  /// unregistered.
  @protected
  bool get registerTestWindowingOwner => true;

  /// Delay for `duration` of time.
  ///
  /// In the automated test environment ([AutomatedTestWidgetsFlutterBinding],
  /// typically used in `flutter test`), this advances the fake [clock] for the
  /// period.
  ///
  /// In the live test environment ([LiveTestWidgetsFlutterBinding], typically
  /// used for `flutter run` and for [e2e](https://pub.dev/packages/e2e)), it is
  /// equivalent to [Future.delayed].
  Future<void> delayed(Duration duration);

  /// The current [TestWidgetsFlutterBinding], if one has been created.
  ///
  /// Provides access to the features exposed by this binding. The binding must
  /// be initialized before using this getter; this is typically done by calling
  /// [testWidgets] or [TestWidgetsFlutterBinding.ensureInitialized].
  static TestWidgetsFlutterBinding get instance => BindingBase.checkInstance(_instance);
  static TestWidgetsFlutterBinding? _instance;

  /// Creates and initializes the binding. This function is
  /// idempotent; calling it a second time will just return the
  /// previously-created instance.
  ///
  /// This function will use [AutomatedTestWidgetsFlutterBinding] if
  /// the test was run using `flutter test`, and
  /// [LiveTestWidgetsFlutterBinding] otherwise (e.g. if it was run
  /// using `flutter run`). This is determined by looking at the
  /// environment variables for a variable called `FLUTTER_TEST`.
  ///
  /// If `FLUTTER_TEST` is set with a value of 'true', then this test was
  /// invoked by `flutter test`. If `FLUTTER_TEST` is not set, or if it is set
  /// to 'false', then this test was invoked by `flutter run`.
  ///
  /// Browser environments do not currently support the
  /// [LiveTestWidgetsFlutterBinding], so this function will always set up an
  /// [AutomatedTestWidgetsFlutterBinding] when run in a web browser.
  ///
  /// The parameter `environment` is used to test the test framework
  /// itself by checking how it reacts to different environment
  /// variable values, and should not be used outside of this context.
  ///
  /// If a [TestWidgetsFlutterBinding] subclass was explicitly initialized
  /// before calling [ensureInitialized], then that version of the binding is
  /// returned regardless of the logic described above. This allows tests to
  /// force a specific test binding to be used.
  ///
  /// This is called automatically by [testWidgets].
  static TestWidgetsFlutterBinding ensureInitialized([
    @visibleForTesting Map<String, String>? environment,
  ]) {
    return _instance ?? binding.ensureInitialized(environment);
  }

  @override
  void initInstances() {
    // This is initialized here because it's needed for the `super.initInstances`
    // call. It can't be handled as a ctor initializer because it's dependent
    // on `platformDispatcher`. It can't be handled in the ctor itself because
    // the base class ctor is called first and calls `initInstances`.
    window = TestWindow.fromPlatformDispatcher(platformDispatcher: platformDispatcher);

    super.initInstances();
    _instance = this;
    timeDilation = 1.0; // just in case the developer has artificially changed it for development
    if (overrideHttpClient) {
      binding.setupHttpOverrides();
    }
    _testTextInput = TestTextInput(onCleared: _resetFocusedEditable);

    if (isWindowingEnabled && registerTestWindowingOwner) {
      windowingOwner = _TestWindowingOwner(platformDispatcher: platformDispatcher);
    }
  }

  @override
  // ignore: must_call_super
  void initLicenses() {
    // Do not include any licenses, because we're a test, and the LICENSE file
    // doesn't get generated for tests.
  }

  @override
  bool debugCheckZone(String entryPoint) {
    // We skip all the zone checks in tests because the test framework makes heavy use
    // of zones and so the zones never quite match the way the framework expects.
    return true;
  }

  /// Whether there is currently a test executing.
  bool get inTest;

  /// The number of outstanding microtasks in the queue.
  int get microtaskCount;

  /// The default test timeout for tests when using this binding.
  ///
  /// This controls the default for the `timeout` argument on [testWidgets]. It
  /// is 10 minutes for [AutomatedTestWidgetsFlutterBinding] (tests running
  /// using `flutter test`), and unlimited for tests using
  /// [LiveTestWidgetsFlutterBinding] (tests running using `flutter run`).
  test_package.Timeout get defaultTestTimeout;

  /// The current time.
  ///
  /// In the automated test environment (`flutter test`), this is a fake clock
  /// that begins in January 2015 at the start of the test and advances each
  /// time [pump] is called with a non-zero duration.
  ///
  /// In the live testing environment (`flutter run`), this object shows the
  /// actual current wall-clock time.
  Clock get clock;

  @override
  SamplingClock? get debugSamplingClock => _TestSamplingClock(clock);

  /// Triggers a frame sequence (build/layout/paint/etc),
  /// then flushes microtasks.
  ///
  /// If duration is set, then advances the clock by that much first.
  /// Doing this flushes microtasks.
  ///
  /// The supplied EnginePhase is the final phase reached during the pump pass;
  /// if not supplied, the whole pass is executed.
  ///
  /// See also [LiveTestWidgetsFlutterBindingFramePolicy], which affects how
  /// this method works when the test is run with `flutter run`.
  Future<void> pump([Duration? duration, EnginePhase newPhase = EnginePhase.sendSemanticsUpdate]);

  /// Runs a `callback` that performs real asynchronous work.
  ///
  /// This is intended for callers who need to call asynchronous methods where
  /// the methods spawn isolates or OS threads and thus cannot be executed
  /// synchronously by calling [pump].
  ///
  /// The `callback` must return a [Future] that completes to a value of type
  /// `T`.
  ///
  /// If `callback` completes successfully, this will return the future
  /// returned by `callback`.
  ///
  /// If `callback` completes with an error, the error will be caught by the
  /// Flutter framework and made available via [takeException], and this method
  /// will return a future that completes with `null`.
  ///
  /// Re-entrant calls to this method are not allowed; callers of this method
  /// are required to wait for the returned future to complete before calling
  /// this method again. Attempts to do otherwise will result in a
  /// [TestFailure] error being thrown.
  Future<T?> runAsync<T>(Future<T> Function() callback);

  /// Artificially calls dispatchLocalesChanged on the Widget binding,
  /// then flushes microtasks.
  ///
  /// Passes only one single Locale. Use [setLocales] to pass a full preferred
  /// locales list.
  Future<void> setLocale(String languageCode, String countryCode) {
    return TestAsyncUtils.guard<void>(() async {
      assert(inTest);
      final locale = Locale(languageCode, countryCode == '' ? null : countryCode);
      dispatchLocalesChanged(<Locale>[locale]);
    });
  }

  /// Artificially calls dispatchLocalesChanged on the Widget binding,
  /// then flushes microtasks.
  Future<void> setLocales(List<Locale> locales) {
    return TestAsyncUtils.guard<void>(() async {
      assert(inTest);
      dispatchLocalesChanged(locales);
    });
  }

  @override
  Future<ui.AppExitResponse> exitApplication(ui.AppExitType exitType, [int exitCode = 0]) async {
    switch (exitType) {
      case ui.AppExitType.cancelable:
        // The test framework shouldn't actually exit when requested.
        return ui.AppExitResponse.cancel;
      case ui.AppExitType.required:
        throw FlutterError('Unexpected application exit request while running test');
    }
  }

  /// Re-attempts the initialization of the lifecycle state after providing
  /// test values in [TestPlatformDispatcher.initialLifecycleStateTestValue].
  void readTestInitialLifecycleStateFromNativeWindow() {
    readInitialLifecycleStateFromNativeWindow();
  }

  Size? _surfaceSize;

  /// Artificially changes the logical size of [WidgetTester.view] to the
  /// specified size, then flushes microtasks.
  ///
  /// Set to null to use the default surface size.
  ///
  /// To avoid affecting other tests by leaking state, a test that
  /// uses this method should always reset the surface size to the default.
  /// For example, using `addTearDown`:
  /// ```dart
  ///   await binding.setSurfaceSize(someSize);
  ///   addTearDown(() => binding.setSurfaceSize(null));
  /// ```
  ///
  /// This method only affects the size of the [WidgetTester.view]. It does not
  /// affect the size of any other views. Instead of this method, consider
  /// setting [TestFlutterView.physicalSize], which works for any view,
  /// including [WidgetTester.view].
  // TODO(pdblasi-google): Deprecate this. https://github.com/flutter/flutter/issues/123881
  Future<void> setSurfaceSize(Size? size) {
    return TestAsyncUtils.guard<void>(() async {
      assert(inTest);
      if (_surfaceSize == size) {
        return;
      }
      _surfaceSize = size;
      handleMetricsChanged();
    });
  }

  @override
  void addRenderView(RenderView view) {
    _insideAddRenderView = true;
    try {
      super.addRenderView(view);
    } finally {
      _insideAddRenderView = false;
    }
  }

  bool _insideAddRenderView = false;

  @override
  ViewConfiguration createViewConfigurationFor(RenderView renderView) {
    if (_insideAddRenderView &&
        renderView.hasConfiguration &&
        renderView.configuration is TestViewConfiguration &&
        renderView == this.renderView) {
      // If a test has reached out to the now deprecated renderView property to set a custom TestViewConfiguration
      // we are not replacing it. This is to maintain backwards compatibility with how things worked prior to the
      // deprecation of that property.
      // TODO(goderbauer): Remove this "if" when the deprecated renderView property is removed.
      return renderView.configuration;
    }
    final FlutterView view = renderView.flutterView;
    if (_surfaceSize != null && view == platformDispatcher.implicitView) {
      final constraints = BoxConstraints.tight(_surfaceSize!);
      return ViewConfiguration(
        logicalConstraints: constraints,
        physicalConstraints: constraints * view.devicePixelRatio,
        devicePixelRatio: view.devicePixelRatio,
      );
    }
    return super.createViewConfigurationFor(renderView);
  }

  /// Acts as if the application went idle.
  ///
  /// Runs all remaining microtasks, including those scheduled as a result of
  /// running them, until there are no more microtasks scheduled. Then, runs any
  /// previously scheduled timers with zero time, and completes the returned future.
  ///
  /// May result in an infinite loop or run out of memory if microtasks continue
  /// to recursively schedule new microtasks. Will not run any timers scheduled
  /// after this method was invoked, even if they are zero-time timers.
  Future<void> idle() {
    return TestAsyncUtils.guard<void>(() {
      final completer = Completer<void>();
      Timer.run(() {
        completer.complete();
      });
      return completer.future;
    });
  }

  /// Convert the given point from the global coordinate space of the provided
  /// [RenderView] to its local one.
  ///
  /// This method operates in logical pixels for both coordinate spaces. It does
  /// not apply the device pixel ratio (used to translate to/from physical
  /// pixels).
  ///
  /// For definitions for coordinate spaces, see [TestWidgetsFlutterBinding].
  Offset globalToLocal(Offset point, RenderView view) => point;

  /// Convert the given point from the local coordinate space to the global
  /// coordinate space of the [RenderView].
  ///
  /// This method operates in logical pixels for both coordinate spaces. It does
  /// not apply the device pixel ratio to translate to physical pixels.
  ///
  /// For definitions for coordinate spaces, see [TestWidgetsFlutterBinding].
  Offset localToGlobal(Offset point, RenderView view) => point;

  /// The source of the current pointer event.
  ///
  /// The [pointerEventSource] is set as the `source` parameter of
  /// [handlePointerEventForSource] and can be used in the immediate enclosing
  /// [dispatchEvent].
  ///
  /// When [handlePointerEvent] is called directly, [pointerEventSource]
  /// is [TestBindingEventSource.device].
  ///
  /// This means that pointer events triggered by the [WidgetController] (e.g.
  /// via [WidgetController.tap]) will result in actual interactions with the
  /// UI, but other pointer events such as those from physical taps will be
  /// dropped. See also [shouldPropagateDevicePointerEvents] if this is
  /// undesired.
  TestBindingEventSource get pointerEventSource => _pointerEventSource;
  TestBindingEventSource _pointerEventSource = TestBindingEventSource.device;

  /// Whether pointer events from [TestBindingEventSource.device] will be
  /// propagated to the framework, or dropped.
  ///
  /// Setting this can be useful to interact with the app in some other way
  /// besides through the [WidgetController], such as with `adb shell input tap`
  /// on Android.
  ///
  /// See also [pointerEventSource].
  bool shouldPropagateDevicePointerEvents = false;

  /// Dispatch an event to the targets found by a hit test on its position,
  /// and remember its source as [pointerEventSource].
  ///
  /// This method sets [pointerEventSource] to `source`, forwards the call to
  /// [handlePointerEvent], then resets [pointerEventSource] to the previous
  /// value.
  ///
  /// If `source` is [TestBindingEventSource.device], then the `event` is based
  /// in the global coordinate space (for definitions for coordinate spaces,
  /// see [TestWidgetsFlutterBinding]) and the event is likely triggered by the
  /// user physically interacting with the screen during a live test on a real
  /// device (see [LiveTestWidgetsFlutterBinding]).
  ///
  /// If `source` is [TestBindingEventSource.test], then the `event` is based
  /// in the local coordinate space and the event is likely triggered by
  /// programmatically simulated pointer events, such as:
  ///
  ///  * [WidgetController.tap] and alike methods, as well as directly using
  ///    [TestGesture]. They are usually used in
  ///    [AutomatedTestWidgetsFlutterBinding] but sometimes in live tests too.
  ///  * [WidgetController.timedDrag] and alike methods. They are usually used
  ///    in macrobenchmarks.
  void handlePointerEventForSource(
    PointerEvent event, {
    TestBindingEventSource source = TestBindingEventSource.device,
  }) {
    withPointerEventSource(source, () => handlePointerEvent(event));
  }

  /// Sets [pointerEventSource] to `source`, runs `task`, then resets `source`
  /// to the previous value.
  @protected
  void withPointerEventSource(TestBindingEventSource source, VoidCallback task) {
    final TestBindingEventSource previousSource = _pointerEventSource;
    _pointerEventSource = source;
    try {
      task();
    } finally {
      _pointerEventSource = previousSource;
    }
  }

  /// A stub for the system's onscreen keyboard. Callers must set the
  /// [focusedEditable] before using this value.
  TestTextInput get testTextInput => _testTextInput;
  late TestTextInput _testTextInput;

  /// The [State] of the current [EditableText] client of the onscreen keyboard.
  ///
  /// Setting this property to a new value causes the given [EditableTextState]
  /// to focus itself and request the keyboard to establish a
  /// [TextInputConnection].
  ///
  /// Callers must pump an additional frame after setting this property to
  /// complete the focus change.
  ///
  /// Instead of setting this directly, consider using
  /// [WidgetTester.showKeyboard].
  //
  // TODO(ianh): We should just remove this property and move the call to
  // requestKeyboard to the WidgetTester.showKeyboard method.
  EditableTextState? get focusedEditable => _focusedEditable;
  EditableTextState? _focusedEditable;
  set focusedEditable(EditableTextState? value) {
    if (_focusedEditable != value) {
      _focusedEditable = value;
      value?.requestKeyboard();
    }
  }

  void _resetFocusedEditable() {
    _focusedEditable = null;
  }

  /// Returns the exception most recently caught by the Flutter framework.
  ///
  /// Call this if you expect an exception during a test. If an exception is
  /// thrown and this is not called, then the exception is rethrown when
  /// the [testWidgets] call completes.
  ///
  /// If two exceptions are thrown in a row without the first one being
  /// acknowledged with a call to this method, then when the second exception is
  /// thrown, they are both dumped to the console and then the second is
  /// rethrown from the exception handler. This will likely result in the
  /// framework entering a highly unstable state and everything collapsing.
  ///
  /// It's safe to call this when there's no pending exception; it will return
  /// null in that case.
  dynamic takeException() {
    assert(inTest);
    final dynamic result = _pendingExceptionDetails?.exception;
    _pendingExceptionDetails = null;
    return result;
  }

  FlutterExceptionHandler? _oldExceptionHandler;
  late StackTraceDemangler _oldStackTraceDemangler;
  FlutterErrorDetails? _pendingExceptionDetails;

  _MockMessageHandler? _announcementHandler;
  List<CapturedAccessibilityAnnouncement> _announcements = <CapturedAccessibilityAnnouncement>[];

  /// {@template flutter.flutter_test.TakeAccessibilityAnnouncements}
  /// Returns a list of all the accessibility announcements made by the Flutter
  /// framework since the last time this function was called.
  ///
  /// It's safe to call this when there hasn't been any announcements; it will return
  /// an empty list in that case.
  /// {@endtemplate}
  List<CapturedAccessibilityAnnouncement> takeAnnouncements() {
    assert(inTest);
    final List<CapturedAccessibilityAnnouncement> announcements = _announcements;
    _announcements = <CapturedAccessibilityAnnouncement>[];
    return announcements;
  }

  static const TextStyle _messageStyle = TextStyle(color: Color(0xFF8F7FFF), fontSize: 40.0);

  static const Widget _preTestMessage = Center(
    child: Text('Test starting...', style: _messageStyle, textDirection: TextDirection.ltr),
  );

  static const Widget _postTestMessage = Center(
    child: Text('Test finished.', style: _messageStyle, textDirection: TextDirection.ltr),
  );

  /// Whether to include the output of debugDumpApp() when reporting
  /// test failures.
  bool showAppDumpInErrors = false;

  /// Call the testBody inside a [FakeAsync] scope on which [pump] can
  /// advance time.
  ///
  /// Returns a future which completes when the test has run.
  ///
  /// Called by the [testWidgets] and [benchmarkWidgets] functions to
  /// run a test.
  ///
  /// The `invariantTester` argument is called after the `testBody`'s [Future]
  /// completes. If it throws, then the test is marked as failed.
  ///
  /// The `description` is used by the [LiveTestWidgetsFlutterBinding] to
  /// show a label on the screen during the test. The description comes from
  /// the value passed to [testWidgets].
  Future<void> runTest(
    Future<void> Function() testBody,
    VoidCallback invariantTester, {
    String description = '',
  });

  /// This is called during test execution before and after the body has been
  /// executed.
  ///
  /// It's used by [AutomatedTestWidgetsFlutterBinding] to drain the microtasks
  /// before the final [pump] that happens during test cleanup.
  void asyncBarrier() {
    TestAsyncUtils.verifyAllScopesClosed();
  }

  Zone? _parentZone;
  Zone? _testZone;

  VoidCallback _createTestCompletionHandler(String testDescription, Completer<void> completer) {
    return () {
      // This can get called twice, in the case of a Future without listeners failing, and then
      // our main future completing.
      assert(Zone.current == _parentZone);
      if (_pendingExceptionDetails != null) {
        debugPrint =
            debugPrintOverride; // just in case the test overrides it -- otherwise we won't see the error!
        reportTestException(_pendingExceptionDetails!, testDescription);
        _pendingExceptionDetails = null;
      }
      if (!completer.isCompleted) {
        completer.complete();
      }
    };
  }

  /// Called when the framework catches an exception, even if that exception is
  /// being handled by [takeException].
  ///
  /// This is called when there is no pending exception; if multiple exceptions
  /// are thrown and [takeException] isn't used, then subsequent exceptions are
  /// logged to the console regardless (and the test will fail).
  @protected
  void reportExceptionNoticed(FlutterErrorDetails exception) {
    // By default we do nothing.
    // The LiveTestWidgetsFlutterBinding overrides this to report the exception to the console.
  }

  Future<void> _handleAnnouncementMessage(Object? mockMessage) async {
    if (mockMessage! case {
      'type': 'announce',
      'data': final Map<Object?, Object?> data as Map<Object?, Object?>,
    }) {
      _announcements.add(
        CapturedAccessibilityAnnouncement._(
          data['message'].toString(),
          data['viewId']! as int,
          TextDirection.values[data['textDirection']! as int],
          Assertiveness.values[(data['assertiveness'] ?? 0) as int],
        ),
      );
    }
  }

  Future<void> _runTest(
    Future<void> Function() testBody,
    VoidCallback invariantTester,
    String description,
  ) {
    assert(inTest);

    // Set the handler only if there is currently none.
    if (TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.checkMockMessageHandler(
      SystemChannels.accessibility.name,
      null,
    )) {
      _announcementHandler = _handleAnnouncementMessage;
      TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
          .setMockDecodedMessageHandler<dynamic>(
            SystemChannels.accessibility,
            _announcementHandler,
          );
    }

    _oldExceptionHandler = FlutterError.onError;
    _oldStackTraceDemangler = FlutterError.demangleStackTrace;
    var exceptionCount = 0; // number of un-taken exceptions
    FlutterError.onError = (FlutterErrorDetails details) {
      if (_pendingExceptionDetails != null) {
        debugPrint =
            debugPrintOverride; // just in case the test overrides it -- otherwise we won't see the errors!
        if (exceptionCount == 0) {
          exceptionCount = 2;
          FlutterError.dumpErrorToConsole(_pendingExceptionDetails!, forceReport: true);
        } else {
          exceptionCount += 1;
        }
        FlutterError.dumpErrorToConsole(details, forceReport: true);
        _pendingExceptionDetails = FlutterErrorDetails(
          exception:
              'Multiple exceptions ($exceptionCount) were detected during the running of the current test, and at least one was unexpected.',
          library: 'Flutter test framework',
        );
      } else {
        reportExceptionNoticed(
          details,
        ); // mostly this is just a hook for the LiveTestWidgetsFlutterBinding
        _pendingExceptionDetails = details;
      }
    };
    FlutterError.demangleStackTrace = (StackTrace stack) {
      // package:stack_trace uses ZoneSpecification.errorCallback to add useful
      // information to stack traces, meaning Trace and Chain classes can be
      // present. Because these StackTrace implementations do not follow the
      // format the framework expects, we convert them to a vm trace here.
      if (stack is stack_trace.Trace) {
        return stack.vmTrace;
      }
      if (stack is stack_trace.Chain) {
        return stack.toTrace().vmTrace;
      }
      return stack;
    };
    final testCompleter = Completer<void>();
    final VoidCallback testCompletionHandler = _createTestCompletionHandler(
      description,
      testCompleter,
    );
    void handleUncaughtError(Object exception, StackTrace stack) {
      if (testCompleter.isCompleted) {
        // Well this is not a good sign.
        // Ideally, once the test has failed we would stop getting errors from the test.
        // However, if someone tries hard enough they could get in a state where this happens.
        // If we silently dropped these errors on the ground, nobody would ever know. So instead
        // we raise them and fail the test after it has already completed.
        debugPrint =
            debugPrintOverride; // just in case the test overrides it -- otherwise we won't see the error!
        reportTestException(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            context: ErrorDescription('running a test (but after the test had completed)'),
            library: 'Flutter test framework',
          ),
          description,
        );
        return;
      }
      // This is where test failures, e.g. those in expect(), will end up.
      // Specifically, runUnaryGuarded() will call this synchronously and
      // return our return value if _runTestBody fails synchronously (which it
      // won't, so this never happens), and Future will call this when the
      // Future completes with an error and it would otherwise call listeners
      // if the listener is in a different zone (which it would be for the
      // `whenComplete` handler below), or if the Future completes with an
      // error and the future has no listeners at all.
      //
      // This handler further calls the onError handler above, which sets
      // _pendingExceptionDetails. Nothing gets printed as a result of that
      // call unless we already had an exception pending, because in general
      // we want people to be able to cause the framework to report exceptions
      // and then use takeException to verify that they were really caught.
      // Now, if we actually get here, this isn't going to be one of those
      // cases. We only get here if the test has actually failed. So, once
      // we've carefully reported it, we then immediately end the test by
      // calling the testCompletionHandler in the _parentZone.
      //
      // We have to manually call testCompletionHandler because if the Future
      // library calls us, it is maybe _instead_ of calling a registered
      // listener from a different zone. In our case, that would be instead of
      // calling the whenComplete() listener below.
      //
      // We have to call it in the parent zone because if we called it in
      // _this_ zone, the test framework would find this zone was the current
      // zone and helpfully throw the error in this zone, causing us to be
      // directly called again.
      DiagnosticsNode treeDump;
      try {
        treeDump = rootElement?.toDiagnosticsNode() ?? DiagnosticsNode.message('<no tree>');
        // We try to stringify the tree dump here (though we immediately discard the result) because
        // we want to make sure that if it can't be serialized, we replace it with a message that
        // says the tree could not be serialized. Otherwise, the real exception might get obscured
        // by side-effects of the underlying issues causing the tree dumping code to flail.
        treeDump.toStringDeep();
      } catch (exception) {
        treeDump = DiagnosticsNode.message(
          '<additional error caught while dumping tree: $exception>',
          level: DiagnosticLevel.error,
        );
      }
      final omittedFrames = <DiagnosticsNode>[];
      final int stackLinesToOmit = reportExpectCall(stack, omittedFrames);
      FlutterError.reportError(
        FlutterErrorDetails(
          exception: exception,
          stack: stack,
          context: ErrorDescription('running a test'),
          library: 'Flutter test framework',
          stackFilter: (Iterable<String> frames) {
            return FlutterError.defaultStackFilter(frames.skip(stackLinesToOmit));
          },
          informationCollector: () sync* {
            if (stackLinesToOmit > 0) {
              yield* omittedFrames;
            }
            if (showAppDumpInErrors) {
              yield DiagnosticsProperty<DiagnosticsNode>(
                'At the time of the failure, the widget tree looked as follows',
                treeDump,
                linePrefix: '# ',
                style: DiagnosticsTreeStyle.flat,
              );
            }
            if (description.isNotEmpty) {
              yield DiagnosticsProperty<String>(
                'The test description was',
                description,
                style: DiagnosticsTreeStyle.errorProperty,
              );
            }
          },
        ),
      );
      assert(_parentZone != null);
      assert(
        _pendingExceptionDetails != null,
        'A test overrode FlutterError.onError but either failed to return it to its original state, or had unexpected additional errors that it could not handle. Typically, this is caused by using expect() before restoring FlutterError.onError.',
      );
      _parentZone!.run<void>(testCompletionHandler);
    }

    final errorHandlingZoneSpecification = ZoneSpecification(
      handleUncaughtError:
          (Zone self, ZoneDelegate parent, Zone zone, Object exception, StackTrace stack) {
            handleUncaughtError(exception, stack);
          },
    );
    _parentZone = Zone.current;
    final Zone testZone = _parentZone!.fork(specification: errorHandlingZoneSpecification);
    _testZone = testZone;
    testZone
        .runBinary<Future<void>, Future<void> Function(), VoidCallback>(
          _runTestBody,
          testBody,
          invariantTester,
        )
        .whenComplete(testCompletionHandler);
    return testCompleter.future;
  }

  Future<void> _runTestBody(Future<void> Function() testBody, VoidCallback invariantTester) async {
    assert(inTest);
    // So that we can assert that it remains the same after the test finishes.
    _beforeTestCheckIntrinsicSizes = debugCheckIntrinsicSizes;

    runApp(Container(key: UniqueKey(), child: _preTestMessage)); // Reset the tree to a known state.
    await pump();
    // Pretend that the first frame produced in the test body is the first frame
    // sent to the engine.
    resetFirstFrameSent();

    final bool autoUpdateGoldensBeforeTest = autoUpdateGoldenFiles && !isBrowser;
    final TestExceptionReporter reportTestExceptionBeforeTest = reportTestException;
    final ErrorWidgetBuilder errorWidgetBuilderBeforeTest = ErrorWidget.builder;
    final bool shouldPropagateDevicePointerEventsBeforeTest = shouldPropagateDevicePointerEvents;

    // run the test
    await testBody();
    asyncBarrier(); // drains the microtasks in `flutter test` mode (when using AutomatedTestWidgetsFlutterBinding)

    if (_pendingExceptionDetails == null) {
      // We only try to clean up and verify invariants if we didn't already
      // fail. If we got an exception already, then we instead leave everything
      // alone so that we don't cause more spurious errors.
      runApp(
        Container(key: UniqueKey(), child: _postTestMessage),
      ); // Unmount any remaining widgets.
      await pump();
      _restorationManager?.dispose();
      _restorationManager = null;
      if (registerTestTextInput) {
        _testTextInput.unregister();
      }
      invariantTester();
      _verifyAutoUpdateGoldensUnset(autoUpdateGoldensBeforeTest && !isBrowser);
      _verifyReportTestExceptionUnset(reportTestExceptionBeforeTest);
      _verifyErrorWidgetBuilderUnset(errorWidgetBuilderBeforeTest);
      _verifyShouldPropagateDevicePointerEventsUnset(shouldPropagateDevicePointerEventsBeforeTest);
      _verifyInvariants();
    }

    assert(inTest);
    asyncBarrier(); // When using AutomatedTestWidgetsFlutterBinding, this flushes the microtasks.
  }

  late bool _beforeTestCheckIntrinsicSizes;

  void _verifyInvariants() {
    assert(
      debugAssertNoTransientCallbacks(
        'An animation is still running even after the widget tree was disposed.',
      ),
    );
    assert(
      debugAssertNoPendingPerformanceModeRequests(
        'A performance mode was requested and not disposed by a test.',
      ),
    );
    assert(debugAssertNoTimeDilation('The timeDilation was changed and not reset by the test.'));
    assert(
      debugAssertAllFoundationVarsUnset(
        'The value of a foundation debug variable was changed by the test.',
        debugPrintOverride: debugPrintOverride,
      ),
    );
    assert(
      debugAssertAllGesturesVarsUnset(
        'The value of a gestures debug variable was changed by the test.',
      ),
    );
    assert(
      debugAssertAllPaintingVarsUnset(
        'The value of a painting debug variable was changed by the test.',
        debugDisableShadowsOverride: disableShadows,
      ),
    );
    assert(
      debugAssertAllRenderVarsUnset(
        'The value of a rendering debug variable was changed by the test.',
        debugCheckIntrinsicSizesOverride: _beforeTestCheckIntrinsicSizes,
      ),
    );
    assert(
      debugAssertAllWidgetVarsUnset(
        'The value of a widget debug variable was changed by the test.',
      ),
    );
    assert(
      debugAssertAllSchedulerVarsUnset(
        'The value of a scheduler debug variable was changed by the test.',
      ),
    );
    assert(
      debugAssertAllServicesVarsUnset(
        'The value of a services debug variable was changed by the test.',
      ),
    );
  }

  void _verifyAutoUpdateGoldensUnset(bool valueBeforeTest) {
    assert(() {
      if (autoUpdateGoldenFiles != valueBeforeTest) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: FlutterError('The value of autoUpdateGoldenFiles was changed by the test.'),
            stack: StackTrace.current,
            library: 'Flutter test framework',
          ),
        );
      }
      return true;
    }());
  }

  void _verifyReportTestExceptionUnset(TestExceptionReporter valueBeforeTest) {
    assert(() {
      if (reportTestException != valueBeforeTest) {
        // We can't report this error to their modified reporter because we
        // can't be guaranteed that their reporter will cause the test to fail.
        // So we reset the error reporter to its initial value and then report
        // this error.
        reportTestException = valueBeforeTest;
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: FlutterError('The value of reportTestException was changed by the test.'),
            stack: StackTrace.current,
            library: 'Flutter test framework',
          ),
        );
      }
      return true;
    }());
  }

  void _verifyErrorWidgetBuilderUnset(ErrorWidgetBuilder valueBeforeTest) {
    assert(() {
      if (ErrorWidget.builder != valueBeforeTest) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: FlutterError('The value of ErrorWidget.builder was changed by the test.'),
            stack: StackTrace.current,
            library: 'Flutter test framework',
          ),
        );
      }
      return true;
    }());
  }

  void _verifyShouldPropagateDevicePointerEventsUnset(bool valueBeforeTest) {
    assert(() {
      if (shouldPropagateDevicePointerEvents != valueBeforeTest) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: FlutterError(
              'The value of shouldPropagateDevicePointerEvents was changed by the test.',
            ),
            stack: StackTrace.current,
            library: 'Flutter test framework',
          ),
        );
      }
      return true;
    }());
  }

  /// Replaces the root layers of all managed [renderViews] with new, unused
  /// layers.
  ///
  /// This method is typically used in a test's [addTearDown] to ensure that
  /// resources associated with the root transform layer are properly disposed
  /// of between tests. It is useful for tests that modify the view
  /// configuration (for example, by calling [setSurfaceSize] or changing
  /// [ViewConfiguration]). Such tests might cause the root layer to not be
  /// automatically disposed before the leak check, triggering false negatives.
  ///
  /// This method also resets view configuration to its default value.
  ///
  /// See also:
  ///
  ///  * [setSurfaceSize], which often necessitates calling this method during
  ///    tear down.
  Future<void> resetLayers() async {
    await setSurfaceSize(null);
    for (final RenderView renderView in renderViews) {
      // To reliably trigger [RenderView.replaceRootLayer], we assign a new
      // device pixel ratio that differs from the current one.
      renderView.configuration = ViewConfiguration(
        devicePixelRatio: renderView.flutterView.devicePixelRatio + 1.0,
      );
      // Reset the device pixel ratio (and other view configurations) to their
      // default values.
      renderView.configuration = createViewConfigurationFor(renderView);
    }
  }

  /// Called by the [testWidgets] function after a test is executed.
  void postTest() {
    assert(inTest);
    FlutterError.onError = _oldExceptionHandler;
    FlutterError.demangleStackTrace = _oldStackTraceDemangler;
    _pendingExceptionDetails = null;
    _parentZone = null;
    _testZone = null;
    buildOwner!.focusManager.dispose();

    if (TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.checkMockMessageHandler(
      SystemChannels.accessibility.name,
      _announcementHandler,
    )) {
      TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
          .setMockDecodedMessageHandler(SystemChannels.accessibility, null);
      _announcementHandler = null;
    }
    _announcements = <CapturedAccessibilityAnnouncement>[];

    ServicesBinding.instance.keyEventManager.keyMessageHandler = null;
    buildOwner!.focusManager = FocusManager()..registerGlobalHandlers();

    // Disabling the warning because @visibleForTesting doesn't take the testing
    // framework itself into account, but we don't want it visible outside of
    // tests.
    // ignore: invalid_use_of_visible_for_testing_member
    RawKeyboard.instance.clearKeysPressed();
    // ignore: invalid_use_of_visible_for_testing_member
    HardwareKeyboard.instance.clearState();
    // ignore: invalid_use_of_visible_for_testing_member
    keyEventManager.clearState();
    // ignore: invalid_use_of_visible_for_testing_member
    RendererBinding.instance.initMouseTracker();

    assert(ServicesBinding.instance == WidgetsBinding.instance);
    // ignore: invalid_use_of_visible_for_testing_member
    ServicesBinding.instance.resetInternalState();
  }
}

/// A variant of [TestWidgetsFlutterBinding] for executing tests typically
/// the `flutter test` environment, unless it is an integration test.
///
/// When doing integration test, [LiveTestWidgetsFlutterBinding] is utilized
/// instead.
///
/// This binding controls time, allowing tests to verify long
/// animation sequences without having to execute them in real time.
///
/// This class assumes it is always run in debug mode (since tests are always
/// run in debug mode).
///
/// See [TestWidgetsFlutterBinding] for a list of mixins that must be
/// provided by the binding active while the test framework is
/// running.
class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    binding.mockFlutterAssets();
  }

  /// The current [AutomatedTestWidgetsFlutterBinding], if one has been created.
  ///
  /// The binding must be initialized before using this getter. If you
  /// need the binding to be constructed before calling [testWidgets],
  /// you can ensure a binding has been constructed by calling the
  /// [TestWidgetsFlutterBinding.ensureInitialized] function.
  static AutomatedTestWidgetsFlutterBinding get instance => BindingBase.checkInstance(_instance);
  static AutomatedTestWidgetsFlutterBinding? _instance;

  /// Returns an instance of the binding that implements
  /// [AutomatedTestWidgetsFlutterBinding]. If no binding has yet been
  /// initialized, the a new instance is created.
  ///
  /// Generally, there is no need to call this method. Use
  /// [TestWidgetsFlutterBinding.ensureInitialized] instead, as it
  /// will select the correct test binding implementation
  /// automatically.
  static AutomatedTestWidgetsFlutterBinding ensureInitialized() {
    if (AutomatedTestWidgetsFlutterBinding._instance == null) {
      AutomatedTestWidgetsFlutterBinding();
    }
    return AutomatedTestWidgetsFlutterBinding.instance;
  }

  FakeAsync? _currentFakeAsync; // set in runTest; cleared in postTest
  Completer<void>? _pendingAsyncTasks;

  @override
  Clock get clock {
    assert(inTest);
    return _clock!;
  }

  Clock? _clock;

  @override
  DebugPrintCallback get debugPrintOverride => debugPrintSynchronously;

  @override
  bool get disableShadows => true;

  /// The value of [defaultTestTimeout] can be set to `None` to enable debugging
  /// flutter tests where we would not want to timeout the test. This is
  /// expected to be used by test tooling which can detect debug mode.
  @override
  test_package.Timeout defaultTestTimeout = const test_package.Timeout(Duration(minutes: 10));

  @override
  bool get inTest => _currentFakeAsync != null;

  @override
  int get microtaskCount => _currentFakeAsync!.microtaskCount;

  @override
  Future<void> pump([Duration? duration, EnginePhase newPhase = EnginePhase.sendSemanticsUpdate]) {
    return TestAsyncUtils.guard<void>(() {
      assert(inTest);
      assert(_clock != null);
      if (duration != null) {
        _currentFakeAsync!.elapse(duration);
      }
      _phase = newPhase;
      if (hasScheduledFrame) {
        _currentFakeAsync!.flushMicrotasks();
        handleBeginFrame(Duration(microseconds: _clock!.now().microsecondsSinceEpoch));
        _currentFakeAsync!.flushMicrotasks();
        handleDrawFrame();
      }
      _currentFakeAsync!.flushMicrotasks();
      return Future<void>.value();
    });
  }

  @override
  Future<T?> runAsync<T>(Future<T> Function() callback) {
    assert(() {
      if (_pendingAsyncTasks == null) {
        return true;
      }
      fail(
        'Reentrant call to runAsync() denied.\n'
        'runAsync() was called, then before its future completed, it '
        'was called again. You must wait for the first returned future '
        'to complete before calling runAsync() again.',
      );
    }());

    final Zone realAsyncZone = Zone.current.fork(
      specification: ZoneSpecification(
        scheduleMicrotask: (Zone self, ZoneDelegate parent, Zone zone, void Function() f) {
          _rootDelegate.scheduleMicrotask(zone, f);
        },
        createTimer:
            (Zone self, ZoneDelegate parent, Zone zone, Duration duration, void Function() f) {
              return _rootDelegate.createTimer(zone, duration, f);
            },
        createPeriodicTimer:
            (
              Zone self,
              ZoneDelegate parent,
              Zone zone,
              Duration period,
              void Function(Timer timer) f,
            ) {
              return _rootDelegate.createPeriodicTimer(zone, period, f);
            },
      ),
    );

    return realAsyncZone.run<Future<T?>>(() {
      final result = Completer<T?>();
      _pendingAsyncTasks = Completer<void>();
      try {
        callback().then(result.complete).catchError((Object exception, StackTrace stack) {
          FlutterError.reportError(
            FlutterErrorDetails(
              exception: exception,
              stack: stack,
              library: 'Flutter test framework',
              context: ErrorDescription('while running async test code'),
              informationCollector: () {
                return <DiagnosticsNode>[ErrorHint('The exception was caught asynchronously.')];
              },
            ),
          );
          result.complete(null);
        });
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'Flutter test framework',
            context: ErrorDescription('while running async test code'),
            informationCollector: () {
              return <DiagnosticsNode>[ErrorHint('The exception was caught synchronously.')];
            },
          ),
        );
        result.complete(null);
      }
      result.future.whenComplete(() {
        _pendingAsyncTasks!.complete();
        _pendingAsyncTasks = null;
      });
      return result.future;
    });
  }

  @override
  void ensureFrameCallbacksRegistered() {
    // Leave PlatformDispatcher alone, do nothing.
    assert(platformDispatcher.onDrawFrame == null);
    assert(platformDispatcher.onBeginFrame == null);
  }

  @override
  void scheduleWarmUpFrame() {
    // We override the default version of this so that the application-startup warm-up frame
    // does not schedule timers which we might never get around to running.
    assert(inTest);
    handleBeginFrame(null);
    _currentFakeAsync!.flushMicrotasks();
    handleDrawFrame();
    _currentFakeAsync!.flushMicrotasks();
  }

  /// The [ZoneDelegate] for [Zone.root].
  ///
  /// Used to schedule (real) microtasks and timers in the root zone,
  /// to be run in the correct zone.
  static final ZoneDelegate _rootDelegate = _captureRootZoneDelegate();

  /// Hack to extract the [ZoneDelegate] for [Zone.root].
  static ZoneDelegate _captureRootZoneDelegate() {
    final Zone captureZone = Zone.root.fork(
      specification: ZoneSpecification(
        run: <R>(Zone self, ZoneDelegate parent, Zone zone, R Function() f) {
          return parent as R;
        },
      ),
    );
    // The `_captureRootZoneDelegate` argument just happens to be a constant
    // function with the necessary type. It's not called recursively.
    return captureZone.run<ZoneDelegate>(_captureRootZoneDelegate);
  }

  @override
  void scheduleAttachRootWidget(Widget rootWidget) {
    // We override the default version of this so that the application-startup widget tree
    // build does not schedule timers which we might never get around to running.
    assert(inTest);
    attachRootWidget(rootWidget);
    _currentFakeAsync!.flushMicrotasks();
  }

  @override
  Future<void> idle() {
    assert(inTest);
    final Future<void> result = super.idle();
    _currentFakeAsync!.elapse(Duration.zero);
    return result;
  }

  int _firstFrameDeferredCount = 0;
  bool _firstFrameSent = false;

  @override
  bool get sendFramesToEngine => _firstFrameSent || _firstFrameDeferredCount == 0;

  @override
  void deferFirstFrame() {
    assert(_firstFrameDeferredCount >= 0);
    _firstFrameDeferredCount += 1;
  }

  @override
  void allowFirstFrame() {
    assert(_firstFrameDeferredCount > 0);
    _firstFrameDeferredCount -= 1;
    // Unlike in RendererBinding.allowFirstFrame we do not force a frame here
    // to give the test full control over frame scheduling.
  }

  @override
  void resetFirstFrameSent() {
    _firstFrameSent = false;
  }

  EnginePhase _phase = EnginePhase.sendSemanticsUpdate;

  // Cloned from RendererBinding.drawFrame() but with early-exit semantics.
  @override
  void drawFrame() {
    assert(inTest);
    try {
      debugBuildingDirtyElements = true;
      buildOwner!.buildScope(rootElement!);
      if (_phase != EnginePhase.build) {
        rootPipelineOwner.flushLayout();
        if (_phase != EnginePhase.layout) {
          rootPipelineOwner.flushCompositingBits();
          if (_phase != EnginePhase.compositingBits) {
            rootPipelineOwner.flushPaint();
            if (_phase != EnginePhase.paint && sendFramesToEngine) {
              _firstFrameSent = true;
              for (final RenderView renderView in renderViews) {
                renderView.compositeFrame(); // this sends the bits to the GPU
              }
              if (_phase != EnginePhase.composite) {
                rootPipelineOwner.flushSemantics(); // this sends the semantics to the OS.
                assert(
                  _phase == EnginePhase.flushSemantics || _phase == EnginePhase.sendSemanticsUpdate,
                );
              }
            }
          }
        }
      }
      buildOwner!.finalizeTree();
    } finally {
      debugBuildingDirtyElements = false;
    }
  }

  @override
  Future<void> delayed(Duration duration) {
    assert(_currentFakeAsync != null);
    _currentFakeAsync!.elapse(duration);
    return Future<void>.value();
  }

  /// Simulates the synchronous passage of time, resulting from blocking or
  /// expensive calls.
  void elapseBlocking(Duration duration) {
    _currentFakeAsync!.elapseBlocking(duration);
  }

  @override
  Future<void> runTest(
    Future<void> Function() testBody,
    VoidCallback invariantTester, {
    String description = '',
  }) {
    assert(!inTest);
    assert(_currentFakeAsync == null);
    assert(_clock == null);

    final fakeAsync = FakeAsync();
    _currentFakeAsync = fakeAsync; // reset in postTest
    _clock = fakeAsync.getClock(DateTime.utc(2015));
    late Future<void> testBodyResult;
    fakeAsync.run((FakeAsync localFakeAsync) {
      assert(fakeAsync == _currentFakeAsync);
      assert(fakeAsync == localFakeAsync);
      testBodyResult = _runTest(testBody, invariantTester, description);
      assert(inTest);
    });

    return Future<void>.microtask(() async {
      // testBodyResult is a Future that was created in the Zone of the
      // fakeAsync. This means that if we await it here, it will register a
      // microtask to handle the future _in the fake async zone_. We avoid this
      // by calling '.then' in the current zone. While flushing the microtasks
      // of the fake-zone below, the new future will be completed and can then
      // be used without fakeAsync.

      final Future<void> resultFuture = testBodyResult.then<void>((_) {
        // Do nothing.
      });

      // Resolve interplay between fake async and real async calls.
      fakeAsync.flushMicrotasks();
      while (_pendingAsyncTasks != null) {
        await _pendingAsyncTasks!.future;
        fakeAsync.flushMicrotasks();
      }
      return resultFuture;
    });
  }

  @override
  void asyncBarrier() {
    assert(_currentFakeAsync != null);
    _currentFakeAsync!.flushMicrotasks();
    super.asyncBarrier();
  }

  @override
  void _verifyInvariants() {
    super._verifyInvariants();

    assert(inTest);

    var timersPending = false;
    if (_currentFakeAsync!.periodicTimerCount != 0 ||
        _currentFakeAsync!.nonPeriodicTimerCount != 0) {
      debugPrint('Pending timers:');
      for (final FakeTimer timer in _currentFakeAsync!.pendingTimers) {
        debugPrint(
          'Timer (duration: ${timer.duration}, '
          'periodic: ${timer.isPeriodic}), created:',
        );
        debugPrintStack(stackTrace: timer.creationStackTrace);
        debugPrint('');
      }
      timersPending = true;
    }
    assert(!timersPending, 'A Timer is still pending even after the widget tree was disposed.');
    assert(_currentFakeAsync!.microtaskCount == 0); // Shouldn't be possible.
  }

  @override
  void postTest() {
    super.postTest();
    assert(_currentFakeAsync != null);
    assert(_clock != null);
    _clock = null;
    _currentFakeAsync = null;
  }
}

/// Available policies for how a [LiveTestWidgetsFlutterBinding] should paint
/// frames.
///
/// These values are set on the binding's
/// [LiveTestWidgetsFlutterBinding.framePolicy] property.
///
/// {@template flutter.flutter_test.LiveTestWidgetsFlutterBindingFramePolicy}
/// The default is [LiveTestWidgetsFlutterBindingFramePolicy.fadePointers].
/// Setting this to anything other than
/// [LiveTestWidgetsFlutterBindingFramePolicy.onlyPumps] results in pumping
/// extra frames, which might involve calling builders more, or calling paint
/// callbacks more, etc, and might interfere with the test. If you know that
/// your test won't be affected by this, you can set the policy to
/// [LiveTestWidgetsFlutterBindingFramePolicy.fullyLive] or
/// [LiveTestWidgetsFlutterBindingFramePolicy.benchmarkLive] in that particular
/// file.
///
/// To set a value while still allowing the test file to work as a normal test,
/// add the following code to your test file at the top of your
/// `void main() { }` function, before calls to [testWidgets]:
///
/// ```dart
/// TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
/// if (binding is LiveTestWidgetsFlutterBinding) {
///   binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.onlyPumps;
/// }
/// ```
/// {@endtemplate}
enum LiveTestWidgetsFlutterBindingFramePolicy {
  /// Strictly show only frames that are explicitly pumped.
  ///
  /// This most closely matches the [AutomatedTestWidgetsFlutterBinding]
  /// (the default binding for `flutter test`) behavior.
  onlyPumps,

  /// Show pumped frames, and additionally schedule and run frames to fade
  /// out the pointer crosshairs and other debugging information shown by
  /// the binding.
  ///
  /// This will schedule frames when pumped or when there has been some
  /// activity with [TestPointer]s.
  ///
  /// This can result in additional frames being pumped beyond those that
  /// the test itself requests, which can cause differences in behavior.
  fadePointers,

  /// Show every frame that the framework requests, even if the frames are not
  /// explicitly pumped.
  ///
  /// The major difference between [fullyLive] and [benchmarkLive] is the latter
  /// ignores frame requests by [WidgetTester.pump].
  ///
  /// This can help with orienting the developer when looking at
  /// heavily-animated situations, and will almost certainly result in
  /// additional frames being pumped beyond those that the test itself requests,
  /// which can cause differences in behavior.
  fullyLive,

  /// Ignore any request to schedule a frame.
  ///
  /// This is intended to be used by benchmarks (hence the name) that drive the
  /// pipeline directly. It tells the binding to entirely ignore requests for a
  /// frame to be scheduled, while still allowing frames that are pumped
  /// directly to run (either by using [WidgetTester.pumpBenchmark] or invoking
  /// [PlatformDispatcher.onBeginFrame] and [PlatformDispatcher.onDrawFrame]).
  ///
  /// This allows all frame requests from the engine to be serviced, and allows
  /// all frame requests that are artificially triggered to be serviced, but
  /// ignores [SchedulerBinding.scheduleFrame] requests from the framework.
  /// Therefore animation won't run for this mode because the framework
  /// generates an animation by requesting new frames.
  ///
  /// The [SchedulerBinding.hasScheduledFrame] property will never be true in
  /// this mode. This can cause unexpected effects. For instance,
  /// [WidgetTester.pumpAndSettle] does not function in this mode, as it relies
  /// on the [SchedulerBinding.hasScheduledFrame] property to determine when the
  /// application has "settled".
  benchmark,

  /// Ignore any request from pump but respect other requests to schedule a
  /// frame.
  ///
  /// This is used for running the test on a device, where scheduling of new
  /// frames respects what the engine and the device needed.
  ///
  /// Compared to [fullyLive] this policy ignores the frame requests from
  /// [WidgetTester.pump] so that frame scheduling mimics that of the real
  /// environment, and avoids waiting for an artificially pumped frame. (For
  /// example, when driving the test in methods like
  /// [WidgetTester.handlePointerEventRecord] or [WidgetTester.fling].)
  ///
  /// This policy differs from [benchmark] in that it can be used for capturing
  /// animation frames requested by the framework.
  benchmarkLive,
}

enum _HandleDrawFrame { reset, drawFrame, skipFrame }

/// A variant of [TestWidgetsFlutterBinding] for executing tests
/// on a device, typically via `flutter run`, or via integration tests.
/// This is intended to allow interactive test development.
///
/// This is not the way to run a remote-control test. To run a test on
/// a device from a development computer, see the [flutter_driver]
/// package and the `flutter drive` command.
///
/// When running tests using `flutter run`, consider adding the
/// `--use-test-fonts` argument so that the fonts used match those used under
/// `flutter test`. (This forces all text to use the "Ahem" font, which is a
/// font that covers ASCII characters and gives them all the appearance of a
/// square whose size equals the font size.)
///
/// This binding overrides the default [SchedulerBinding] behavior to ensure
/// that tests work in the same way in this environment as they would under the
/// [AutomatedTestWidgetsFlutterBinding]. To override this (and see intermediate
/// frames that the test does not explicitly trigger), set [framePolicy] to
/// [LiveTestWidgetsFlutterBindingFramePolicy.fullyLive]. (This is likely to
/// make tests fail, though, especially if e.g. they test how many times a
/// particular widget was built.) The default behavior is to show pumped frames
/// and a few additional frames when pointers are triggered (to animate the
/// pointer crosshairs).
///
/// This binding does not support the [EnginePhase] argument to
/// [pump]. (There would be no point setting it to a value that
/// doesn't trigger a paint, since then you could not see anything
/// anyway.)
///
/// See [TestWidgetsFlutterBinding] for a list of mixins that must be
/// provided by the binding active while the test framework is
/// running.
class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;

    RenderView.debugAddPaintCallback(_handleRenderViewPaint);
  }

  /// The current [LiveTestWidgetsFlutterBinding], if one has been created.
  ///
  /// The binding must be initialized before using this getter. If you
  /// need the binding to be constructed before calling [testWidgets],
  /// you can ensure a binding has been constructed by calling the
  /// [TestWidgetsFlutterBinding.ensureInitialized] function.
  static LiveTestWidgetsFlutterBinding get instance => BindingBase.checkInstance(_instance);
  static LiveTestWidgetsFlutterBinding? _instance;

  /// Returns an instance of the binding that implements
  /// [LiveTestWidgetsFlutterBinding]. If no binding has yet been
  /// initialized, the a new instance is created.
  ///
  /// Generally, there is no need to call this method. Use
  /// [TestWidgetsFlutterBinding.ensureInitialized] instead, as it
  /// will select the correct test binding implementation
  /// automatically.
  static LiveTestWidgetsFlutterBinding ensureInitialized() {
    if (LiveTestWidgetsFlutterBinding._instance == null) {
      LiveTestWidgetsFlutterBinding();
    }
    return LiveTestWidgetsFlutterBinding.instance;
  }

  @override
  bool get inTest => _inTest;
  bool _inTest = false;

  @override
  Clock get clock => const Clock();

  @override
  int get microtaskCount {
    // The Dart SDK doesn't report this number.
    assert(false, 'microtaskCount cannot be reported when running in real time');
    return -1;
  }

  @override
  test_package.Timeout get defaultTestTimeout => test_package.Timeout.none;

  Completer<void>? _pendingFrame;
  bool _expectingFrame = false;
  bool _expectingFrameToReassemble = false;
  bool _viewNeedsPaint = false;
  bool _runningAsyncTasks = false;

  /// The strategy for [pump]ing and requesting new frames.
  ///
  /// The policy decides whether [pump] (with a duration) pumps a single frame
  /// (as would happen in a normal test environment using
  /// [AutomatedTestWidgetsFlutterBinding]), or pumps every frame that the
  /// system requests during an asynchronous pause (as would normally happen
  /// when running an application with [WidgetsFlutterBinding]).
  ///
  /// {@macro flutter.flutter_test.LiveTestWidgetsFlutterBindingFramePolicy}
  ///
  /// See [LiveTestWidgetsFlutterBindingFramePolicy].
  LiveTestWidgetsFlutterBindingFramePolicy framePolicy =
      LiveTestWidgetsFlutterBindingFramePolicy.fadePointers;

  @override
  Future<void> delayed(Duration duration) {
    return Future<void>.delayed(duration);
  }

  @override
  void scheduleFrame() {
    if (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmark) {
      // In benchmark mode, don't actually schedule any engine frames.
      return;
    }
    super.scheduleFrame();
  }

  @override
  void scheduleForcedFrame() {
    if (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmark) {
      // In benchmark mode, don't actually schedule any engine frames.
      return;
    }
    super.scheduleForcedFrame();
  }

  @override
  Future<void> reassembleApplication() {
    _expectingFrameToReassemble = true;
    return super.reassembleApplication();
  }

  _HandleDrawFrame _drawFrame = _HandleDrawFrame.reset;

  @override
  void handleBeginFrame(Duration? rawTimeStamp) {
    if (_testZone != null) {
      _testZone!.runUnary<void, Duration?>(_handleBeginFrame, rawTimeStamp);
    } else {
      _handleBeginFrame(rawTimeStamp);
    }
  }

  void _handleBeginFrame(Duration? rawTimeStamp) {
    if (_drawFrame != _HandleDrawFrame.reset) {
      throw StateError('handleBeginFrame() called before previous handleDrawFrame()');
    }
    if (_expectingFrame ||
        _expectingFrameToReassemble ||
        (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.fullyLive) ||
        (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmarkLive) ||
        (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmark) ||
        (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.fadePointers && _viewNeedsPaint)) {
      _drawFrame = _HandleDrawFrame.drawFrame;
      super.handleBeginFrame(rawTimeStamp);
    } else {
      _drawFrame = _HandleDrawFrame.skipFrame;
    }
  }

  @override
  void handleDrawFrame() {
    if (_testZone != null) {
      _testZone!.run<void>(_handleDrawFrame);
    } else {
      _handleDrawFrame();
    }
  }

  void _handleDrawFrame() {
    if (_drawFrame == _HandleDrawFrame.reset) {
      throw StateError('handleDrawFrame() called without paired handleBeginFrame()');
    }
    if (_drawFrame == _HandleDrawFrame.drawFrame) {
      super.handleDrawFrame();
    }
    _drawFrame = _HandleDrawFrame.reset;
    _viewNeedsPaint = false;
    _expectingFrameToReassemble = false;
    if (_expectingFrame) {
      // set during pump
      assert(_pendingFrame != null);
      _pendingFrame!.complete(); // unlocks the test API
      _pendingFrame = null;
      _expectingFrame = false;
    } else if (framePolicy != LiveTestWidgetsFlutterBindingFramePolicy.benchmark) {
      platformDispatcher.scheduleFrame();
    }
  }

  void _markViewsNeedPaint([int? viewId]) {
    _viewNeedsPaint = true;
    final Iterable<RenderView> toMark = viewId == null
        ? renderViews
        : renderViews.where((RenderView renderView) => renderView.flutterView.viewId == viewId);
    for (final renderView in toMark) {
      renderView.markNeedsPaint();
    }
  }

  TextPainter? _label;
  static const TextStyle _labelStyle = TextStyle(fontFamily: 'sans-serif', fontSize: 10.0);

  /// Label describing the test.
  @visibleForTesting
  TextPainter? get label => _label;

  /// Set a description label that is drawn into the test output.
  @protected
  void setLabel(String value) {
    if (value.isEmpty) {
      _label = null;
      return;
    }
    // TODO(ianh): Figure out if the test name is actually RTL.
    _label ??= TextPainter(textAlign: TextAlign.left, textDirection: TextDirection.ltr);
    _label!.text = TextSpan(text: value, style: _labelStyle);
    _label!.layout();
    _markViewsNeedPaint();
  }

  final Expando<Map<int, _LiveTestPointerRecord>> _renderViewToPointerIdToPointerRecord =
      Expando<Map<int, _LiveTestPointerRecord>>();

  void _handleRenderViewPaint(PaintingContext context, Offset offset, RenderView renderView) {
    assert(offset == Offset.zero);

    final Map<int, _LiveTestPointerRecord>? pointerIdToRecord =
        _renderViewToPointerIdToPointerRecord[renderView];
    if (pointerIdToRecord != null && pointerIdToRecord.isNotEmpty) {
      final double radius = renderView.size.shortestSide * 0.05;
      final path = Path()
        ..addOval(Rect.fromCircle(center: Offset.zero, radius: radius))
        ..moveTo(0.0, -radius * 2.0)
        ..lineTo(0.0, radius * 2.0)
        ..moveTo(-radius * 2.0, 0.0)
        ..lineTo(radius * 2.0, 0.0);
      final Canvas canvas = context.canvas;
      final paint = Paint()
        ..strokeWidth = radius / 10.0
        ..style = PaintingStyle.stroke;
      var dirty = false;
      for (final _LiveTestPointerRecord record in pointerIdToRecord.values) {
        paint.color = record.color.withOpacity(
          record.decay < 0 ? (record.decay / (_kPointerDecay - 1)) : 1.0,
        );
        canvas.drawPath(path.shift(record.position), paint);
        if (record.decay < 0) {
          dirty = true;
        }
        record.decay += 1;
      }
      pointerIdToRecord.keys
          .where((int pointer) => pointerIdToRecord[pointer]!.decay == 0)
          .toList()
          .forEach(pointerIdToRecord.remove);
      if (dirty) {
        scheduleMicrotask(() {
          _markViewsNeedPaint(renderView.flutterView.viewId);
        });
      }
    }

    _label?.paint(context.canvas, offset - const Offset(0.0, 10.0));
  }

  /// An object to which real device events should be routed.
  ///
  /// Normally, device events are silently dropped. However, if this property is
  /// set to a non-null value, then the events will be routed to its
  /// [HitTestDispatcher.dispatchEvent] method instead, unless
  /// [shouldPropagateDevicePointerEvents] is true.
  ///
  /// Events dispatched by [TestGesture] are not affected by this.
  HitTestDispatcher? deviceEventDispatcher;

  /// Dispatch an event to the targets found by a hit test on its position.
  ///
  /// If the [pointerEventSource] is [TestBindingEventSource.test], then
  /// the event is forwarded to [GestureBinding.dispatchEvent] as usual;
  /// additionally, down pointers are painted on the screen.
  ///
  /// If the [pointerEventSource] is [TestBindingEventSource.device], then
  /// the event, after being transformed to the local coordinate system, is
  /// forwarded to [deviceEventDispatcher].
  @override
  void handlePointerEvent(PointerEvent event) {
    if (_testZone != null) {
      _testZone!.runUnary<void, PointerEvent>(_handlePointerEvent, event);
    } else {
      _handlePointerEvent(event);
    }
  }

  void _handlePointerEvent(PointerEvent event) {
    switch (pointerEventSource) {
      case TestBindingEventSource.test:
        RenderView? target;
        for (final RenderView renderView in renderViews) {
          if (renderView.flutterView.viewId == event.viewId) {
            target = renderView;
            break;
          }
        }
        if (target != null) {
          final _LiveTestPointerRecord? record =
              _renderViewToPointerIdToPointerRecord[target]?[event.pointer];
          if (record != null) {
            record.position = event.position;
            if (!event.down) {
              record.decay = _kPointerDecay;
            }
            _markViewsNeedPaint(event.viewId);
          } else if (event.down) {
            _renderViewToPointerIdToPointerRecord[target] ??= <int, _LiveTestPointerRecord>{};
            _renderViewToPointerIdToPointerRecord[target]![event.pointer] = _LiveTestPointerRecord(
              event.pointer,
              event.position,
            );
            _markViewsNeedPaint(event.viewId);
          }
        }
        super.handlePointerEvent(event);
      case TestBindingEventSource.device:
        if (shouldPropagateDevicePointerEvents) {
          super.handlePointerEvent(event);
          break;
        }
        if (deviceEventDispatcher != null) {
          // The pointer events received with this source has a global position
          // (see [handlePointerEventForSource]). Transform it to the local
          // coordinate space used by the testing widgets.
          final RenderView renderView = renderViews.firstWhere(
            (RenderView r) => r.flutterView.viewId == event.viewId,
          );
          final PointerEvent localEvent = event.copyWith(
            position: globalToLocal(event.position, renderView),
          );
          withPointerEventSource(
            TestBindingEventSource.device,
            () => super.handlePointerEvent(localEvent),
          );
        }
    }
  }

  @override
  void dispatchEvent(PointerEvent event, HitTestResult? hitTestResult) {
    switch (pointerEventSource) {
      case TestBindingEventSource.test:
        super.dispatchEvent(event, hitTestResult);
      case TestBindingEventSource.device:
        assert(hitTestResult != null || event is PointerAddedEvent || event is PointerRemovedEvent);
        if (shouldPropagateDevicePointerEvents) {
          super.dispatchEvent(event, hitTestResult);
          break;
        }
        assert(deviceEventDispatcher != null);
        if (hitTestResult != null) {
          deviceEventDispatcher!.dispatchEvent(event, hitTestResult);
        }
    }
  }

  @override
  Future<void> pump([Duration? duration, EnginePhase newPhase = EnginePhase.sendSemanticsUpdate]) {
    assert(newPhase == EnginePhase.sendSemanticsUpdate);
    assert(inTest);
    assert(!_expectingFrame);
    assert(_pendingFrame == null);
    if (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmarkLive) {
      // Ignore all pumps and just wait.
      return delayed(duration ?? Duration.zero);
    }
    return TestAsyncUtils.guard<void>(() {
      if (duration != null) {
        Timer(duration, () {
          _expectingFrame = true;
          scheduleFrame();
        });
      } else {
        _expectingFrame = true;
        scheduleFrame();
      }
      _pendingFrame = Completer<void>();
      return _pendingFrame!.future;
    });
  }

  @override
  Future<T?> runAsync<T>(Future<T> Function() callback) async {
    assert(() {
      if (!_runningAsyncTasks) {
        return true;
      }
      fail(
        'Reentrant call to runAsync() denied.\n'
        'runAsync() was called, then before its future completed, it '
        'was called again. You must wait for the first returned future '
        'to complete before calling runAsync() again.',
      );
    }());

    _runningAsyncTasks = true;
    try {
      return await callback();
    } catch (error, stack) {
      FlutterError.reportError(
        FlutterErrorDetails(
          exception: error,
          stack: stack,
          library: 'Flutter test framework',
          context: ErrorSummary('while running async test code'),
        ),
      );
      return null;
    } finally {
      _runningAsyncTasks = false;
    }
  }

  @override
  Future<void> runTest(
    Future<void> Function() testBody,
    VoidCallback invariantTester, {
    String description = '',
  }) {
    assert(!inTest);
    _inTest = true;
    setLabel(description);
    return _runTest(testBody, invariantTester, description);
  }

  @override
  void reportExceptionNoticed(FlutterErrorDetails exception) {
    final DebugPrintCallback testPrint = debugPrint;
    debugPrint = debugPrintOverride;
    debugPrint('(The following exception is now available via WidgetTester.takeException:)');
    FlutterError.dumpErrorToConsole(exception, forceReport: true);
    debugPrint(
      '(If WidgetTester.takeException is called, the above exception will be ignored. '
      'If it is not, then the above exception will be dumped when another exception is '
      'caught by the framework or when the test ends, whichever happens first, and then '
      'the test will fail due to having not caught or expected the exception.)',
    );
    debugPrint = testPrint;
  }

  @override
  void postTest() {
    super.postTest();
    assert(!_expectingFrame);
    assert(_pendingFrame == null);
    _inTest = false;
  }

  @override
  ViewConfiguration createViewConfigurationFor(RenderView renderView) {
    final FlutterView view = renderView.flutterView;
    if (view == platformDispatcher.implicitView) {
      return TestViewConfiguration.fromView(
        size: _surfaceSize ?? _kDefaultTestViewportSize,
        view: view,
      );
    }
    final double devicePixelRatio = view.devicePixelRatio;
    return TestViewConfiguration.fromView(size: view.physicalSize / devicePixelRatio, view: view);
  }

  @override
  Offset globalToLocal(Offset point, RenderView view) {
    // The method is expected to translate the given point expressed in logical
    // pixels in the global coordinate space to the local coordinate space (also
    // expressed in logical pixels).
    // The inverted transform translates from the global coordinate space in
    // physical pixels to the local coordinate space in logical pixels.
    final Matrix4 transform = view.configuration.toMatrix();
    final double det = transform.invert();
    assert(det != 0.0);
    // In order to use the transform, we need to translate the point first into
    // the physical coordinate space by applying the device pixel ratio.
    return MatrixUtils.transformPoint(transform, point * view.configuration.devicePixelRatio);
  }

  @override
  Offset localToGlobal(Offset point, RenderView view) {
    // The method is expected to translate the given point expressed in logical
    // pixels in the local coordinate space to the global coordinate space (also
    // expressed in logical pixels).
    // The transform translates from the local coordinate space in logical
    // pixels to the global coordinate space in physical pixels.
    final Matrix4 transform = view.configuration.toMatrix();
    final Offset pointInPhysicalPixels = MatrixUtils.transformPoint(transform, point);
    // We need to apply the device pixel ratio to get back to logical pixels.
    return pointInPhysicalPixels / view.configuration.devicePixelRatio;
  }
}

/// A [ViewConfiguration] that pretends the display is of a particular size (in
/// logical pixels).
///
/// The resulting ViewConfiguration maps the given size onto the actual display
/// using the [BoxFit.contain] algorithm.
///
/// If the underlying [FlutterView] changes, a new [TestViewConfiguration] should
/// be created. See [RendererBinding.handleMetricsChanged] and
/// [RendererBinding.createViewConfigurationFor].
class TestViewConfiguration implements ViewConfiguration {
  /// Deprecated. Will be removed in a future version of Flutter.
  ///
  /// This property has been deprecated to prepare for Flutter's upcoming
  /// support for multiple views and multiple windows.
  ///
  /// Use [TestViewConfiguration.fromView] instead.
  @Deprecated(
    'Use TestViewConfiguration.fromView instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.7.0-32.0.pre.',
  )
  factory TestViewConfiguration({Size size = _kDefaultTestViewportSize, ui.FlutterView? window}) {
    return TestViewConfiguration.fromView(size: size, view: window ?? ui.window);
  }

  /// Creates a [TestViewConfiguration] with the given size and view.
  ///
  /// The [size] defaults to 800x600.
  ///
  /// The settings of the given [FlutterView] are captured when the constructor
  /// is called, and subsequent changes are ignored. A new
  /// [TestViewConfiguration] should be created if the underlying [FlutterView]
  /// changes. See [RendererBinding.handleMetricsChanged] and
  /// [RendererBinding.createViewConfigurationFor].
  TestViewConfiguration.fromView({
    required ui.FlutterView view,
    Size size = _kDefaultTestViewportSize,
  }) : devicePixelRatio = view.devicePixelRatio,
       logicalConstraints = BoxConstraints.tight(size),
       physicalConstraints = BoxConstraints.tight(size) * view.devicePixelRatio,
       _paintMatrix = _getMatrix(size, view.devicePixelRatio, view),
       _physicalSize = view.physicalSize;

  @override
  final double devicePixelRatio;

  @override
  final BoxConstraints logicalConstraints;

  @override
  final BoxConstraints physicalConstraints;

  static Matrix4 _getMatrix(Size size, double devicePixelRatio, ui.FlutterView window) {
    final double inverseRatio = devicePixelRatio / window.devicePixelRatio;
    final double actualWidth = window.physicalSize.width * inverseRatio;
    final double actualHeight = window.physicalSize.height * inverseRatio;
    final double desiredWidth = size.width;
    final double desiredHeight = size.height;
    double scale, shiftX, shiftY;
    if (desiredWidth == 0.0 || desiredHeight == 0.0) {
      scale = 1.0;
      shiftX = 0.0;
      shiftY = 0.0;
    } else if ((actualWidth / actualHeight) > (desiredWidth / desiredHeight)) {
      scale = actualHeight / desiredHeight;
      shiftX = (actualWidth - desiredWidth * scale) / 2.0;
      shiftY = 0.0;
    } else {
      scale = actualWidth / desiredWidth;
      shiftX = 0.0;
      shiftY = (actualHeight - desiredHeight * scale) / 2.0;
    }
    final matrix = Matrix4.compose(
      Vector3(shiftX, shiftY, 0.0), // translation
      Quaternion.identity(), // rotation
      Vector3(scale, scale, 1.0), // scale
    );
    return matrix;
  }

  final Matrix4 _paintMatrix;

  @override
  Matrix4 toMatrix() => _paintMatrix.clone();

  @override
  bool shouldUpdateMatrix(ViewConfiguration oldConfiguration) {
    if (oldConfiguration.runtimeType != runtimeType) {
      // New configuration could have different logic, so we don't know
      // whether it will need a new transform. Return a conservative result.
      return true;
    }
    oldConfiguration as TestViewConfiguration;
    // Compare the matrices directly since they are cached.
    return oldConfiguration._paintMatrix != _paintMatrix;
  }

  final Size _physicalSize;

  @override
  Size toPhysicalSize(Size logicalSize) => _physicalSize;

  @override
  String toString() => 'TestViewConfiguration';
}

class _TestSamplingClock implements SamplingClock {
  _TestSamplingClock(this._clock);

  @override
  DateTime now() => _clock.now();

  @override
  Stopwatch stopwatch() => _clock.stopwatch();

  final Clock _clock;
}

const int _kPointerDecay = -2;

class _LiveTestPointerRecord {
  _LiveTestPointerRecord(this.pointer, this.position)
    : color = HSVColor.fromAHSV(0.8, (35.0 * pointer) % 360.0, 1.0, 1.0).toColor(),
      decay = 1;
  final int pointer;
  final Color color;
  Offset position;
  int decay; // >0 means down, <0 means up, increases by one each time, removed at 0
}
