// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

typedef ElementRebuildCallback = void Function(StatefulElement element);

class TestState extends State<StatefulWidget> {
  @override
  Widget build(BuildContext context) => const SizedBox();
}

@optionalTypeArgs
class _MyGlobalObjectKey<T extends State<StatefulWidget>> extends GlobalObjectKey<T> {
  const _MyGlobalObjectKey(Object value) : super(value);
}

void main() {
  testWidgets('UniqueKey control test', (WidgetTester tester) async {
    final Key key = UniqueKey();
    expect(key, hasOneLineDescription);
    expect(key, isNot(equals(UniqueKey())));
  });

  testWidgets('ObjectKey control test', (WidgetTester tester) async {
    final Object a = Object();
    final Object b = Object();
    final Key keyA = ObjectKey(a);
    final Key keyA2 = ObjectKey(a);
    final Key keyB = ObjectKey(b);

    expect(keyA, hasOneLineDescription);
    expect(keyA, equals(keyA2));
    expect(keyA.hashCode, equals(keyA2.hashCode));
    expect(keyA, isNot(equals(keyB)));
  });

  testWidgets('GlobalObjectKey toString test', (WidgetTester tester) async {
    const GlobalObjectKey one = GlobalObjectKey(1);
    const GlobalObjectKey<TestState> two = GlobalObjectKey<TestState>(2);
    const GlobalObjectKey three = _MyGlobalObjectKey(3);
    const GlobalObjectKey<TestState> four = _MyGlobalObjectKey<TestState>(4);

    expect(one.toString(), equals('[GlobalObjectKey ${describeIdentity(1)}]'));
    expect(two.toString(), equals('[GlobalObjectKey<TestState> ${describeIdentity(2)}]'));
    expect(three.toString(), equals('[_MyGlobalObjectKey ${describeIdentity(3)}]'));
    expect(four.toString(), equals('[_MyGlobalObjectKey<TestState> ${describeIdentity(4)}]'));
  });

  testWidgets('GlobalObjectKey control test', (WidgetTester tester) async {
    final Object a = Object();
    final Object b = Object();
    final Key keyA = GlobalObjectKey(a);
    final Key keyA2 = GlobalObjectKey(a);
    final Key keyB = GlobalObjectKey(b);

    expect(keyA, hasOneLineDescription);
    expect(keyA, equals(keyA2));
    expect(keyA.hashCode, equals(keyA2.hashCode));
    expect(keyA, isNot(equals(keyB)));
  });

  testWidgets('GlobalKey correct case 1 - can move global key from container widget to layoutbuilder', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'correct');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          key: const ValueKey<int>(1),
          child: SizedBox(key: key),
        ),
        LayoutBuilder(
          key: const ValueKey<int>(2),
          builder: (BuildContext context, BoxConstraints constraints) {
            return const Placeholder();
          },
        ),
      ],
    ));

    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          key: const ValueKey<int>(1),
          child: const Placeholder(),
        ),
        LayoutBuilder(
          key: const ValueKey<int>(2),
          builder: (BuildContext context, BoxConstraints constraints) {
            return SizedBox(key: key);
          },
        ),
      ],
    ));
  });

  testWidgets('GlobalKey correct case 2 - can move global key from layoutbuilder to container widget', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'correct');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          key: const ValueKey<int>(1),
          child: const Placeholder(),
        ),
        LayoutBuilder(
          key: const ValueKey<int>(2),
          builder: (BuildContext context, BoxConstraints constraints) {
            return SizedBox(key: key);
          },
        ),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          key: const ValueKey<int>(1),
          child: SizedBox(key: key),
        ),
        LayoutBuilder(
          key: const ValueKey<int>(2),
          builder: (BuildContext context, BoxConstraints constraints) {
            return const Placeholder();
          },
        ),
      ],
    ));
  });

  testWidgets('GlobalKey correct case 3 - can deal with early rebuild in layoutbuilder - move backward', (WidgetTester tester) async {
    const Key key1 = GlobalObjectKey('Text1');
    const Key key2 = GlobalObjectKey('Text2');
    Key? rebuiltKeyOfSecondChildBeforeLayout;
    Key? rebuiltKeyOfFirstChildAfterLayout;
    Key? rebuiltKeyOfSecondChildAfterLayout;
    await tester.pumpWidget(
      LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Column(
            children: <Widget>[
              const _Stateful(
                child: Text(
                  'Text1',
                  textDirection: TextDirection.ltr,
                  key: key1,
                ),
              ),
              _Stateful(
                child: const Text(
                  'Text2',
                  textDirection: TextDirection.ltr,
                  key: key2,
                ),
                onElementRebuild: (StatefulElement element) {
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfSecondChildBeforeLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfSecondChildBeforeLayout =
                    statefulWidget.child.key;
                },
              ),
            ],
          );
        },
      )
    );
    // Result will be written during first build and need to clear it to remove
    // noise.
    rebuiltKeyOfSecondChildBeforeLayout = null;

    final _StatefulState state = tester.firstState(find.byType(_Stateful).at(1));
    state.rebuild();
    // Reorders the items
    await tester.pumpWidget(
      LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Column(
            children: <Widget>[
              _Stateful(
                child: const Text(
                  'Text2',
                  textDirection: TextDirection.ltr,
                  key: key2,
                ),
                onElementRebuild: (StatefulElement element) {
                  // Verifies the early rebuild happens before layout.
                  expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfFirstChildAfterLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfFirstChildAfterLayout = statefulWidget.child.key;
                },
              ),
              _Stateful(
                child: const Text(
                  'Text1',
                  textDirection: TextDirection.ltr,
                  key: key1,
                ),
                onElementRebuild: (StatefulElement element) {
                  // Verifies the early rebuild happens before layout.
                  expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfSecondChildAfterLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfSecondChildAfterLayout = statefulWidget.child.key;
                },
              ),
            ],
          );
        },
      )
    );
    expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
    expect(rebuiltKeyOfFirstChildAfterLayout, key2);
    expect(rebuiltKeyOfSecondChildAfterLayout, key1);
  });

  testWidgets('GlobalKey correct case 4 - can deal with early rebuild in layoutbuilder - move forward', (WidgetTester tester) async {
    const Key key1 = GlobalObjectKey('Text1');
    const Key key2 = GlobalObjectKey('Text2');
    const Key key3 = GlobalObjectKey('Text3');
    Key? rebuiltKeyOfSecondChildBeforeLayout;
    Key? rebuiltKeyOfSecondChildAfterLayout;
    Key? rebuiltKeyOfThirdChildAfterLayout;
    await tester.pumpWidget(
      LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Column(
            children: <Widget>[
              const _Stateful(
                child: Text(
                  'Text1',
                  textDirection: TextDirection.ltr,
                  key: key1,
                ),
              ),
              _Stateful(
                child: const Text(
                  'Text2',
                  textDirection: TextDirection.ltr,
                  key: key2,
                ),
                onElementRebuild: (StatefulElement element) {
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfSecondChildBeforeLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfSecondChildBeforeLayout = statefulWidget.child.key;
                },
              ),
              const _Stateful(
                child: Text(
                  'Text3',
                  textDirection: TextDirection.ltr,
                  key: key3,
                ),
              ),
            ],
          );
        },
      )
    );
    // Result will be written during first build and need to clear it to remove
    // noise.
    rebuiltKeyOfSecondChildBeforeLayout = null;

    final _StatefulState state = tester.firstState(find.byType(_Stateful).at(1));
    state.rebuild();
    // Reorders the items
    await tester.pumpWidget(
      LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Column(
            children: <Widget>[
              const _Stateful(
                child: Text(
                  'Text1',
                  textDirection: TextDirection.ltr,
                  key: key1,
                ),
              ),
              _Stateful(
                child: const Text(
                  'Text3',
                  textDirection: TextDirection.ltr,
                  key: key3,
                ),
                onElementRebuild: (StatefulElement element) {
                  // Verifies the early rebuild happens before layout.
                  expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfSecondChildAfterLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfSecondChildAfterLayout = statefulWidget.child.key;
                },
              ),
              _Stateful(
                child: const Text(
                  'Text2',
                  textDirection: TextDirection.ltr,
                  key: key2,
                ),
                onElementRebuild: (StatefulElement element) {
                  // Verifies the early rebuild happens before layout.
                  expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfThirdChildAfterLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfThirdChildAfterLayout = statefulWidget.child.key;
                },
              ),
            ],
          );
        },
      )
    );
    expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
    expect(rebuiltKeyOfSecondChildAfterLayout, key3);
    expect(rebuiltKeyOfThirdChildAfterLayout, key2);
  });

  testWidgets('GlobalKey correct case 5 - can deal with early rebuild in layoutbuilder - only one global key', (WidgetTester tester) async {
    const Key key1 = GlobalObjectKey('Text1');
    Key? rebuiltKeyOfSecondChildBeforeLayout;
    Key? rebuiltKeyOfThirdChildAfterLayout;
    await tester.pumpWidget(
      LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Column(
            children: <Widget>[
              const _Stateful(
                child: Text(
                  'Text1',
                  textDirection: TextDirection.ltr,
                ),
              ),
              _Stateful(
                child: const Text(
                  'Text2',
                  textDirection: TextDirection.ltr,
                  key: key1,
                ),
                onElementRebuild: (StatefulElement element) {
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfSecondChildBeforeLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfSecondChildBeforeLayout = statefulWidget.child.key;
                },
              ),
              const _Stateful(
                child: Text(
                  'Text3',
                  textDirection: TextDirection.ltr,
                ),
              ),
            ],
          );
        },
      )
    );
    // Result will be written during first build and need to clear it to remove
    // noise.
    rebuiltKeyOfSecondChildBeforeLayout = null;

    final _StatefulState state = tester.firstState(find.byType(_Stateful).at(1));
    state.rebuild();
    // Reorders the items
    await tester.pumpWidget(
      LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Column(
            children: <Widget>[
              const _Stateful(
                child: Text(
                  'Text1',
                  textDirection: TextDirection.ltr,
                ),
              ),
              _Stateful(
                child: const Text(
                  'Text3',
                  textDirection: TextDirection.ltr,
                ),
                onElementRebuild: (StatefulElement element) {
                  // Verifies the early rebuild happens before layout.
                  expect(rebuiltKeyOfSecondChildBeforeLayout, key1);
                },
              ),
              _Stateful(
                child: const Text(
                  'Text2',
                  textDirection: TextDirection.ltr,
                  key: key1,
                ),
                onElementRebuild: (StatefulElement element) {
                  // Verifies the early rebuild happens before layout.
                  expect(rebuiltKeyOfSecondChildBeforeLayout, key1);
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfThirdChildAfterLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfThirdChildAfterLayout = statefulWidget.child.key;
                },
              ),
            ],
          );
        },
      )
    );
    expect(rebuiltKeyOfSecondChildBeforeLayout, key1);
    expect(rebuiltKeyOfThirdChildAfterLayout, key1);
  });

  testWidgets('GlobalKey duplication 1 - double appearance', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          key: const ValueKey<int>(1),
          child: SizedBox(key: key),
        ),
        Container(
          key: const ValueKey<int>(2),
          child: Placeholder(key: key),
        ),
      ],
    ));
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Multiple widgets used the same GlobalKey.\n'
        'The key [GlobalKey#00000 problematic] was used by multiple widgets. The parents of those widgets were:\n'
        '- Container-[<1>]\n'
        '- Container-[<2>]\n'
        'A GlobalKey can only be specified on one widget at a time in the widget tree.'
      ),
    );
  });

  testWidgets('GlobalKey duplication 2 - splitting and changing type', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');

    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          key: const ValueKey<int>(1),
        ),
        Container(
          key: const ValueKey<int>(2),
        ),
        Container(
          key: key
        ),
      ],
    ));

    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(
          key: const ValueKey<int>(1),
          child: SizedBox(key: key),
        ),
        Container(
          key: const ValueKey<int>(2),
          child: Placeholder(key: key),
        ),
      ],
    ));

    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Multiple widgets used the same GlobalKey.\n'
        'The key [GlobalKey#00000 problematic] was used by multiple widgets. The parents of those widgets were:\n'
        '- Container-[<1>]\n'
        '- Container-[<2>]\n'
        'A GlobalKey can only be specified on one widget at a time in the widget tree.'
      ),
    );
  });

  testWidgets('GlobalKey duplication 3 - splitting and changing type', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        SizedBox(key: key),
        Placeholder(key: key),
      ],
    ));
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Multiple widgets used the same GlobalKey.\n'
        'The key [GlobalKey#00000 problematic] was used by 2 widgets:\n'
        '  SizedBox-[GlobalKey#00000 problematic]\n'
        '  Placeholder-[GlobalKey#00000 problematic]\n'
        'A GlobalKey can only be specified on one widget at a time in the widget tree.'
      ),
    );
  });

  testWidgets('GlobalKey duplication 4 - splitting and half changing type', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
        Placeholder(key: key),
      ],
    ));
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Multiple widgets used the same GlobalKey.\n'
        'The key [GlobalKey#00000 problematic] was used by 2 widgets:\n'
        '  Container-[GlobalKey#00000 problematic]\n'
        '  Placeholder-[GlobalKey#00000 problematic]\n'
        'A GlobalKey can only be specified on one widget at a time in the widget tree.'
      ),
    );
  });

  testWidgets('GlobalKey duplication 5 - splitting and half changing type', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Placeholder(key: key),
        Container(key: key),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 6 - splitting and not changing type', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
        Container(key: key),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 7 - appearing later', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
        Container(key: const ValueKey<int>(2)),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
        Container(key: const ValueKey<int>(2), child: Container(key: key)),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 8 - appearing earlier', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(1)),
        Container(key: const ValueKey<int>(2), child: Container(key: key)),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
        Container(key: const ValueKey<int>(2), child: Container(key: key)),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 9 - moving and appearing later', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(0), child: Container(key: key)),
        Container(key: const ValueKey<int>(1)),
        Container(key: const ValueKey<int>(2)),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
        Container(key: const ValueKey<int>(2), child: Container(key: key)),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 10 - moving and appearing earlier', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(1)),
        Container(key: const ValueKey<int>(2)),
        Container(key: const ValueKey<int>(3), child: Container(key: key)),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
        Container(key: const ValueKey<int>(2), child: Container(key: key)),
        Container(key: const ValueKey<int>(3)),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 11 - double sibling appearance', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
        Container(key: key),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 12 - all kinds of badness at once', (WidgetTester tester) async {
    final Key key1 = GlobalKey(debugLabel: 'problematic');
    final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label
    final Key key3 = GlobalKey(debugLabel: 'also problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key1),
        Container(key: key1),
        Container(key: key2),
        Container(key: key1),
        Container(key: key1),
        Container(key: key2),
        Container(key: key1),
        Container(key: key1),
        Row(
          children: <Widget>[
            Container(key: key1),
            Container(key: key1),
            Container(key: key2),
            Container(key: key2),
            Container(key: key2),
            Container(key: key3),
            Container(key: key2),
          ],
        ),
        Row(
          children: <Widget>[
            Container(key: key1),
            Container(key: key1),
            Container(key: key3),
          ],
        ),
        Container(key: key3),
      ],
    ));
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Duplicate keys found.\n'
        'If multiple keyed nodes exist as children of another node, they must have unique keys.\n'
        'Stack(alignment: AlignmentDirectional.topStart, textDirection: ltr, fit: loose) has multiple children with key [GlobalKey#00000 problematic].'
      ),
    );
  });

  testWidgets('GlobalKey duplication 13 - all kinds of badness at once', (WidgetTester tester) async {
    final Key key1 = GlobalKey(debugLabel: 'problematic');
    final Key key2 = GlobalKey(debugLabel: 'problematic'); // intentionally the same label
    final Key key3 = GlobalKey(debugLabel: 'also problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key1),
        Container(key: key2),
        Container(key: key3),
      ]),
    );
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key1),
        Container(key: key1),
        Container(key: key2),
        Container(key: key1),
        Container(key: key1),
        Container(key: key2),
        Container(key: key1),
        Container(key: key1),
        Row(
          children: <Widget>[
            Container(key: key1),
            Container(key: key1),
            Container(key: key2),
            Container(key: key2),
            Container(key: key2),
            Container(key: key3),
            Container(key: key2),
          ],
        ),
        Row(
          children: <Widget>[
            Container(key: key1),
            Container(key: key1),
            Container(key: key3),
          ],
        ),
        Container(key: key3),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 14 - moving during build - before', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1)),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
      ],
    ));
  });

  testWidgets('GlobalKey duplication 15 - duplicating during build - before', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1)),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: key),
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
      ],
    ));
    expect(tester.takeException(), isFlutterError);
  });

  testWidgets('GlobalKey duplication 16 - moving during build - after', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1)),
        Container(key: key),
      ],
    ));
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
      ],
    ));
  });

  testWidgets('GlobalKey duplication 17 - duplicating during build - after', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1)),
        Container(key: key),
      ],
    ));
    int count = 0;
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = (FlutterErrorDetails details) {
      expect(details.exception, isFlutterError);
      count += 1;
    };
    await tester.pumpWidget(Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        Container(key: const ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1), child: Container(key: key)),
        Container(key: key),
      ],
    ));
    FlutterError.onError = oldHandler;
    expect(count, 1);
  });

  testWidgets('GlobalKey duplication 18 - subtree build duplicate key with same type', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    final Stack stack = Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        const SwapKeyWidget(childKey: ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1)),
        Container(key: key),
      ],
    );
    await tester.pumpWidget(stack);
    final SwapKeyWidgetState state = tester.state(find.byType(SwapKeyWidget));
    state.swapKey(key);
    await tester.pump();
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Duplicate GlobalKey detected in widget tree.\n'
        'The following GlobalKey was specified multiple times in the widget tree. This will lead '
        'to parts of the widget tree being truncated unexpectedly, because the second time a key is seen, the '
        'previous instance is moved to the new location. The key was:\n'
        '- [GlobalKey#00000 problematic]\n'
        'This was determined by noticing that after the widget with the above global key was '
        'moved out of its previous parent, that previous parent never updated during this frame, meaning that '
        'it either did not update at all or updated before the widget was moved, in either case implying that '
        'it still thinks that it should have a child with that global key.\n'
        'The specific parent that did not update after having one or more children forcibly '
        'removed due to GlobalKey reparenting is:\n'
        '- Stack(alignment: AlignmentDirectional.topStart, textDirection: ltr, fit: loose, '
        'renderObject: RenderStack#00000)\n'
        'A GlobalKey can only be specified on one widget at a time in the widget tree.'
      ),
    );
  });

  testWidgets('GlobalKey duplication 19 - subtree build duplicate key with different types', (WidgetTester tester) async {
    final Key key = GlobalKey(debugLabel: 'problematic');
    final Stack stack = Stack(
      textDirection: TextDirection.ltr,
      children: <Widget>[
        const SwapKeyWidget(childKey: ValueKey<int>(0)),
        Container(key: const ValueKey<int>(1)),
        Container(child: SizedBox(key: key)),
      ],
    );
    await tester.pumpWidget(stack);
    final SwapKeyWidgetState state = tester.state(find.byType(SwapKeyWidget));
    state.swapKey(key);
    await tester.pump();
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Multiple widgets used the same GlobalKey.\n'
        'The key [GlobalKey#95367 problematic] was used by 2 widgets:\n'
        '  SizedBox-[GlobalKey#00000 problematic]\n'
        '  Container-[GlobalKey#00000 problematic]\n'
        'A GlobalKey can only be specified on one widget at a time in the widget tree.'
      ),
    );
  });

  testWidgets('GlobalKey duplication 20 - real duplication with early rebuild in layoutbuilder will throw', (WidgetTester tester) async {
    const Key key1 = GlobalObjectKey('Text1');
    const Key key2 = GlobalObjectKey('Text2');
    Key? rebuiltKeyOfSecondChildBeforeLayout;
    Key? rebuiltKeyOfFirstChildAfterLayout;
    Key? rebuiltKeyOfSecondChildAfterLayout;
    await tester.pumpWidget(
      LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Column(
            children: <Widget>[
              const _Stateful(
                child: Text(
                  'Text1',
                  textDirection: TextDirection.ltr,
                  key: key1,
                ),
              ),
              _Stateful(
                child: const Text(
                  'Text2',
                  textDirection: TextDirection.ltr,
                  key: key2,
                ),
                onElementRebuild: (StatefulElement element) {
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfSecondChildBeforeLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfSecondChildBeforeLayout = statefulWidget.child.key;
                },
              ),
            ],
          );
        },
      )
    );
    // Result will be written during first build and need to clear it to remove
    // noise.
    rebuiltKeyOfSecondChildBeforeLayout = null;

    final _StatefulState state = tester.firstState(find.byType(_Stateful).at(1));
    state.rebuild();

    await tester.pumpWidget(
      LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          return Column(
            children: <Widget>[
              _Stateful(
                child: const Text(
                  'Text2',
                  textDirection: TextDirection.ltr,
                  key: key2,
                ),
                onElementRebuild: (StatefulElement element) {
                  // Verifies the early rebuild happens before layout.
                  expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfFirstChildAfterLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfFirstChildAfterLayout = statefulWidget.child.key;
                },
              ),
              _Stateful(
                child: const Text(
                  'Text1',
                  textDirection: TextDirection.ltr,
                  key: key2,
                ),
                onElementRebuild: (StatefulElement element) {
                  // Verifies the early rebuild happens before layout.
                  expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
                  // We don't want noise to override the result;
                  expect(rebuiltKeyOfSecondChildAfterLayout, isNull);
                  final _Stateful statefulWidget = element.widget as _Stateful;
                  rebuiltKeyOfSecondChildAfterLayout = statefulWidget.child.key;
                },
              ),
            ],
          );
        },
      )
    );
    expect(rebuiltKeyOfSecondChildBeforeLayout, key2);
    expect(rebuiltKeyOfFirstChildAfterLayout, key2);
    expect(rebuiltKeyOfSecondChildAfterLayout, key2);
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Multiple widgets used the same GlobalKey.\n'
        'The key [GlobalObjectKey String#00000] was used by multiple widgets. The '
        'parents of those widgets were:\n'
        '- _Stateful(state: _StatefulState#00000)\n'
        '- _Stateful(state: _StatefulState#00000)\n'
        'A GlobalKey can only be specified on one widget at a time in the widget tree.'
      ),
    );
  });

  testWidgets('GlobalKey - detach and re-attach child to different parents', (WidgetTester tester) async {
    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: Center(
        child: Container(
          height: 100,
          child: CustomScrollView(
            controller: ScrollController(),
            slivers: <Widget>[
              SliverList(
                delegate: SliverChildListDelegate(<Widget>[
                  Text('child', key: GlobalKey()),
                ]),
              ),
            ],
          ),
        ),
      ),
    ));
    final SliverMultiBoxAdaptorElement element = tester.element(find.byType(SliverList));
    late Element childElement;
    // Removing and recreating child with same Global Key should not trigger
    // duplicate key error.
    element.visitChildren((Element e) {
      childElement = e;
    });
    element.removeChild(childElement.renderObject! as RenderBox);
    element.createChild(0, after: null);
    element.visitChildren((Element e) {
      childElement = e;
    });
    element.removeChild(childElement.renderObject! as RenderBox);
    element.createChild(0, after: null);
  });

  testWidgets('GlobalKey - re-attach child to new parents, and the old parent is deactivated(unmounted)', (WidgetTester tester) async {
    // This is a regression test for https://github.com/flutter/flutter/issues/62055
    const Key key1 = GlobalObjectKey('key1');
    const Key key2 = GlobalObjectKey('key2');
    late StateSetter setState;
    int tabBarViewCnt = 2;
    TabController tabController = TabController(length: tabBarViewCnt, vsync: const TestVSync(),);

    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: StatefulBuilder(
        builder: (BuildContext context, StateSetter setter) {
          setState = setter;
          return TabBarView(
            controller: tabController,
            children: <Widget>[
              if (tabBarViewCnt > 0) const Text('key1', key: key1,),
              if (tabBarViewCnt > 1) const Text('key2', key: key2,),
            ],
          );
        },
      ),
    ));

    expect(tabController.index, 0);

    // switch tabs 0 -> 1
    setState((){
      tabController.index = 1;
    });

    await tester.pump(const Duration(seconds: 1)); // finish the animation

    expect(tabController.index, 1);

    // rebuild TabBarView that only have the 1st page with GlobalKey 'key1'
    setState((){
      tabBarViewCnt = 1;
      tabController = TabController(length: tabBarViewCnt, vsync: const TestVSync(),);
    });

    await tester.pump(const Duration(seconds: 1)); // finish the animation

    expect(tabController.index, 0);
  });

  testWidgets('Defunct setState throws exception', (WidgetTester tester) async {
    late StateSetter setState;

    await tester.pumpWidget(StatefulBuilder(
      builder: (BuildContext context, StateSetter setter) {
        setState = setter;
        return Container();
      },
    ));

    // Control check that setState doesn't throw an exception.
    setState(() { });

    await tester.pumpWidget(Container());

    expect(() { setState(() { }); }, throwsFlutterError);
  });

  testWidgets('State toString', (WidgetTester tester) async {
    final TestState state = TestState();
    expect(state.toString(), contains('no widget'));
  });

  testWidgets('debugPrintGlobalKeyedWidgetLifecycle control test', (WidgetTester tester) async {
    expect(debugPrintGlobalKeyedWidgetLifecycle, isFalse);

    final DebugPrintCallback oldCallback = debugPrint;
    debugPrintGlobalKeyedWidgetLifecycle = true;

    final List<String> log = <String>[];
    debugPrint = (String? message, { int? wrapWidth }) {
      log.add(message!);
    };

    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(Container(key: key));
    expect(log, isEmpty);
    await tester.pumpWidget(const Placeholder());
    debugPrint = oldCallback;
    debugPrintGlobalKeyedWidgetLifecycle = false;

    expect(log.length, equals(2));
    expect(log[0], matches('Deactivated'));
    expect(log[1], matches('Discarding .+ from inactive elements list.'));
  });

  testWidgets('MultiChildRenderObjectElement.children', (WidgetTester tester) async {
    GlobalKey key0, key1, key2;
    await tester.pumpWidget(Column(
      key: key0 = GlobalKey(),
      children: <Widget>[
        Container(),
        Container(key: key1 = GlobalKey()),
        Container(child: Container()),
        Container(key: key2 = GlobalKey()),
        Container(),
      ],
    ));
    final MultiChildRenderObjectElement element = key0.currentContext! as MultiChildRenderObjectElement;
    expect(
      element.children.map((Element element) => element.widget.key),
      <Key?>[null, key1, null, key2, null],
    );
  });

  testWidgets('Element diagnostics', (WidgetTester tester) async {
    GlobalKey key0;
    await tester.pumpWidget(Column(
      key: key0 = GlobalKey(),
      children: <Widget>[
        Container(),
        Container(key: GlobalKey()),
        Container(child: Container()),
        Container(key: GlobalKey()),
        Container(),
      ],
    ));
    final MultiChildRenderObjectElement element = key0.currentContext! as MultiChildRenderObjectElement;

    expect(element, hasAGoodToStringDeep);
    expect(
      element.toStringDeep(),
      equalsIgnoringHashCodes(
        'Column-[GlobalKey#00000](direction: vertical, mainAxisAlignment: start, crossAxisAlignment: center, renderObject: RenderFlex#00000)\n'
        '├Container\n'
        '│└LimitedBox(maxWidth: 0.0, maxHeight: 0.0, renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)\n'
        '│ └ConstrainedBox(BoxConstraints(biggest), renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)\n'
        '├Container-[GlobalKey#00000]\n'
        '│└LimitedBox(maxWidth: 0.0, maxHeight: 0.0, renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)\n'
        '│ └ConstrainedBox(BoxConstraints(biggest), renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)\n'
        '├Container\n'
        '│└Container\n'
        '│ └LimitedBox(maxWidth: 0.0, maxHeight: 0.0, renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)\n'
        '│  └ConstrainedBox(BoxConstraints(biggest), renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)\n'
        '├Container-[GlobalKey#00000]\n'
        '│└LimitedBox(maxWidth: 0.0, maxHeight: 0.0, renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)\n'
        '│ └ConstrainedBox(BoxConstraints(biggest), renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)\n'
        '└Container\n'
        ' └LimitedBox(maxWidth: 0.0, maxHeight: 0.0, renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)\n'
        '  └ConstrainedBox(BoxConstraints(biggest), renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)\n',
      ),
    );
  });

  testWidgets('scheduleBuild while debugBuildingDirtyElements is true', (WidgetTester tester) async {
    /// ignore here is required for testing purpose because changing the flag properly is hard
    // ignore: invalid_use_of_protected_member
    tester.binding.debugBuildingDirtyElements = true;
    late FlutterError error;
    try {
      tester.binding.buildOwner!.scheduleBuildFor(
        DirtyElementWithCustomBuildOwner(tester.binding.buildOwner!, Container()));
    } on FlutterError catch (e) {
      error = e;
    } finally {
      expect(error.diagnostics.length, 3);
      expect(error.diagnostics.last.level, DiagnosticLevel.hint);
      expect(
        error.diagnostics.last.toStringDeep(),
        equalsIgnoringHashCodes(
          'This might be because setState() was called from a layout or\n'
          'paint callback. If a change is needed to the widget tree, it\n'
          'should be applied as the tree is being built. Scheduling a change\n'
          'for the subsequent frame instead results in an interface that\n'
          'lags behind by one frame. If this was done to make your build\n'
          'dependent on a size measured at layout time, consider using a\n'
          'LayoutBuilder, CustomSingleChildLayout, or\n'
          'CustomMultiChildLayout. If, on the other hand, the one frame\n'
          'delay is the desired effect, for example because this is an\n'
          'animation, consider scheduling the frame in a post-frame callback\n'
          'using SchedulerBinding.addPostFrameCallback or using an\n'
          'AnimationController to trigger the animation.\n',
        ),
      );
      expect(
        error.toStringDeep(),
        'FlutterError\n'
        '   Build scheduled during frame.\n'
        '   While the widget tree was being built, laid out, and painted, a\n'
        '   new frame was scheduled to rebuild the widget tree.\n'
        '   This might be because setState() was called from a layout or\n'
        '   paint callback. If a change is needed to the widget tree, it\n'
        '   should be applied as the tree is being built. Scheduling a change\n'
        '   for the subsequent frame instead results in an interface that\n'
        '   lags behind by one frame. If this was done to make your build\n'
        '   dependent on a size measured at layout time, consider using a\n'
        '   LayoutBuilder, CustomSingleChildLayout, or\n'
        '   CustomMultiChildLayout. If, on the other hand, the one frame\n'
        '   delay is the desired effect, for example because this is an\n'
        '   animation, consider scheduling the frame in a post-frame callback\n'
        '   using SchedulerBinding.addPostFrameCallback or using an\n'
        '   AnimationController to trigger the animation.\n',
      );
    }
  });

  testWidgets('didUpdateDependencies is not called on a State that never rebuilds', (WidgetTester tester) async {
    final GlobalKey<DependentState> key = GlobalKey<DependentState>();

    /// Initial build - should call didChangeDependencies, not deactivate
    await tester.pumpWidget(Inherited(1, child: DependentStatefulWidget(key: key)));
    final DependentState state = key.currentState!;
    expect(key.currentState, isNotNull);
    expect(state.didChangeDependenciesCount, 1);
    expect(state.deactivatedCount, 0);

    /// Rebuild with updated value - should call didChangeDependencies
    await tester.pumpWidget(Inherited(2, child: DependentStatefulWidget(key: key)));
    expect(key.currentState, isNotNull);
    expect(state.didChangeDependenciesCount, 2);
    expect(state.deactivatedCount, 0);

    // reparent it - should call deactivate and didChangeDependencies
    await tester.pumpWidget(Inherited(3, child: SizedBox(child: DependentStatefulWidget(key: key))));
    expect(key.currentState, isNotNull);
    expect(state.didChangeDependenciesCount, 3);
    expect(state.deactivatedCount, 1);

    // Remove it - should call deactivate, but not didChangeDependencies
    await tester.pumpWidget(const Inherited(4, child: SizedBox()));
    expect(key.currentState, isNull);
    expect(state.didChangeDependenciesCount, 3);
    expect(state.deactivatedCount, 2);
  });

  testWidgets('StatefulElement subclass can decorate State.build', (WidgetTester tester) async {
    late bool isDidChangeDependenciesDecorated;
    late bool isBuildDecorated;

    final Widget child = Decorate(
      didChangeDependencies: (bool value) {
        isDidChangeDependenciesDecorated = value;
      },
      build: (bool value) {
        isBuildDecorated = value;
      }
    );

    await tester.pumpWidget(Inherited(0, child: child));

    expect(isBuildDecorated, isTrue);
    expect(isDidChangeDependenciesDecorated, isFalse);

    await tester.pumpWidget(Inherited(1, child: child));

    expect(isBuildDecorated, isTrue);
    expect(isDidChangeDependenciesDecorated, isFalse);
  });
  group('BuildContext.debugDoingbuild', () {
    testWidgets('StatelessWidget', (WidgetTester tester) async {
      late bool debugDoingBuildOnBuild;
      await tester.pumpWidget(
        StatelessWidgetSpy(
          onBuild: (BuildContext context) {
            debugDoingBuildOnBuild = context.debugDoingBuild;
          },
        ),
      );

      final Element context = tester.element(find.byType(StatelessWidgetSpy));

      expect(context.debugDoingBuild, isFalse);
      expect(debugDoingBuildOnBuild, isTrue);
    });
    testWidgets('StatefulWidget', (WidgetTester tester) async {
      late bool debugDoingBuildOnBuild;
      late bool debugDoingBuildOnInitState;
      late bool debugDoingBuildOnDidChangeDependencies;
      late bool debugDoingBuildOnDidUpdateWidget;
      bool? debugDoingBuildOnDispose;
      bool? debugDoingBuildOnDeactivate;

      await tester.pumpWidget(
        Inherited(
          0,
          child: StatefulWidgetSpy(
            onInitState: (BuildContext context) {
              debugDoingBuildOnInitState = context.debugDoingBuild;
            },
            onDidChangeDependencies: (BuildContext context) {
              context.dependOnInheritedWidgetOfExactType<Inherited>();
              debugDoingBuildOnDidChangeDependencies = context.debugDoingBuild;
            },
            onBuild: (BuildContext context) {
              debugDoingBuildOnBuild = context.debugDoingBuild;
            },
          ),
        ),
      );

      final Element context = tester.element(find.byType(StatefulWidgetSpy));

      expect(context.debugDoingBuild, isFalse);
      expect(debugDoingBuildOnBuild, isTrue);
      expect(debugDoingBuildOnInitState, isFalse);
      expect(debugDoingBuildOnDidChangeDependencies, isFalse);

      await tester.pumpWidget(
        Inherited(
          1,
          child: StatefulWidgetSpy(
            onDidUpdateWidget: (BuildContext context) {
              debugDoingBuildOnDidUpdateWidget = context.debugDoingBuild;
            },
            onDidChangeDependencies: (BuildContext context) {
              debugDoingBuildOnDidChangeDependencies = context.debugDoingBuild;
            },
            onBuild: (BuildContext context) {
              debugDoingBuildOnBuild = context.debugDoingBuild;
            },
            onDispose: (BuildContext context) {
              debugDoingBuildOnDispose = context.debugDoingBuild;
            },
            onDeactivate: (BuildContext context) {
              debugDoingBuildOnDeactivate = context.debugDoingBuild;
            },
          ),
        ),
      );

      expect(context.debugDoingBuild, isFalse);
      expect(debugDoingBuildOnBuild, isTrue);
      expect(debugDoingBuildOnDidUpdateWidget, isFalse);
      expect(debugDoingBuildOnDidChangeDependencies, isFalse);
      expect(debugDoingBuildOnDeactivate, isNull);
      expect(debugDoingBuildOnDispose, isNull);

      await tester.pumpWidget(Container());

      expect(context.debugDoingBuild, isFalse);
      expect(debugDoingBuildOnDispose, isFalse);
      expect(debugDoingBuildOnDeactivate, isFalse);
    });
    testWidgets('RenderObjectWidget', (WidgetTester tester) async {
      late bool debugDoingBuildOnCreateRenderObject;
      bool? debugDoingBuildOnUpdateRenderObject;
      bool? debugDoingBuildOnDidUnmountRenderObject;
      final ValueNotifier<int> notifier = ValueNotifier<int>(0);

      late BuildContext spyContext;

      Widget build() {
        return ValueListenableBuilder<int>(
          valueListenable: notifier,
          builder: (BuildContext context, int? value, Widget? child) {
            return Inherited(value, child: child!);
          },
          child: RenderObjectWidgetSpy(
            onCreateRenderObject: (BuildContext context) {
              spyContext = context;
              context.dependOnInheritedWidgetOfExactType<Inherited>();
              debugDoingBuildOnCreateRenderObject = context.debugDoingBuild;
            },
            onUpdateRenderObject: (BuildContext context) {
              debugDoingBuildOnUpdateRenderObject = context.debugDoingBuild;
            },
            onDidUnmountRenderObject: () {
              debugDoingBuildOnDidUnmountRenderObject = spyContext.debugDoingBuild;
            },
          ),
        );
      }

      await tester.pumpWidget(build());

      spyContext = tester.element(find.byType(RenderObjectWidgetSpy));

      expect(spyContext.debugDoingBuild, isFalse);
      expect(debugDoingBuildOnCreateRenderObject, isTrue);
      expect(debugDoingBuildOnUpdateRenderObject, isNull);
      expect(debugDoingBuildOnDidUnmountRenderObject, isNull);

      await tester.pumpWidget(build());

      expect(spyContext.debugDoingBuild, isFalse);
      expect(debugDoingBuildOnUpdateRenderObject, isTrue);
      expect(debugDoingBuildOnDidUnmountRenderObject, isNull);

      notifier.value++;
      debugDoingBuildOnUpdateRenderObject = false;
      await tester.pump();

      expect(spyContext.debugDoingBuild, isFalse);
      expect(debugDoingBuildOnUpdateRenderObject, isTrue);
      expect(debugDoingBuildOnDidUnmountRenderObject, isNull);

      await tester.pumpWidget(Container());

      expect(spyContext.debugDoingBuild, isFalse);
      expect(debugDoingBuildOnDidUnmountRenderObject, isFalse);
    });
  });

  testWidgets('A widget whose element has an invalid visitChildren implementation triggers a useful error message', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(Container(child: _WidgetWithNoVisitChildren(_StatefulLeaf(key: key))));
    (key.currentState! as _StatefulLeafState).markNeedsBuild();
    await tester.pumpWidget(Container());
    final dynamic exception = tester.takeException();
    expect(
      exception.message,
      equalsIgnoringHashCodes(
        'Tried to build dirty widget in the wrong build scope.\n'
        'A widget which was marked as dirty and is still active was scheduled to be built, '
        'but the current build scope unexpectedly does not contain that widget.\n'
        'Sometimes this is detected when an element is removed from the widget tree, but '
        'the element somehow did not get marked as inactive. In that case, it might be '
        'caused by an ancestor element failing to implement visitChildren correctly, thus '
        'preventing some or all of its descendants from being correctly deactivated.\n'
        'The root of the build scope was:\n'
        '  [root]\n'
        'The offending element (which does not appear to be a descendant of the root of '
        'the build scope) was:\n'
        '  _StatefulLeaf-[GlobalKey#00000]'
      )
    );
  });

  testWidgets('Can create BuildOwner that does not interfere with pointer router or raw key event handler', (WidgetTester tester) async {
    final int pointerRouterCount = GestureBinding.instance!.pointerRouter.debugGlobalRouteCount;
    final RawKeyEventHandler? rawKeyEventHandler = RawKeyboard.instance.keyEventHandler;
    expect(rawKeyEventHandler, isNotNull);
    BuildOwner(focusManager: _FakeFocusManager());
    expect(GestureBinding.instance!.pointerRouter.debugGlobalRouteCount, pointerRouterCount);
    expect(RawKeyboard.instance.keyEventHandler, same(rawKeyEventHandler));
  });

  testWidgets('Can access debugFillProperties without _LateInitializationError', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    TestRenderObjectElement().debugFillProperties(builder);
    expect(builder.properties.any((DiagnosticsNode property) => property.name == 'renderObject' && property.value == null), isTrue);
  });
}

