From eec1ac25062e01b1e2f852d4ad876532fd2838a7 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 13:59:31 -0700 Subject: [PATCH 01/21] Refactor the test benchmark app to make the example easier to follow --- packages/web_benchmarks/CHANGELOG.md | 4 + packages/web_benchmarks/README.md | 4 +- packages/web_benchmarks/lib/server.dart | 9 +- packages/web_benchmarks/lib/src/runner.dart | 9 +- packages/web_benchmarks/pubspec.yaml | 2 +- .../testing/test_app/.gitignore | 9 +- .../web_benchmarks/testing/test_app/.metadata | 24 ++- .../benchmark/test_infra/automator.dart | 146 ++++++++++++++++++ .../test_infra/client/app_client.dart | 21 +++ .../client/simple_compilation_client.dart | 18 +++ .../test_app/benchmark/test_infra/common.dart | 10 ++ .../benchmark/test_infra/recorder.dart | 38 +++++ .../benchmark}/web_benchmarks_test.dart | 51 +++--- .../testing/test_app/lib/about_page.dart | 6 +- .../test_app/lib/benchmarks/runner.dart | 101 ------------ .../lib/benchmarks/runner_simple.dart | 28 ---- .../testing/test_app/lib/home_page.dart | 5 +- .../testing/test_app/lib/icon_page.dart | 45 ------ .../testing/test_app/lib/main.dart | 28 +++- .../testing/test_app/pubspec.yaml | 8 + .../test_app/web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes .../test_app/web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes .../testing/test_app/web/index.html | 22 ++- .../testing/test_app/web/manifest.json | 12 ++ 24 files changed, 369 insertions(+), 231 deletions(-) create mode 100644 packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart create mode 100644 packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/app_client.dart create mode 100644 packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_compilation_client.dart create mode 100644 packages/web_benchmarks/testing/test_app/benchmark/test_infra/common.dart create mode 100644 packages/web_benchmarks/testing/test_app/benchmark/test_infra/recorder.dart rename packages/web_benchmarks/testing/{ => test_app/benchmark}/web_benchmarks_test.dart (67%) delete mode 100644 packages/web_benchmarks/testing/test_app/lib/benchmarks/runner.dart delete mode 100644 packages/web_benchmarks/testing/test_app/lib/benchmarks/runner_simple.dart delete mode 100644 packages/web_benchmarks/testing/test_app/lib/icon_page.dart create mode 100644 packages/web_benchmarks/testing/test_app/web/icons/Icon-maskable-192.png create mode 100644 packages/web_benchmarks/testing/test_app/web/icons/Icon-maskable-512.png diff --git a/packages/web_benchmarks/CHANGELOG.md b/packages/web_benchmarks/CHANGELOG.md index 434f9bee76d..a8b4eb16091 100644 --- a/packages/web_benchmarks/CHANGELOG.md +++ b/packages/web_benchmarks/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.0-wip + +* Restructure the `testing/test_app` to make the example benchmarks easier to follow. + ## 2.0.2 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. diff --git a/packages/web_benchmarks/README.md b/packages/web_benchmarks/README.md index ce98a22b194..9b63bf815d4 100644 --- a/packages/web_benchmarks/README.md +++ b/packages/web_benchmarks/README.md @@ -5,14 +5,14 @@ benchmarks in Chrome. # Writing a benchmark -An example benchmark can be found in [testing/web_benchmark_test.dart][1]. +An example benchmark can be found in [testing/test_app/benchmark/web_benchmark_test.dart][1]. A web benchmark is made of two parts: a client and a server. The client is code that runs in the browser together with the benchmark code. The server serves the app's code and assets. Additionally, the server communicates with the browser to extract the performance traces. -[1]: https://github.com/flutter/packages/blob/master/packages/web_benchmarks/testing/web_benchmarks_test.dart +[1]: https://github.com/flutter/packages/blob/master/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart # Analyzing benchmark results diff --git a/packages/web_benchmarks/lib/server.dart b/packages/web_benchmarks/lib/server.dart index 514b111d95f..80e5f7a4f50 100644 --- a/packages/web_benchmarks/lib/server.dart +++ b/packages/web_benchmarks/lib/server.dart @@ -32,8 +32,6 @@ const int defaultChromeDebugPort = 10000; /// can be different (and typically is) from the production entry point of the /// app. /// -/// If [useCanvasKit] is true, builds the app in CanvasKit mode. -/// /// [benchmarkServerPort] is the port this benchmark server serves the app on. /// By default uses [defaultBenchmarkServerPort]. /// @@ -42,6 +40,13 @@ const int defaultChromeDebugPort = 10000; /// /// If [headless] is true, runs Chrome without UI. In particular, this is /// useful in environments (e.g. CI) that doesn't have a display. +/// +/// If [treeShakeIcons] is false, '--no-tree-shake-icons' will be passed as a +/// build argument when building the benchmark app. +/// +/// [compilationOptions] specify the compiler and renderer to use for the +/// benchmark app. This can either use dart2wasm & skwasm or +/// dart2js & canvaskit. Future serveWebBenchmark({ required io.Directory benchmarkAppDirectory, required String entryPoint, diff --git a/packages/web_benchmarks/lib/src/runner.dart b/packages/web_benchmarks/lib/src/runner.dart index 3ad6f86c96e..0c929104622 100644 --- a/packages/web_benchmarks/lib/src/runner.dart +++ b/packages/web_benchmarks/lib/src/runner.dart @@ -39,8 +39,6 @@ class BenchmarkServer { /// can be different (and typically is) from the production entry point of the /// app. /// - /// If [useCanvasKit] is true, builds the app in CanvasKit mode. - /// /// [benchmarkServerPort] is the port this benchmark server serves the app on. /// /// [chromeDebugPort] is the port Chrome uses for DevTool Protocol used to @@ -48,6 +46,13 @@ class BenchmarkServer { /// /// If [headless] is true, runs Chrome without UI. In particular, this is /// useful in environments (e.g. CI) that doesn't have a display. + /// + /// If [treeShakeIcons] is false, '--no-tree-shake-icons' will be passed as a + /// build argument when building the benchmark app. + /// + /// [compilationOptions] specify the compiler and renderer to use for the + /// benchmark app. This can either use dart2wasm & skwasm or + /// dart2js & canvaskit. BenchmarkServer({ required this.benchmarkAppDirectory, required this.entryPoint, diff --git a/packages/web_benchmarks/pubspec.yaml b/packages/web_benchmarks/pubspec.yaml index 6386767133d..0bc109d17d3 100644 --- a/packages/web_benchmarks/pubspec.yaml +++ b/packages/web_benchmarks/pubspec.yaml @@ -2,7 +2,7 @@ name: web_benchmarks description: A benchmark harness for performance-testing Flutter apps in Chrome. repository: https://github.com/flutter/packages/tree/main/packages/web_benchmarks issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+web_benchmarks%22 -version: 2.0.2 +version: 3.0.0-wip environment: sdk: ^3.3.0 diff --git a/packages/web_benchmarks/testing/test_app/.gitignore b/packages/web_benchmarks/testing/test_app/.gitignore index 9f6b8e534c2..79c113f9b50 100644 --- a/packages/web_benchmarks/testing/test_app/.gitignore +++ b/packages/web_benchmarks/testing/test_app/.gitignore @@ -5,9 +5,12 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ +migrate_working_dir/ # IntelliJ related *.iml @@ -26,7 +29,6 @@ .dart_tool/ .flutter-plugins .flutter-plugins-dependencies -.packages .pub-cache/ .pub/ /build/ @@ -36,3 +38,8 @@ app.*.symbols # Obfuscation related app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/web_benchmarks/testing/test_app/.metadata b/packages/web_benchmarks/testing/test_app/.metadata index 5e875f26787..7dd91c1357b 100644 --- a/packages/web_benchmarks/testing/test_app/.metadata +++ b/packages/web_benchmarks/testing/test_app/.metadata @@ -4,7 +4,27 @@ # This file should be version controlled and should not be manually edited. version: - revision: d26268bb9e6d713a73d6148da7fa75936d442741 - channel: master + revision: "0cd170798c6462aec738d4c749ce3a5fff1c80cf" + channel: "master" project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 0cd170798c6462aec738d4c749ce3a5fff1c80cf + base_revision: 0cd170798c6462aec738d4c749ce3a5fff1c80cf + - platform: web + create_revision: 0cd170798c6462aec738d4c749ce3a5fff1c80cf + base_revision: 0cd170798c6462aec738d4c749ce3a5fff1c80cf + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart new file mode 100644 index 00000000000..1e5592424bf --- /dev/null +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart @@ -0,0 +1,146 @@ +// Copyright 2013 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: avoid_print + +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:test_app/home_page.dart' show aboutPageKey, textKey; +import 'package:test_app/main.dart'; +import 'package:web/web.dart'; +import 'package:web_benchmarks/client.dart'; + +import 'common.dart'; + +/// A class that automates the test web app. +class Automater { + Automater({ + required this.benchmark, + required this.stopWarmingUpCallback, + required this.profile, + }); + + /// The current benchmark. + final BenchmarkName benchmark; + + /// A function to call when warm-up is finished. + /// + /// This function is intended to ask `Recorder` to mark the warm-up phase + /// as over. + final void Function() stopWarmingUpCallback; + + /// The profile collected for the running benchmark + final Profile profile; + + /// Whether the automation has ended. + bool finished = false; + + /// A widget controller for automation. + late LiveWidgetController controller; + + Widget createWidget() { + Future.delayed(const Duration(milliseconds: 400), automate); + return const MyApp(); + } + + Future automate() async { + await warmUp(); + + switch (benchmark) { + case BenchmarkName.appNavigate: + await _handleAppNavigate(); + case BenchmarkName.appScroll: + await _handleAppScroll(); + case BenchmarkName.appTap: + await _handleAppTap(); + case BenchmarkName.simpleCompilationCheck: + _handleSimpleCompilationCheck(); + case BenchmarkName.simpleBenchmarkPathCheck: + _handleSimpleBenchmarkPathCheck(); + } + + // At the end of the test, mark as finished. + finished = true; + } + + /// Warm up the animation. + Future warmUp() async { + // Let animation stop. + await animationStops(); + + // Set controller. + controller = LiveWidgetController(WidgetsBinding.instance); + + await controller.pumpAndSettle(); + + // When warm-up finishes, inform the recorder. + stopWarmingUpCallback(); + } + + Future _handleAppNavigate() async { + for (int i = 0; i < 10; ++i) { + print('Testing round $i...'); + await controller.tap(find.byKey(aboutPageKey)); + await animationStops(); + await controller.tap(find.byType(BackButton)); + await animationStops(); + } + } + + Future _handleAppScroll() async { + final ScrollableState scrollable = + Scrollable.of(find.byKey(textKey).evaluate().single); + await scrollable.position.animateTo( + 30000, + curve: Curves.linear, + duration: const Duration(seconds: 20), + ); + } + + Future _handleAppTap() async { + for (int i = 0; i < 10; ++i) { + print('Testing round $i...'); + await controller.tap(find.byIcon(Icons.add)); + await animationStops(); + } + } + + void _handleSimpleCompilationCheck() { + // Record whether we are in wasm mode or not. Ideally, we'd have a more + // first-class way to add metadata like this, but this will work for us to + // pass information about the environment back to the server for the + // purposes of our own tests. + profile.extraData['isWasm'] = kIsWasm ? 1 : 0; + } + + void _handleSimpleBenchmarkPathCheck() { + // Record whether the URL contains the expected path so we can verify the + // behavior of setting the `benchmarkPath` on the benchmark server. + final bool containsExpectedPath = + window.location.toString().contains(testBenchmarkPath); + profile.extraData['expectedUrl'] = containsExpectedPath ? 1 : 0; + } +} + +const Duration _animationCheckingInterval = Duration(milliseconds: 50); + +Future animationStops() async { + if (!WidgetsBinding.instance.hasScheduledFrame) { + return; + } + + final Completer stopped = Completer(); + + Timer.periodic(_animationCheckingInterval, (Timer timer) { + if (!WidgetsBinding.instance.hasScheduledFrame) { + stopped.complete(); + timer.cancel(); + } + }); + + await stopped.future; +} diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/app_client.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/app_client.dart new file mode 100644 index 00000000000..2887ba9b7c2 --- /dev/null +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/app_client.dart @@ -0,0 +1,21 @@ +// Copyright 2013 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:web_benchmarks/client.dart'; + +import '../common.dart'; +import '../recorder.dart'; + +Future main() async { + await runBenchmarks( + { + BenchmarkName.appNavigate.name: () => + TestAppRecorder(benchmark: BenchmarkName.appNavigate), + BenchmarkName.appScroll.name: () => + TestAppRecorder(benchmark: BenchmarkName.appScroll), + BenchmarkName.appTap.name: () => + TestAppRecorder(benchmark: BenchmarkName.appTap), + }, + ); +} diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_compilation_client.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_compilation_client.dart new file mode 100644 index 00000000000..301ca2111e7 --- /dev/null +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_compilation_client.dart @@ -0,0 +1,18 @@ +// Copyright 2013 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:web_benchmarks/client.dart'; + +import '../common.dart'; +import '../recorder.dart'; + +Future main() async { + await runBenchmarks( + { + BenchmarkName.simpleCompilationCheck.name: () => TestAppRecorder( + benchmark: BenchmarkName.simpleCompilationCheck, + ), + }, + ); +} diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/common.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/common.dart new file mode 100644 index 00000000000..06667d8738d --- /dev/null +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/common.dart @@ -0,0 +1,10 @@ +// Copyright 2013 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. + +enum BenchmarkName { + appNavigate, + appScroll, + appTap, + simpleCompilationCheck; +} diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/recorder.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/recorder.dart new file mode 100644 index 00000000000..ba0dc55ba30 --- /dev/null +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/recorder.dart @@ -0,0 +1,38 @@ +// Copyright 2013 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/material.dart'; +import 'package:web_benchmarks/client.dart'; + +import 'automator.dart'; +import 'common.dart'; + +/// A recorder that measures frame building durations for the test app. +class TestAppRecorder extends WidgetRecorder { + TestAppRecorder({required this.benchmark}) + : super(name: benchmark.name, useCustomWarmUp: true); + + /// The name of the benchmark to be run. + /// + /// See `common.dart` for the list of the names of all benchmarks. + final BenchmarkName benchmark; + + Automater? _automator; + bool get _finished => _automator?.finished ?? false; + + /// Whether we should continue recording. + @override + bool shouldContinue() => !_finished || profile.shouldContinue(); + + /// Creates the [Automater] widget. + @override + Widget createWidget() { + _automator = Automater( + benchmark: benchmark, + stopWarmingUpCallback: profile.stopWarmingUp, + profile: profile, + ); + return _automator!.createWidget(); + } +} diff --git a/packages/web_benchmarks/testing/web_benchmarks_test.dart b/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart similarity index 67% rename from packages/web_benchmarks/testing/web_benchmarks_test.dart rename to packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart index 3cdefc671d7..7a83c5ddbe5 100644 --- a/packages/web_benchmarks/testing/web_benchmarks_test.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart @@ -10,43 +10,38 @@ import 'package:test/test.dart'; import 'package:web_benchmarks/server.dart'; import 'package:web_benchmarks/src/common.dart'; -Future main() async { - test('Can run a web benchmark', () async { - await _runBenchmarks( - benchmarkNames: ['scroll', 'page', 'tap'], - entryPoint: 'lib/benchmarks/runner.dart', - ); - }, timeout: Timeout.none); - - test('Can run a web benchmark with an alternate initial page', () async { - final BenchmarkResults results = await _runBenchmarks( - benchmarkNames: ['simple'], - entryPoint: 'lib/benchmarks/runner_simple.dart', - initialPage: 'index.html#about', - ); - - // The simple runner just puts an `isWasm` metric in there so we can make - // sure that we're running in the right environment. - final List? scores = results.scores['simple']; - expect(scores, isNotNull); +import 'test_infra/common.dart'; - final BenchmarkScore isWasmScore = - scores!.firstWhere((BenchmarkScore score) => score.metric == 'isWasm'); - expect(isWasmScore.value, 0); - }, timeout: Timeout.none); +Future main() async { + test( + 'Can run a web benchmark', + () async { + await _runBenchmarks( + benchmarkNames: [ + BenchmarkName.appNavigate.name, + BenchmarkName.appScroll.name, + BenchmarkName.appTap.name, + ], + entryPoint: 'benchmark/test_infra/client/app_client.dart', + ); + }, + timeout: Timeout.none, + ); test( 'Can run a web benchmark with wasm', () async { final BenchmarkResults results = await _runBenchmarks( - benchmarkNames: ['simple'], - entryPoint: 'lib/benchmarks/runner_simple.dart', + benchmarkNames: [BenchmarkName.simpleCompilationCheck.name], + entryPoint: + 'benchmark/test_infra/client/simple_compilation_client.dart', compilationOptions: const CompilationOptions.wasm(), ); // The simple runner just puts an `isWasm` metric in there so we can make // sure that we're running in the right environment. - final List? scores = results.scores['simple']; + final List? scores = + results.scores[BenchmarkName.simpleCompilationCheck.name]; expect(scores, isNotNull); final BenchmarkScore isWasmScore = scores! @@ -60,14 +55,14 @@ Future main() async { Future _runBenchmarks({ required List benchmarkNames, required String entryPoint, - String initialPage = defaultInitialPage, + String benchmarkPath = defaultInitialPath, CompilationOptions compilationOptions = const CompilationOptions.js(), }) async { final BenchmarkResults taskResult = await serveWebBenchmark( benchmarkAppDirectory: Directory('testing/test_app'), entryPoint: entryPoint, treeShakeIcons: false, - initialPage: initialPage, + benchmarkPath: benchmarkPath, compilationOptions: compilationOptions, ); diff --git a/packages/web_benchmarks/testing/test_app/lib/about_page.dart b/packages/web_benchmarks/testing/test_app/lib/about_page.dart index 4147c33f8f1..23f85320eaf 100644 --- a/packages/web_benchmarks/testing/test_app/lib/about_page.dart +++ b/packages/web_benchmarks/testing/test_app/lib/about_page.dart @@ -3,8 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; - -const ValueKey backKey = ValueKey('backKey'); +import 'package:go_router/go_router.dart'; class AboutPage extends StatelessWidget { const AboutPage({super.key}); @@ -14,8 +13,7 @@ class AboutPage extends StatelessWidget { return Scaffold( appBar: AppBar( leading: BackButton( - key: backKey, - onPressed: () => Navigator.of(context).pop(), + onPressed: () => context.canPop() ? context.pop() : context.go('/'), ), ), body: Center( diff --git a/packages/web_benchmarks/testing/test_app/lib/benchmarks/runner.dart b/packages/web_benchmarks/testing/test_app/lib/benchmarks/runner.dart deleted file mode 100644 index 9a870dfca2e..00000000000 --- a/packages/web_benchmarks/testing/test_app/lib/benchmarks/runner.dart +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2013 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: avoid_print - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:web_benchmarks/client.dart'; - -import '../about_page.dart' show backKey; -import '../home_page.dart' show aboutPageKey, textKey; -import '../main.dart'; - -/// A recorder that measures frame building durations. -abstract class AppRecorder extends WidgetRecorder { - AppRecorder({required this.benchmarkName}) : super(name: benchmarkName); - - final String benchmarkName; // ignore: unreachable_from_main - - Future automate(); - - @override - Widget createWidget() { - Future.delayed(const Duration(milliseconds: 400), automate); - return const MyApp(); - } - - Future animationStops() async { - while (WidgetsBinding.instance.hasScheduledFrame) { - await Future.delayed(const Duration(milliseconds: 200)); - } - } -} - -class ScrollRecorder extends AppRecorder { - ScrollRecorder() : super(benchmarkName: 'scroll'); - - @override - Future automate() async { - final ScrollableState scrollable = - Scrollable.of(find.byKey(textKey).evaluate().single); - await scrollable.position.animateTo( - 30000, - curve: Curves.linear, - duration: const Duration(seconds: 20), - ); - } -} - -class PageRecorder extends AppRecorder { - PageRecorder() : super(benchmarkName: 'page'); - - bool _completed = false; - - @override - bool shouldContinue() => profile.shouldContinue() || !_completed; - - @override - Future automate() async { - final LiveWidgetController controller = - LiveWidgetController(WidgetsBinding.instance); - for (int i = 0; i < 10; ++i) { - print('Testing round $i...'); - await controller.tap(find.byKey(aboutPageKey)); - await animationStops(); - await controller.tap(find.byKey(backKey)); - await animationStops(); - } - _completed = true; - } -} - -class TapRecorder extends AppRecorder { - TapRecorder() : super(benchmarkName: 'tap'); - - bool _completed = false; - - @override - bool shouldContinue() => profile.shouldContinue() || !_completed; - - @override - Future automate() async { - final LiveWidgetController controller = - LiveWidgetController(WidgetsBinding.instance); - for (int i = 0; i < 10; ++i) { - print('Testing round $i...'); - await controller.tap(find.byIcon(Icons.add)); - await animationStops(); - } - _completed = true; - } -} - -Future main() async { - await runBenchmarks({ - 'scroll': () => ScrollRecorder(), - 'page': () => PageRecorder(), - 'tap': () => TapRecorder(), - }); -} diff --git a/packages/web_benchmarks/testing/test_app/lib/benchmarks/runner_simple.dart b/packages/web_benchmarks/testing/test_app/lib/benchmarks/runner_simple.dart deleted file mode 100644 index c233ebe6187..00000000000 --- a/packages/web_benchmarks/testing/test_app/lib/benchmarks/runner_simple.dart +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 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/foundation.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:web_benchmarks/client.dart'; - -import 'runner.dart'; - -class SimpleRecorder extends AppRecorder { - SimpleRecorder() : super(benchmarkName: 'simple'); - - @override - Future automate() async { - // Record whether we are in wasm mode or not. Ideally, we'd have a more - // first-class way to add metadata like this, but this will work for us to - // pass information about the environment back to the server for the - // purposes of our own tests. - profile.extraData['isWasm'] = kIsWasm ? 1 : 0; - } -} - -Future main() async { - await runBenchmarks({ - 'simple': () => SimpleRecorder(), - }); -} diff --git a/packages/web_benchmarks/testing/test_app/lib/home_page.dart b/packages/web_benchmarks/testing/test_app/lib/home_page.dart index dee8c9d0eeb..c0f7a131aec 100644 --- a/packages/web_benchmarks/testing/test_app/lib/home_page.dart +++ b/packages/web_benchmarks/testing/test_app/lib/home_page.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; const ValueKey textKey = ValueKey('textKey'); const ValueKey aboutPageKey = ValueKey('aboutPageKey'); @@ -33,8 +34,8 @@ class _HomePageState extends State { actions: [ IconButton( key: aboutPageKey, - icon: const Icon(Icons.alternate_email), - onPressed: () => Navigator.of(context).pushNamed('about'), + icon: const Icon(Icons.help_outline), + onPressed: () => context.go('/about'), ), ], ), diff --git a/packages/web_benchmarks/testing/test_app/lib/icon_page.dart b/packages/web_benchmarks/testing/test_app/lib/icon_page.dart deleted file mode 100644 index fd0da430ee0..00000000000 --- a/packages/web_benchmarks/testing/test_app/lib/icon_page.dart +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 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/material.dart'; - -class IconGeneratorPage extends StatefulWidget { - const IconGeneratorPage({super.key}); - - static int defaultIconCodePoint = int.parse('0xf03f'); - - @override - State createState() => _IconGeneratorPageState(); -} - -class _IconGeneratorPageState extends State { - int iconCodePoint = IconGeneratorPage.defaultIconCodePoint; - - @override - Widget build(BuildContext context) { - return Column( - children: [ - TextField( - onSubmitted: (String value) { - final int codePointAsInt = - int.tryParse(value) ?? IconGeneratorPage.defaultIconCodePoint; - setState(() { - iconCodePoint = codePointAsInt; - }); - }, - ), - const SizedBox(height: 24.0), - Icon(generateIcon(iconCodePoint)), - ], - ); - } - - // Unless '--no-tree-shake-icons' is passed to the flutter build command, - // the presence of this method will trigger an exception due to the use of - // non-constant invocations of [IconData]. - IconData generateIcon(int materialIconCodePoint) => IconData( - materialIconCodePoint, - fontFamily: 'MaterialIcons', - ); -} diff --git a/packages/web_benchmarks/testing/test_app/lib/main.dart b/packages/web_benchmarks/testing/test_app/lib/main.dart index e07fc56ec2a..172abba3288 100644 --- a/packages/web_benchmarks/testing/test_app/lib/main.dart +++ b/packages/web_benchmarks/testing/test_app/lib/main.dart @@ -3,32 +3,44 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; +import 'package:flutter_web_plugins/url_strategy.dart'; +import 'package:go_router/go_router.dart'; import 'about_page.dart'; import 'home_page.dart'; -import 'icon_page.dart'; void main() { + usePathUrlStrategy(); runApp(const MyApp()); } +final GoRouter _router = GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (_, __) => const HomePage(title: 'Flutter Demo Home Page'), + ), + GoRoute( + path: '/about', + builder: (_, __) => const AboutPage(), + ), + ], +); + class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { - return MaterialApp( + return MaterialApp.router( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), - initialRoute: 'home', - routes: { - 'home': (_) => const HomePage(title: 'Flutter Demo Home Page'), - 'about': (_) => const AboutPage(), - 'icon_generator': (_) => const IconGeneratorPage(), - }, + routerConfig: _router, + // This blocks the About page button. + debugShowCheckedModeBanner: false, ); } } diff --git a/packages/web_benchmarks/testing/test_app/pubspec.yaml b/packages/web_benchmarks/testing/test_app/pubspec.yaml index e298d6defa4..58dffcd083e 100644 --- a/packages/web_benchmarks/testing/test_app/pubspec.yaml +++ b/packages/web_benchmarks/testing/test_app/pubspec.yaml @@ -11,8 +11,16 @@ environment: dependencies: flutter: sdk: flutter + flutter_web_plugins: + sdk: flutter + go_router: ^14.2.7 + +dev_dependencies: + flutter_lints: ^4.0.0 flutter_test: sdk: flutter + test: ^1.25.8 + web: ">=0.5.1 <2.0.0" web_benchmarks: path: ../../ diff --git a/packages/web_benchmarks/testing/test_app/web/icons/Icon-maskable-192.png b/packages/web_benchmarks/testing/test_app/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/packages/web_benchmarks/testing/test_app/web/icons/Icon-maskable-512.png b/packages/web_benchmarks/testing/test_app/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 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 MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/packages/web_benchmarks/testing/test_app/web/index.html b/packages/web_benchmarks/testing/test_app/web/index.html index 5b2c184c9a8..98fc61ffe20 100644 --- a/packages/web_benchmarks/testing/test_app/web/index.html +++ b/packages/web_benchmarks/testing/test_app/web/index.html @@ -1,15 +1,27 @@ - + + + - + @@ -21,6 +33,6 @@ - + diff --git a/packages/web_benchmarks/testing/test_app/web/manifest.json b/packages/web_benchmarks/testing/test_app/web/manifest.json index 13a23690776..8242090a0aa 100644 --- a/packages/web_benchmarks/testing/test_app/web/manifest.json +++ b/packages/web_benchmarks/testing/test_app/web/manifest.json @@ -18,6 +18,18 @@ "src": "icons/Icon-512.png", "sizes": "512x512", "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" } ] } From 0a155ece870a0b6cd03b52928553644135b4ed98 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:00:01 -0700 Subject: [PATCH 02/21] remove case --- .../test_app/benchmark/test_infra/automator.dart | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart index 1e5592424bf..45f43ae7346 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart @@ -59,8 +59,6 @@ class Automater { await _handleAppTap(); case BenchmarkName.simpleCompilationCheck: _handleSimpleCompilationCheck(); - case BenchmarkName.simpleBenchmarkPathCheck: - _handleSimpleBenchmarkPathCheck(); } // At the end of the test, mark as finished. @@ -116,14 +114,6 @@ class Automater { // purposes of our own tests. profile.extraData['isWasm'] = kIsWasm ? 1 : 0; } - - void _handleSimpleBenchmarkPathCheck() { - // Record whether the URL contains the expected path so we can verify the - // behavior of setting the `benchmarkPath` on the benchmark server. - final bool containsExpectedPath = - window.location.toString().contains(testBenchmarkPath); - profile.extraData['expectedUrl'] = containsExpectedPath ? 1 : 0; - } } const Duration _animationCheckingInterval = Duration(milliseconds: 50); From dfd6d34214b0f1c61139729ea0e71666568b6a39 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:03:03 -0700 Subject: [PATCH 03/21] fix test --- .../benchmark/web_benchmarks_test.dart | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart b/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart index 7a83c5ddbe5..a42557b83a6 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart @@ -28,6 +28,27 @@ Future main() async { timeout: Timeout.none, ); + test( + 'Can run a web benchmark with an alternate initial page', + () async { + final BenchmarkResults results = await _runBenchmarks( + benchmarkNames: ['simple'], + entryPoint: 'lib/benchmarks/runner_simple.dart', + initialPage: 'index.html#about', + ); + + // The simple runner just puts an `isWasm` metric in there so we can make + // sure that we're running in the right environment. + final List? scores = results.scores['simple']; + expect(scores, isNotNull); + + final BenchmarkScore isWasmScore = scores! + .firstWhere((BenchmarkScore score) => score.metric == 'isWasm'); + expect(isWasmScore.value, 0); + }, + timeout: Timeout.none, + ); + test( 'Can run a web benchmark with wasm', () async { @@ -55,14 +76,14 @@ Future main() async { Future _runBenchmarks({ required List benchmarkNames, required String entryPoint, - String benchmarkPath = defaultInitialPath, + String initialPage = defaultInitialPage, CompilationOptions compilationOptions = const CompilationOptions.js(), }) async { final BenchmarkResults taskResult = await serveWebBenchmark( benchmarkAppDirectory: Directory('testing/test_app'), entryPoint: entryPoint, treeShakeIcons: false, - benchmarkPath: benchmarkPath, + initialPage: initialPage, compilationOptions: compilationOptions, ); From 31adbd36b7452847bb821da616db30b06d3ef682 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:03:18 -0700 Subject: [PATCH 04/21] remove import --- .../testing/test_app/benchmark/test_infra/automator.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart index 45f43ae7346..05d953d85a8 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart @@ -11,7 +11,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:test_app/home_page.dart' show aboutPageKey, textKey; import 'package:test_app/main.dart'; -import 'package:web/web.dart'; import 'package:web_benchmarks/client.dart'; import 'common.dart'; From ec8ca103a12e0e89ffe6e29dc0f069b64184801b Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:37:42 -0700 Subject: [PATCH 05/21] clean up --- .../benchmark/test_infra/automator.dart | 11 +++++++++ .../client/simple_initial_page_client.dart | 19 +++++++++++++++ .../test_app/benchmark/test_infra/common.dart | 3 +++ .../benchmark/web_benchmarks_test.dart | 23 +++++++++++-------- 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_initial_page_client.dart diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart index 05d953d85a8..45cc5082efb 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart @@ -11,6 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:test_app/home_page.dart' show aboutPageKey, textKey; import 'package:test_app/main.dart'; +import 'package:web/web.dart'; import 'package:web_benchmarks/client.dart'; import 'common.dart'; @@ -58,6 +59,8 @@ class Automater { await _handleAppTap(); case BenchmarkName.simpleCompilationCheck: _handleSimpleCompilationCheck(); + case BenchmarkName.simpleInitialPageCheck: + _handleSimpleInitialPageCheck(); } // At the end of the test, mark as finished. @@ -113,6 +116,14 @@ class Automater { // purposes of our own tests. profile.extraData['isWasm'] = kIsWasm ? 1 : 0; } + + void _handleSimpleInitialPageCheck() { + // Record whether the URL contains the expected initial page so we can + // verify the behavior of setting the `initialPage` on the benchmark server. + final bool containsExpectedPage = + window.location.toString().contains(testBenchmarkInitialPage); + profile.extraData['expectedUrl'] = containsExpectedPage ? 1 : 0; + } } const Duration _animationCheckingInterval = Duration(milliseconds: 50); diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_initial_page_client.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_initial_page_client.dart new file mode 100644 index 00000000000..75bb8e31e7a --- /dev/null +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_initial_page_client.dart @@ -0,0 +1,19 @@ +// Copyright 2013 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:web_benchmarks/client.dart'; + +import '../common.dart'; +import '../recorder.dart'; + +Future main() async { + await runBenchmarks( + { + BenchmarkName.simpleInitialPageCheck.name: () => TestAppRecorder( + benchmark: BenchmarkName.simpleInitialPageCheck, + ), + }, + initialPage: testBenchmarkInitialPage, + ); +} diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/common.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/common.dart index 06667d8738d..eaba8cd1157 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/common.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/common.dart @@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +const String testBenchmarkInitialPage = 'index.html#about'; + enum BenchmarkName { appNavigate, appScroll, appTap, + simpleInitialPageCheck, simpleCompilationCheck; } diff --git a/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart b/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart index a42557b83a6..64b4f6061c8 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/web_benchmarks_test.dart @@ -32,19 +32,22 @@ Future main() async { 'Can run a web benchmark with an alternate initial page', () async { final BenchmarkResults results = await _runBenchmarks( - benchmarkNames: ['simple'], - entryPoint: 'lib/benchmarks/runner_simple.dart', - initialPage: 'index.html#about', + benchmarkNames: [BenchmarkName.simpleInitialPageCheck.name], + entryPoint: + 'benchmark/test_infra/client/simple_initial_page_client.dart', + initialPage: testBenchmarkInitialPage, ); - // The simple runner just puts an `isWasm` metric in there so we can make - // sure that we're running in the right environment. - final List? scores = results.scores['simple']; + // The runner puts an `expectedUrl` metric in the results so that we can + // verify the initial page value that should be passed on initial load + // and on reloads. + final List? scores = + results.scores[BenchmarkName.simpleInitialPageCheck.name]; expect(scores, isNotNull); final BenchmarkScore isWasmScore = scores! - .firstWhere((BenchmarkScore score) => score.metric == 'isWasm'); - expect(isWasmScore.value, 0); + .firstWhere((BenchmarkScore score) => score.metric == 'expectedUrl'); + expect(isWasmScore.value, 1); }, timeout: Timeout.none, ); @@ -59,8 +62,8 @@ Future main() async { compilationOptions: const CompilationOptions.wasm(), ); - // The simple runner just puts an `isWasm` metric in there so we can make - // sure that we're running in the right environment. + // The runner puts an `isWasm` metric in the results so that we can verify + // we are running with the correct compiler and renderer. final List? scores = results.scores[BenchmarkName.simpleCompilationCheck.name]; expect(scores, isNotNull); From 956919c19fd0820496878478f6b1311389019927 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:39:44 -0700 Subject: [PATCH 06/21] revert go router --- .../testing/test_app/lib/about_page.dart | 3 +-- .../testing/test_app/lib/home_page.dart | 3 +-- .../testing/test_app/lib/main.dart | 23 ++++++------------- .../testing/test_app/pubspec.yaml | 1 - 4 files changed, 9 insertions(+), 21 deletions(-) diff --git a/packages/web_benchmarks/testing/test_app/lib/about_page.dart b/packages/web_benchmarks/testing/test_app/lib/about_page.dart index 23f85320eaf..a3603abeb55 100644 --- a/packages/web_benchmarks/testing/test_app/lib/about_page.dart +++ b/packages/web_benchmarks/testing/test_app/lib/about_page.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; class AboutPage extends StatelessWidget { const AboutPage({super.key}); @@ -13,7 +12,7 @@ class AboutPage extends StatelessWidget { return Scaffold( appBar: AppBar( leading: BackButton( - onPressed: () => context.canPop() ? context.pop() : context.go('/'), + onPressed: () => Navigator.of(context).pop(), ), ), body: Center( diff --git a/packages/web_benchmarks/testing/test_app/lib/home_page.dart b/packages/web_benchmarks/testing/test_app/lib/home_page.dart index c0f7a131aec..2fecf2514e1 100644 --- a/packages/web_benchmarks/testing/test_app/lib/home_page.dart +++ b/packages/web_benchmarks/testing/test_app/lib/home_page.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; const ValueKey textKey = ValueKey('textKey'); const ValueKey aboutPageKey = ValueKey('aboutPageKey'); @@ -35,7 +34,7 @@ class _HomePageState extends State { IconButton( key: aboutPageKey, icon: const Icon(Icons.help_outline), - onPressed: () => context.go('/about'), + onPressed: () => Navigator.of(context).pushNamed('about'), ), ], ), diff --git a/packages/web_benchmarks/testing/test_app/lib/main.dart b/packages/web_benchmarks/testing/test_app/lib/main.dart index 172abba3288..d146a080abd 100644 --- a/packages/web_benchmarks/testing/test_app/lib/main.dart +++ b/packages/web_benchmarks/testing/test_app/lib/main.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_web_plugins/url_strategy.dart'; -import 'package:go_router/go_router.dart'; import 'about_page.dart'; import 'home_page.dart'; @@ -14,33 +13,25 @@ void main() { runApp(const MyApp()); } -final GoRouter _router = GoRouter( - routes: [ - GoRoute( - path: '/', - builder: (_, __) => const HomePage(title: 'Flutter Demo Home Page'), - ), - GoRoute( - path: '/about', - builder: (_, __) => const AboutPage(), - ), - ], -); - class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { - return MaterialApp.router( + return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), - routerConfig: _router, // This blocks the About page button. debugShowCheckedModeBanner: false, + initialRoute: 'home', + routes: { + 'home': (_) => const HomePage(title: 'Flutter Demo Home Page'), + 'about': (_) => const AboutPage(), + 'icon_generator': (_) => const IconGeneratorPage(), + }, ); } } diff --git a/packages/web_benchmarks/testing/test_app/pubspec.yaml b/packages/web_benchmarks/testing/test_app/pubspec.yaml index 58dffcd083e..a4de0db432d 100644 --- a/packages/web_benchmarks/testing/test_app/pubspec.yaml +++ b/packages/web_benchmarks/testing/test_app/pubspec.yaml @@ -13,7 +13,6 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - go_router: ^14.2.7 dev_dependencies: flutter_lints: ^4.0.0 From 998fd642cf27c157d879fd6c84054b28e7697df7 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:41:27 -0700 Subject: [PATCH 07/21] remove path url strategy --- packages/web_benchmarks/testing/test_app/lib/main.dart | 2 -- packages/web_benchmarks/testing/test_app/pubspec.yaml | 2 -- 2 files changed, 4 deletions(-) diff --git a/packages/web_benchmarks/testing/test_app/lib/main.dart b/packages/web_benchmarks/testing/test_app/lib/main.dart index d146a080abd..611d0483ddf 100644 --- a/packages/web_benchmarks/testing/test_app/lib/main.dart +++ b/packages/web_benchmarks/testing/test_app/lib/main.dart @@ -3,13 +3,11 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; -import 'package:flutter_web_plugins/url_strategy.dart'; import 'about_page.dart'; import 'home_page.dart'; void main() { - usePathUrlStrategy(); runApp(const MyApp()); } diff --git a/packages/web_benchmarks/testing/test_app/pubspec.yaml b/packages/web_benchmarks/testing/test_app/pubspec.yaml index a4de0db432d..50d6c08dcb7 100644 --- a/packages/web_benchmarks/testing/test_app/pubspec.yaml +++ b/packages/web_benchmarks/testing/test_app/pubspec.yaml @@ -11,8 +11,6 @@ environment: dependencies: flutter: sdk: flutter - flutter_web_plugins: - sdk: flutter dev_dependencies: flutter_lints: ^4.0.0 From 0de0753de9064e65875dc5ac78fe23e8711f57c2 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:42:04 -0700 Subject: [PATCH 08/21] remove unused route --- packages/web_benchmarks/testing/test_app/lib/main.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/web_benchmarks/testing/test_app/lib/main.dart b/packages/web_benchmarks/testing/test_app/lib/main.dart index 611d0483ddf..f615e761acb 100644 --- a/packages/web_benchmarks/testing/test_app/lib/main.dart +++ b/packages/web_benchmarks/testing/test_app/lib/main.dart @@ -28,7 +28,6 @@ class MyApp extends StatelessWidget { routes: { 'home': (_) => const HomePage(title: 'Flutter Demo Home Page'), 'about': (_) => const AboutPage(), - 'icon_generator': (_) => const IconGeneratorPage(), }, ); } From eb480e4ede2bdd838287610ec3ead3cc948ad694 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:53:10 -0700 Subject: [PATCH 09/21] remove initial page --- .../benchmark/test_infra/client/simple_initial_page_client.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_initial_page_client.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_initial_page_client.dart index 75bb8e31e7a..9bfd9cf3ae2 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_initial_page_client.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/client/simple_initial_page_client.dart @@ -14,6 +14,5 @@ Future main() async { benchmark: BenchmarkName.simpleInitialPageCheck, ), }, - initialPage: testBenchmarkInitialPage, ); } From 8a6631b093502207913abc91d0856ccd1715765a Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 14:54:04 -0700 Subject: [PATCH 10/21] versions --- packages/web_benchmarks/CHANGELOG.md | 2 +- packages/web_benchmarks/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web_benchmarks/CHANGELOG.md b/packages/web_benchmarks/CHANGELOG.md index a8b4eb16091..9afb5e58ce2 100644 --- a/packages/web_benchmarks/CHANGELOG.md +++ b/packages/web_benchmarks/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.0.0-wip +## 2.1.0-wip * Restructure the `testing/test_app` to make the example benchmarks easier to follow. diff --git a/packages/web_benchmarks/pubspec.yaml b/packages/web_benchmarks/pubspec.yaml index 0bc109d17d3..fb8f9df26df 100644 --- a/packages/web_benchmarks/pubspec.yaml +++ b/packages/web_benchmarks/pubspec.yaml @@ -2,7 +2,7 @@ name: web_benchmarks description: A benchmark harness for performance-testing Flutter apps in Chrome. repository: https://github.com/flutter/packages/tree/main/packages/web_benchmarks issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+web_benchmarks%22 -version: 3.0.0-wip +version: 2.1.0-wip environment: sdk: ^3.3.0 From 268e261ab1760205e329325c50bfb81718b8e755 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 15:00:18 -0700 Subject: [PATCH 11/21] test version --- packages/web_benchmarks/testing/test_app/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web_benchmarks/testing/test_app/pubspec.yaml b/packages/web_benchmarks/testing/test_app/pubspec.yaml index 50d6c08dcb7..953b188efce 100644 --- a/packages/web_benchmarks/testing/test_app/pubspec.yaml +++ b/packages/web_benchmarks/testing/test_app/pubspec.yaml @@ -16,7 +16,7 @@ dev_dependencies: flutter_lints: ^4.0.0 flutter_test: sdk: flutter - test: ^1.25.8 + test: ^1.19.5 web: ">=0.5.1 <2.0.0" web_benchmarks: path: ../../ From 9cab2690be05470f8a4dcecfd66e1eed1f816f39 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 15:25:53 -0700 Subject: [PATCH 12/21] spelling --- .../testing/test_app/benchmark/test_infra/automator.dart | 4 ++-- .../testing/test_app/benchmark/test_infra/recorder.dart | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart index 45cc5082efb..4184a8a7430 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/automator.dart @@ -17,8 +17,8 @@ import 'package:web_benchmarks/client.dart'; import 'common.dart'; /// A class that automates the test web app. -class Automater { - Automater({ +class Automator { + Automator({ required this.benchmark, required this.stopWarmingUpCallback, required this.profile, diff --git a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/recorder.dart b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/recorder.dart index ba0dc55ba30..8b0abd0d125 100644 --- a/packages/web_benchmarks/testing/test_app/benchmark/test_infra/recorder.dart +++ b/packages/web_benchmarks/testing/test_app/benchmark/test_infra/recorder.dart @@ -18,17 +18,17 @@ class TestAppRecorder extends WidgetRecorder { /// See `common.dart` for the list of the names of all benchmarks. final BenchmarkName benchmark; - Automater? _automator; + Automator? _automator; bool get _finished => _automator?.finished ?? false; /// Whether we should continue recording. @override bool shouldContinue() => !_finished || profile.shouldContinue(); - /// Creates the [Automater] widget. + /// Creates the [Automator] widget. @override Widget createWidget() { - _automator = Automater( + _automator = Automator( benchmark: benchmark, stopWarmingUpCallback: profile.stopWarmingUp, profile: profile, From 463d875cd7def94064508811d41f74f45fa51e1f Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 12 Sep 2024 16:21:55 -0700 Subject: [PATCH 13/21] add license --- packages/web_benchmarks/testing/test_app/web/index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/web_benchmarks/testing/test_app/web/index.html b/packages/web_benchmarks/testing/test_app/web/index.html index 98fc61ffe20..cc7ef836e2f 100644 --- a/packages/web_benchmarks/testing/test_app/web/index.html +++ b/packages/web_benchmarks/testing/test_app/web/index.html @@ -1,4 +1,7 @@ +