class _FakeFocusManager implements FocusManager {
  @override
  dynamic noSuchMethod(Invocation invocation) {
    return super.noSuchMethod(invocation);
  }

  @override
  String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
    return '_FakeFocusManager';
  }
}

class _WidgetWithNoVisitChildren extends StatelessWidget {
  const _WidgetWithNoVisitChildren(this.child, { Key? key }) :
    super(key: key);

  final Widget child;

  @override
  Widget build(BuildContext context) => child;

  @override
  _WidgetWithNoVisitChildrenElement createElement() => _WidgetWithNoVisitChildrenElement(this);
}

class _WidgetWithNoVisitChildrenElement extends StatelessElement {
  _WidgetWithNoVisitChildrenElement(_WidgetWithNoVisitChildren widget): super(widget);

  @override
  void visitChildren(ElementVisitor visitor) {
    // This implementation is intentionally buggy, to test that an error message is
    // shown when this situation occurs.
    // The superclass has the correct implementation (calling `visitor(_child)`), so
    // we don't call it here.
  }
}

class _StatefulLeaf extends StatefulWidget {
  const _StatefulLeaf({ Key? key }) : super(key: key);

  @override
  State<_StatefulLeaf> createState() => _StatefulLeafState();
}

class _StatefulLeafState extends State<_StatefulLeaf> {
  void markNeedsBuild() {
    setState(() { });
  }

  @override
  Widget build(BuildContext context) {
    return const SizedBox.shrink();
  }
}

class Decorate extends StatefulWidget {
  const Decorate({
    Key? key,
    required this.didChangeDependencies,
    required this.build
  }) :
    assert(didChangeDependencies != null),
    assert(build != null),
    super(key: key);

  final void Function(bool isInBuild) didChangeDependencies;
  final void Function(bool isInBuild) build;

  @override
  _DecorateState createState() => _DecorateState();

  @override
  DecorateElement createElement() => DecorateElement(this);
}

class DecorateElement extends StatefulElement {
  DecorateElement(Decorate widget): super(widget);

  bool isDecorated = false;

  @override
  Widget build() {
    try {
      isDecorated = true;
      return super.build();
    } finally {
      isDecorated = false;
    }
  }
}

class _DecorateState extends State<Decorate> {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    widget.didChangeDependencies.call((context as DecorateElement).isDecorated);
  }
  @override
  Widget build(covariant DecorateElement context) {
    context.dependOnInheritedWidgetOfExactType<Inherited>();
    widget.build.call(context.isDecorated);
    return Container();
  }
}

class DirtyElementWithCustomBuildOwner extends Element {
  DirtyElementWithCustomBuildOwner(BuildOwner buildOwner, Widget widget)
    : _owner = buildOwner, super(widget);

  final BuildOwner _owner;

  @override
  void performRebuild() {}

  @override
  BuildOwner get owner => _owner;

  @override
  bool get dirty => true;

  @override
  bool get debugDoingBuild => throw UnimplementedError();
}

class Inherited extends InheritedWidget {
  const Inherited(this.value, {Key? key, required Widget child}) : super(key: key, child: child);

  final int? value;

  @override
  bool updateShouldNotify(Inherited oldWidget) => oldWidget.value != value;
}

class DependentStatefulWidget extends StatefulWidget {
  const DependentStatefulWidget({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => DependentState();
}

class DependentState extends State<DependentStatefulWidget> {
  int didChangeDependenciesCount = 0;
  int deactivatedCount = 0;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    didChangeDependenciesCount += 1;
  }

  @override
  Widget build(BuildContext context) {
    context.dependOnInheritedWidgetOfExactType<Inherited>();
    return const SizedBox();
  }

  @override
  void deactivate() {
    super.deactivate();
    deactivatedCount += 1;
  }
}

class SwapKeyWidget extends StatefulWidget {
  const SwapKeyWidget({this.childKey}): super();

  final Key? childKey;
  @override
  SwapKeyWidgetState createState() => SwapKeyWidgetState();
}

class SwapKeyWidgetState extends State<SwapKeyWidget> {
  Key? key;

  @override
  void initState() {
    super.initState();
    key = widget.childKey;
  }

  void swapKey(Key newKey) {
    setState(() {
      key = newKey;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(key: key);
  }
}

class _Stateful extends StatefulWidget {
  const _Stateful({Key? key, required this.child, this.onElementRebuild}) : super(key: key);
  final Text child;
  final ElementRebuildCallback? onElementRebuild;
  @override
  State<StatefulWidget> createState() => _StatefulState();

  @override
  StatefulElement createElement() => StatefulElementSpy(this);
}

class _StatefulState extends State<_Stateful> {
  void rebuild() => setState(() {});

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}

class StatefulElementSpy extends StatefulElement {
  StatefulElementSpy(StatefulWidget widget) : super(widget);

  _Stateful get _statefulWidget => widget as _Stateful;

  @override
  void rebuild() {
    _statefulWidget.onElementRebuild?.call(this);
    super.rebuild();
  }
}

class StatelessWidgetSpy extends StatelessWidget {
  const StatelessWidgetSpy({
    Key? key,
    required this.onBuild,
  })  : assert(onBuild != null),
        super(key: key);

  final void Function(BuildContext) onBuild;

  @override
  Widget build(BuildContext context) {
    onBuild(context);
    return Container();
  }
}

class StatefulWidgetSpy extends StatefulWidget {
  const StatefulWidgetSpy({
    Key? key,
    this.onBuild,
    this.onInitState,
    this.onDidChangeDependencies,
    this.onDispose,
    this.onDeactivate,
    this.onDidUpdateWidget,
  })  : super(key: key);

  final void Function(BuildContext)? onBuild;
  final void Function(BuildContext)? onInitState;
  final void Function(BuildContext)? onDidChangeDependencies;
  final void Function(BuildContext)? onDispose;
  final void Function(BuildContext)? onDeactivate;
  final void Function(BuildContext)? onDidUpdateWidget;

  @override
  _StatefulWidgetSpyState createState() => _StatefulWidgetSpyState();
}

class _StatefulWidgetSpyState extends State<StatefulWidgetSpy> {
  @override
  void initState() {
    super.initState();
    widget.onInitState?.call(context);
  }

  @override
  void deactivate() {
    super.deactivate();
    widget.onDeactivate?.call(context);
  }

  @override
  void dispose() {
    super.dispose();
    widget.onDispose?.call(context);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    widget.onDidChangeDependencies?.call(context);
  }

  @override
  void didUpdateWidget(StatefulWidgetSpy oldWidget) {
    super.didUpdateWidget(oldWidget);
    widget.onDidUpdateWidget?.call(context);
  }

  @override
  Widget build(BuildContext context) {
    widget.onBuild?.call(context);
    return Container();
  }
}

class RenderObjectWidgetSpy extends LeafRenderObjectWidget {
  const RenderObjectWidgetSpy({
    Key? key,
    this.onCreateRenderObject,
    this.onUpdateRenderObject,
    this.onDidUnmountRenderObject,
  })  : super(key: key);

  final void Function(BuildContext)? onCreateRenderObject;
  final void Function(BuildContext)? onUpdateRenderObject;
  final void Function()? onDidUnmountRenderObject;

  @override
  RenderObject createRenderObject(BuildContext context) {
    onCreateRenderObject?.call(context);
    return FakeLeafRenderObject();
  }

  @override
  void updateRenderObject(BuildContext context, RenderObject renderObject) {
    onUpdateRenderObject?.call(context);
  }

  @override
  void didUnmountRenderObject(RenderObject renderObject) {
    super.didUnmountRenderObject(renderObject);
    onDidUnmountRenderObject?.call();
  }
}

class FakeLeafRenderObject extends RenderBox {
  @override
  Size computeDryLayout(BoxConstraints constraints) {
    return constraints.biggest;
  }

  @override
  void performLayout() {
    size = constraints.biggest;
  }
}

class TestRenderObjectElement extends RenderObjectElement {
  TestRenderObjectElement() : super(Table());
}
