From 45ef526a4c26d92bbac4230f45d44d53410b9d0f Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 13:41:26 -0700 Subject: [PATCH 01/17] Remove unused code from test/ --- analysis_options.yaml | 3 +- .../inspector/inspector_integration_test.dart | 11 -- .../memory/framework/memory_service_test.dart | 66 -------- .../vs_code/debug_sessions_test.dart | 7 - .../test_infra/fixtures/debugging_app.dart | 40 ----- .../test/test_infra/fixtures/logging_app.dart | 38 ----- .../fixtures/networking_app/bin/main.dart | 5 - .../test/test_infra/flutter_test_driver.dart | 9 -- .../test_infra/flutter_test_environment.dart | 2 + .../test/test_infra/matchers/matchers.dart | 8 - .../scenes/memory/diff_snapshot.dart | 2 - .../editor_service/simulated_editor.dart | 9 -- .../scenes/standalone_ui/editor_sidebar.dart | 2 - .../scenes/standalone_ui/shared/utils.dart | 4 - .../test_data/deep_link/fake_responses.dart | 12 -- .../test_data/memory/heap/heap_data.dart | 9 -- .../performance/sample_performance_data.dart | 94 ----------- .../test_infra/utils/deep_links_utils.dart | 1 - .../utils/extent_delegate_utils.dart | 1 + .../test_infra/utils/rendering_tester.dart | 152 ------------------ 20 files changed, 5 insertions(+), 470 deletions(-) delete mode 100644 packages/devtools_app/test/screens/memory/framework/memory_service_test.dart delete mode 100644 packages/devtools_app/test/test_infra/fixtures/debugging_app.dart delete mode 100644 packages/devtools_app/test/test_infra/fixtures/logging_app.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index 070a4f5e864..afbbb224aed 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -169,7 +169,8 @@ dart_code_metrics: - lib/src/service/** - lib/src/shared/** - lib/src/standalone_ui/** - - test/** + # This fixture has unused code for testing the debugger. + - test/test_infra/fixtures/flutter_app/** rules: # - arguments-ordering Too strict # - avoid-banned-imports # TODO(polina-c): add configuration diff --git a/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart b/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart index 65ab143f45e..946a6665bf5 100644 --- a/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart +++ b/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart @@ -653,17 +653,6 @@ void verifyPropertyIsVisible({ expect(propertyNameCenter.dy, equals(propertyValueCenter.dy)); } -bool areHorizontallyAligned( - Finder widgetAFinder, - Finder widgetBFinder, { - required WidgetTester tester, -}) { - final widgetACenter = tester.getCenter(widgetAFinder); - final widgetBCenter = tester.getCenter(widgetBFinder); - - return widgetACenter.dy == widgetBCenter.dy; -} - bool _treeRowsAreInOrder({ required List treeRowDescriptions, required int startingAtIndex, diff --git a/packages/devtools_app/test/screens/memory/framework/memory_service_test.dart b/packages/devtools_app/test/screens/memory/framework/memory_service_test.dart deleted file mode 100644 index 650f13afef1..00000000000 --- a/packages/devtools_app/test/screens/memory/framework/memory_service_test.dart +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2019 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. - -import 'package:devtools_app/src/screens/memory/framework/memory_controller.dart'; -import 'package:devtools_app/src/screens/memory/shared/primitives/memory_timeline.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../../../test_infra/flutter_test_driver.dart' - show FlutterRunConfiguration; -import '../../../test_infra/flutter_test_environment.dart'; - -late MemoryController memoryController; - -// Track number of onMemory events received. -int memoryTrackersReceived = 0; - -int previousTimestamp = 0; - -bool firstSample = true; - -void main() { - // TODO(https://github.com/flutter/devtools/issues/2053): rewrite. - // ignore: dead_code - if (false) { - final env = FlutterTestEnvironment( - const FlutterRunConfiguration(withDebugger: true), - ); - - env.afterNewSetup = () { - memoryController = MemoryController(); - }; - } -} - -void validateHeapInfo(MemoryTimeline timeline) { - for (final sample in timeline.data) { - expect(sample.timestamp, greaterThan(0)); - expect(sample.timestamp, greaterThan(previousTimestamp)); - - expect(sample.used, greaterThan(0)); - expect(sample.used, lessThan(sample.capacity)); - - expect(sample.external, greaterThan(0)); - expect(sample.external, lessThan(sample.capacity)); - - // TODO(terry): Bug - VM's first HeapSample returns a null for the rss value. - // Subsequent samples the rss values are valid integers. This is - // a VM regression https://github.com/dart-lang/sdk/issues/40766. - // When fixed, remove below test rss != null and firstSample global. - if (firstSample) { - expect(sample.rss, greaterThan(0)); - expect(sample.rss, greaterThan(sample.capacity)); - firstSample = false; - } - - expect(sample.capacity, greaterThan(0)); - expect(sample.capacity, greaterThan(sample.used + sample.external)); - - previousTimestamp = sample.timestamp; - } - - timeline.data.clear(); - - memoryTrackersReceived++; -} diff --git a/packages/devtools_app/test/standalone_ui/vs_code/debug_sessions_test.dart b/packages/devtools_app/test/standalone_ui/vs_code/debug_sessions_test.dart index 1bb122e5542..a6aa78574b2 100644 --- a/packages/devtools_app/test/standalone_ui/vs_code/debug_sessions_test.dart +++ b/packages/devtools_app/test/standalone_ui/vs_code/debug_sessions_test.dart @@ -4,7 +4,6 @@ import 'package:devtools_app/devtools_app.dart'; import 'package:devtools_app/src/shared/constants.dart'; -import 'package:devtools_app/src/shared/editor/api_classes.dart'; import 'package:devtools_app/src/standalone_ui/vs_code/debug_sessions.dart'; import 'package:devtools_app_shared/ui.dart'; import 'package:devtools_app_shared/utils.dart'; @@ -14,22 +13,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; -import '../../test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart'; import '../../test_infra/utils/sidebar_utils.dart'; void main() { const windowSize = Size(2000.0, 2000.0); late MockEditorClient mockEditorClient; - late final Map deviceMap; setUpAll(() { // Set test mode so that the debug list of extensions will be used. setTestMode(); setGlobal(ServiceConnectionManager, FakeServiceConnectionManager()); - - final devices = stubbedDevices.map((d) => MapEntry(d.id, d)); - deviceMap = {for (final d in devices) d.key: d.value}; }); setUp(() { @@ -52,7 +46,6 @@ void main() { sessions: Map.fromEntries( _debugSessions.map((s) => MapEntry(s.id, s)), ), - devices: deviceMap, ), ), ); diff --git a/packages/devtools_app/test/test_infra/fixtures/debugging_app.dart b/packages/devtools_app/test/test_infra/fixtures/debugging_app.dart deleted file mode 100644 index bb732d9187d..00000000000 --- a/packages/devtools_app/test/test_infra/fixtures/debugging_app.dart +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2019 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. - -// ignore_for_file: avoid_print - -import 'dart:async'; - -void main() { - print('starting debugging app'); - - final cat = Cat('Fluffy'); - - void run() { - Timer(const Duration(milliseconds: 100), () { - cat.performAction(); - - run(); - }); - } - - run(); -} - -class Cat { - Cat(this.name); - - final String name; - - String get type => 'cat'; - - int actionCount = 0; - - void performAction() { - String actionStr = 'catAction'; - actionStr = '$actionStr!'; - - actionCount++; // breakpoint - } -} diff --git a/packages/devtools_app/test/test_infra/fixtures/logging_app.dart b/packages/devtools_app/test/test_infra/fixtures/logging_app.dart deleted file mode 100644 index afe3700a6a2..00000000000 --- a/packages/devtools_app/test/test_infra/fixtures/logging_app.dart +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2018 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. - -// ignore_for_file: avoid_print - -import 'dart:async'; -import 'dart:developer'; -import 'dart:io'; - -// Allow a test driver to communicate with this app through the controller. -final controller = Controller(); - -void main() { - print('starting logging app'); - log('starting logging app'); - - // Don't exit until it's indicated we should by the controller. - Timer(const Duration(days: 1), () {}); -} - -class Controller { - int count = 0; - - void emitLog() { - count++; - - print('emitLog called'); - log('emit log $count', name: 'logging'); - } - - void shutdown() { - print('stopping app'); - log('stopping app'); - - exit(0); - } -} diff --git a/packages/devtools_app/test/test_infra/fixtures/networking_app/bin/main.dart b/packages/devtools_app/test/test_infra/fixtures/networking_app/bin/main.dart index 73d1d30a4ab..c875688e804 100644 --- a/packages/devtools_app/test/test_infra/fixtures/networking_app/bin/main.dart +++ b/packages/devtools_app/test/test_infra/fixtures/networking_app/bin/main.dart @@ -100,11 +100,6 @@ class _HttpClient { final _dio = Dio(); - void close() { - _client.close(force: true); - _dio.close(force: true); - } - void get() async { print('Sending GET...'); final request = await _client.getUrl(_uri); diff --git a/packages/devtools_app/test/test_infra/flutter_test_driver.dart b/packages/devtools_app/test/test_infra/flutter_test_driver.dart index 99eda70e734..5aa28a639f0 100644 --- a/packages/devtools_app/test/test_infra/flutter_test_driver.dart +++ b/packages/devtools_app/test/test_infra/flutter_test_driver.dart @@ -43,17 +43,9 @@ abstract class FlutterTestDriver { final errorBuffer = StringBuffer(); late String lastResponse; late Uri _vmServiceWsUri; - bool hasExited = false; VmServiceWrapper? vmService; - String get lastErrorInfo => errorBuffer.toString(); - - Stream get stderr => stderrController.stream; - Stream get stdout => stdoutController.stream; - - Uri get vmServiceUri => _vmServiceWsUri; - String _debugPrint(String msg) { const maxLength = 500; final truncatedMsg = msg.length > maxLength @@ -94,7 +86,6 @@ abstract class FlutterTestDriver { unawaited( proc.exitCode.then((int code) { _debugPrint('Process exited ($code)'); - hasExited = true; }), ); transformToLines( diff --git a/packages/devtools_app/test/test_infra/flutter_test_environment.dart b/packages/devtools_app/test/test_infra/flutter_test_environment.dart index 54da10aa78d..42172ef6c8b 100644 --- a/packages/devtools_app/test/test_infra/flutter_test_environment.dart +++ b/packages/devtools_app/test/test_infra/flutter_test_environment.dart @@ -74,6 +74,7 @@ class FlutterTestEnvironment { // This function will be called after we have ran the Flutter app and the // vmService is opened. Future Function()? _afterNewSetup; + // ignore: unused-code, part of this class's lifecycle. set afterNewSetup(Future Function() f) => _afterNewSetup = f; // This function will be called for every call to [setupEnvironment], even @@ -92,6 +93,7 @@ class FlutterTestEnvironment { // The function will be called before the final forced teardown at the end // of the test suite (which will then stop the Flutter app). Future Function()? _beforeFinalTearDown; + // ignore: unused-code, part of this class's lifecycle. set beforeFinalTearDown(Future Function() f) => _beforeFinalTearDown = f; diff --git a/packages/devtools_app/test/test_infra/matchers/matchers.dart b/packages/devtools_app/test/test_infra/matchers/matchers.dart index 6005a4540a8..e13237043ee 100644 --- a/packages/devtools_app/test/test_infra/matchers/matchers.dart +++ b/packages/devtools_app/test/test_infra/matchers/matchers.dart @@ -34,14 +34,6 @@ String treeToDebugString(RemoteDiagnosticsNode node) { return node.toDiagnosticsNode().toStringDeep(); } -String treeToDebugStringTruncated(RemoteDiagnosticsNode node, int maxLines) { - List lines = node.toDiagnosticsNode().toStringDeep().split('\n'); - if (lines.length > maxLines) { - lines = lines.take(maxLines).toList()..add('...'); - } - return lines.join('\n'); -} - /// Asserts that a [path] matches a golden file after normalizing likely hash /// codes. /// diff --git a/packages/devtools_app/test/test_infra/scenes/memory/diff_snapshot.dart b/packages/devtools_app/test/test_infra/scenes/memory/diff_snapshot.dart index aa79a9d08dc..ce34c5f5238 100644 --- a/packages/devtools_app/test/test_infra/scenes/memory/diff_snapshot.dart +++ b/packages/devtools_app/test/test_infra/scenes/memory/diff_snapshot.dart @@ -60,6 +60,4 @@ class DiffSnapshotScene extends Scene { ClassFilter(filterType: ClassFilterType.showAll, except: '', only: ''), ); } - - void tearDown() {} } diff --git a/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart b/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart index a762658e145..b549d4c79d7 100644 --- a/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart +++ b/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart @@ -35,11 +35,6 @@ class SimulatedEditor { return editor; } - void dispose() { - unawaited(_logger.close()); - unawaited(close()); - } - /// The URI of the DTD instance we are connecting/connected to. final Uri _dtdUri; @@ -209,10 +204,6 @@ class SimulatedEditor { await _postEvent(DebugSessionStartedEvent(debugSession: debugSession)); } - void sendDebugSessionChanged(EditorDebugSession debugSession) async { - await _postEvent(DebugSessionChangedEvent(debugSession: debugSession)); - } - void sendDebugSessionStopped(EditorDebugSession debugSession) async { await _postEvent(DebugSessionStoppedEvent(debugSessionId: debugSession.id)); } diff --git a/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_sidebar.dart b/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_sidebar.dart index 57cbd4fa9e4..bdf95127c43 100644 --- a/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_sidebar.dart +++ b/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_sidebar.dart @@ -9,7 +9,6 @@ import 'package:devtools_app/src/standalone_ui/standalone_screen.dart'; import 'package:devtools_app_shared/service.dart'; import 'package:devtools_app_shared/ui.dart'; import 'package:devtools_app_shared/utils.dart'; -import 'package:dtd/dtd.dart'; import 'package:flutter/material.dart'; import 'package:stager/stager.dart'; @@ -24,7 +23,6 @@ import 'shared/utils.dart'; /// flutter run -t test/test_infra/scenes/standalone_ui/editor_sidebar.stager_app.g.dart -d chrome class EditorSidebarScene extends Scene { late Stream clientLog; - late DartToolingDaemon clientDtd; late SimulatedEditor editor; @override diff --git a/packages/devtools_app/test/test_infra/scenes/standalone_ui/shared/utils.dart b/packages/devtools_app/test/test_infra/scenes/standalone_ui/shared/utils.dart index 0156a7f2603..bfda887b284 100644 --- a/packages/devtools_app/test/test_infra/scenes/standalone_ui/shared/utils.dart +++ b/packages/devtools_app/test/test_infra/scenes/standalone_ui/shared/utils.dart @@ -9,10 +9,6 @@ import 'package:dtd/dtd.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; -/// A record of a [StreamChannel] and a [Stream] of logs of protocol traffic -/// in both directions across it. -typedef LoggedChannel = ({StreamChannel channel, Stream log}); - /// Connects to the websocket at [wsUri] and returns a [StreamSink]. /// /// All traffic is logged into [sink]. diff --git a/packages/devtools_app/test/test_infra/test_data/deep_link/fake_responses.dart b/packages/devtools_app/test/test_infra/test_data/deep_link/fake_responses.dart index 1f8ebc5272f..beaf9c50d45 100644 --- a/packages/devtools_app/test/test_infra/test_data/deep_link/fake_responses.dart +++ b/packages/devtools_app/test/test_infra/test_data/deep_link/fake_responses.dart @@ -429,18 +429,6 @@ const iosValidationResponseWithError = ''' } '''; -const androidDeepLinkWithPathErrors = '''{ - "host": "example.com", - "path": "/path", - "intentFilterCheck": { - "hasBrowsableCategory": false, - "hasActionView": true, - "hasDefaultCategory": true, - "hasAutoVerify": true - } - } -'''; - const defaultDomain = 'example.com'; String androidDeepLinkJson( diff --git a/packages/devtools_app/test/test_infra/test_data/memory/heap/heap_data.dart b/packages/devtools_app/test/test_infra/test_data/memory/heap/heap_data.dart index 867dff6eae7..be031245f44 100644 --- a/packages/devtools_app/test/test_infra/test_data/memory/heap/heap_data.dart +++ b/packages/devtools_app/test/test_infra/test_data/memory/heap/heap_data.dart @@ -32,15 +32,6 @@ class GoldenHeapTest extends HeapTest { } } -class MockedHeapTest extends HeapTest { - MockedHeapTest({required super.appClassName}); - - @override - Future loadHeap() { - throw UnimplementedError(); - } -} - /// Provides test snapshots from pre-saved goldens. class HeapGraphLoaderGoldens implements HeapGraphLoader { int _nextIndex = 0; diff --git a/packages/devtools_app/test/test_infra/test_data/performance/sample_performance_data.dart b/packages/devtools_app/test/test_infra/test_data/performance/sample_performance_data.dart index 8a9362ca124..e453bb56b31 100644 --- a/packages/devtools_app/test/test_infra/test_data/performance/sample_performance_data.dart +++ b/packages/devtools_app/test/test_infra/test_data/performance/sample_performance_data.dart @@ -140,32 +140,6 @@ extension FlutterFrame2 on Never { ..setEventFlow(uiEvent) ..setEventFlow(rasterEvent); - static const uiEventAsString = - ''' Animator::BeginFrame [713834379092 μs - 713834379102 μs] -'''; - - static const rasterEventAsString = - ''' Rasterizer::DoDraw [713836088591 μs - 713836108931 μs] - Rasterizer::DrawToSurfaces [713836088592 μs - 713836108917 μs] - GPUSurfaceMetalImpeller::AcquireFrame [713836088607 μs - 713836093553 μs] - SurfaceMTL::WrapCurrentMetalLayerDrawable [713836088654 μs - 713836093545 μs] - WaitForNextDrawable [713836088655 μs - 713836093541 μs] - CompositorContext::ScopedFrame::Raster [713836093557 μs - 713836093615 μs] - LayerTree::Preroll [713836093580 μs - 713836093597 μs] - IOSExternalViewEmbedder::PostPrerollAction [713836093598 μs - 713836093598 μs] - LayerTree::Paint [713836093599 μs - 713836093615 μs] - SurfaceFrame::Submit [713836093616 μs - 713836108864 μs] - SurfaceFrame::BuildDisplayList [713836093616 μs - 713836093621 μs] - DisplayListDispatcher::EndRecordingAsPicture [713836094185 μs - 713836094188 μs] - Renderer::Render [713836094188 μs - 713836108846 μs] - EntityPass::OnRender [713836094556 μs - 713836108700 μs] - CreateGlyphAtlas [713836099800 μs - 713836108025 μs] - CanAppendToExistingAtlas [713836099807 μs - 713836099810 μs] - OptimumAtlasSizeForFontGlyphPairs [713836099811 μs - 713836099835 μs] - CreateAtlasBitmap [713836099845 μs - 713836103975 μs] - UploadGlyphTextureAtlas [713836103979 μs - 713836108020 μs] -'''; - static final uiEvent = animatorBeginFrameEvent; static final animatorBeginFrameEvent = testTimelineEvent( name: 'Animator::BeginFrame', @@ -385,40 +359,6 @@ extension FlutterFrame4 on Never { 'vsyncOverhead': 12625, }; - static const uiEventAsString = - ''' Animator::BeginFrame [713836200161 μs - 713836206957 μs] - LAYOUT (root) [713836202351 μs - 713836202383 μs] - LAYOUT [713836202373 μs - 713836202380 μs] - UPDATING COMPOSITING BITS (root) [713836202387 μs - 713836202402 μs] - UPDATING COMPOSITING BITS [713836202397 μs - 713836202400 μs] - PAINT (root) [713836202408 μs - 713836202429 μs] - PAINT [713836202422 μs - 713836202427 μs] - COMPOSITING [713836202440 μs - 713836206727 μs] - Animator::Render [713836206671 μs - 713836206714 μs] - SEMANTICS (root) [713836206752 μs - 713836206828 μs] - SEMANTICS [713836206785 μs - 713836206825 μs] - FINALIZE TREE [713836206834 μs - 713836206878 μs] - POST_FRAME [713836206903 μs - 713836206925 μs] -'''; - - static const rasterEventAsString = - ''' Rasterizer::DoDraw [713836206748 μs - 713836211160 μs] - Rasterizer::DrawToSurfaces [713836206750 μs - 713836211143 μs] - GPUSurfaceMetalImpeller::AcquireFrame [713836206755 μs - 713836210203 μs] - SurfaceMTL::WrapCurrentMetalLayerDrawable [713836206763 μs - 713836210196 μs] - WaitForNextDrawable [713836206764 μs - 713836210193 μs] - CompositorContext::ScopedFrame::Raster [713836210206 μs - 713836210251 μs] - LayerTree::Preroll [713836210219 μs - 713836210225 μs] - IOSExternalViewEmbedder::PostPrerollAction [713836210226 μs - 713836210226 μs] - LayerTree::Paint [713836210240 μs - 713836210250 μs] - SurfaceFrame::Submit [713836210251 μs - 713836211118 μs] - SurfaceFrame::BuildDisplayList [713836210251 μs - 713836210254 μs] - DisplayListDispatcher::EndRecordingAsPicture [713836210613 μs - 713836210616 μs] - Renderer::Render [713836210616 μs - 713836211105 μs] - EntityPass::OnRender [713836210642 μs - 713836211061 μs] - CreateGlyphAtlas [713836210893 μs - 713836210899 μs] -'''; - static final uiEvent = animatorBeginFrameEvent ..addAllChildren([ layoutRootEvent..addChild(layoutEvent), @@ -943,40 +883,6 @@ extension FlutterFrame6 on Never { 'vsyncOverhead': 1108, }; - static const uiEventAsString = - ''' Animator::BeginFrame [713836329948 μs - 713836331003 μs] - LAYOUT (root) [713836330239 μs - 713836330280 μs] - LAYOUT [713836330262 μs - 713836330277 μs] - UPDATING COMPOSITING BITS (root) [713836330284 μs - 713836330307 μs] - UPDATING COMPOSITING BITS [713836330302 μs - 713836330306 μs] - PAINT (root) [713836330324 μs - 713836330348 μs] - PAINT [713836330337 μs - 713836330346 μs] - COMPOSITING [713836330357 μs - 713836330723 μs] - Animator::Render [713836330691 μs - 713836330716 μs] - SEMANTICS (root) [713836330738 μs - 713836330844 μs] - SEMANTICS [713836330783 μs - 713836330842 μs] - FINALIZE TREE [713836330848 μs - 713836330920 μs] - POST_FRAME [713836330964 μs - 713836330989 μs] -'''; - - static const rasterEventAsString = - ''' Rasterizer::DoDraw [713836330790 μs - 713836331692 μs] - Rasterizer::DrawToSurfaces [713836330791 μs - 713836331684 μs] - GPUSurfaceMetalImpeller::AcquireFrame [713836330801 μs - 713836330844 μs] - SurfaceMTL::WrapCurrentMetalLayerDrawable [713836330814 μs - 713836330839 μs] - WaitForNextDrawable [713836330817 μs - 713836330836 μs] - CompositorContext::ScopedFrame::Raster [713836330846 μs - 713836330888 μs] - LayerTree::Preroll [713836330862 μs - 713836330870 μs] - IOSExternalViewEmbedder::PostPrerollAction [713836330870 μs - 713836330870 μs] - LayerTree::Paint [713836330870 μs - 713836330888 μs] - SurfaceFrame::Submit [713836330888 μs - 713836331669 μs] - SurfaceFrame::BuildDisplayList [713836330889 μs - 713836330894 μs] - DisplayListDispatcher::EndRecordingAsPicture [713836331274 μs - 713836331276 μs] - Renderer::Render [713836331277 μs - 713836331661 μs] - EntityPass::OnRender [713836331302 μs - 713836331633 μs] - CreateGlyphAtlas [713836331499 μs - 713836331505 μs] -'''; - static final uiEvent = animatorBeginFrameEvent ..addAllChildren([ layoutRootEvent..addChild(layoutEvent), diff --git a/packages/devtools_app/test/test_infra/utils/deep_links_utils.dart b/packages/devtools_app/test/test_infra/utils/deep_links_utils.dart index 4242f4ee753..509a0b3de83 100644 --- a/packages/devtools_app/test/test_infra/utils/deep_links_utils.dart +++ b/packages/devtools_app/test/test_infra/utils/deep_links_utils.dart @@ -56,7 +56,6 @@ class TestDeepLinksController extends DeepLinksController { List fakeAndroidDeepLinks = []; bool hasAndroidDomainErrors = false; - bool hasAndroidPathErrors = false; String iosValidationResponse = ''; List fakeIosDomains = []; diff --git a/packages/devtools_app/test/test_infra/utils/extent_delegate_utils.dart b/packages/devtools_app/test/test_infra/utils/extent_delegate_utils.dart index 6893cf1909f..e3ef8c0f765 100644 --- a/packages/devtools_app/test/test_infra/utils/extent_delegate_utils.dart +++ b/packages/devtools_app/test/test_infra/utils/extent_delegate_utils.dart @@ -16,6 +16,7 @@ class TestRenderSliverBoxChildManager extends RenderSliverBoxChildManager { }); late RenderSliverExtentDelegateBoxAdaptor _renderObject; + // ignore: unused-code, used in asserts. bool _renderObjectInitialized = false; List children; diff --git a/packages/devtools_app/test/test_infra/utils/rendering_tester.dart b/packages/devtools_app/test/test_infra/utils/rendering_tester.dart index 5b054988ed0..6de266902d4 100644 --- a/packages/devtools_app/test/test_infra/utils/rendering_tester.dart +++ b/packages/devtools_app/test/test_infra/utils/rendering_tester.dart @@ -123,79 +123,8 @@ class TestRenderingFlutterBinding extends BindingBase /// time, or [takeAllFlutterErrorDetails] to iterate over all errors. VoidCallback? onErrors; - /// Returns the error least recently caught by [FlutterError] and removes it - /// from the list of captured errors. - /// - /// Returns null if no errors were captures, or if the list was exhausted by - /// calling this method repeatedly. - FlutterErrorDetails? takeFlutterErrorDetails() { - if (_errors.isEmpty) { - return null; - } - return _errors.removeAt(0); - } - - /// Returns all error details caught by [FlutterError] from least recently caught to - /// most recently caught, and removes them from the list of captured errors. - /// - /// The returned iterable takes errors lazily. If, for example, you iterate over 2 - /// errors, but there are 5 errors total, this binding will still fail the test. - /// Tests are expected to take and inspect all errors. - Iterable takeAllFlutterErrorDetails() sync* { - // sync* and yield are used for lazy evaluation. Otherwise, the list would be - // drained eagerly and allow a test pass with unexpected errors. - while (_errors.isNotEmpty) { - yield _errors.removeAt(0); - } - } - - /// Returns all exceptions caught by [FlutterError] from least recently caught to - /// most recently caught, and removes them from the list of captured errors. - /// - /// The returned iterable takes errors lazily. If, for example, you iterate over 2 - /// errors, but there are 5 errors total, this binding will still fail the test. - /// Tests are expected to take and inspect all errors. - Iterable takeAllFlutterExceptions() sync* { - // sync* and yield are used for lazy evaluation. Otherwise, the list would be - // drained eagerly and allow a test pass with unexpected errors. - while (_errors.isNotEmpty) { - yield _errors.removeAt(0).exception; - } - } - EnginePhase phase = EnginePhase.composite; - /// Pumps a frame and runs its entire life cycle. - /// - /// This method runs all of the [SchedulerPhase]s in a frame, this is useful - /// to test [SchedulerPhase.postFrameCallbacks]. - void pumpCompleteFrame() { - final FlutterExceptionHandler? oldErrorHandler = FlutterError.onError; - FlutterError.onError = _errors.add; - try { - TestRenderingFlutterBinding.instance.handleBeginFrame(null); - TestRenderingFlutterBinding.instance.handleDrawFrame(); - } finally { - FlutterError.onError = oldErrorHandler; - if (_errors.isNotEmpty) { - if (onErrors != null) { - onErrors!(); - if (_errors.isNotEmpty) { - _errors.forEach(FlutterError.dumpErrorToConsole); - fail( - 'There are more errors than the test inspected using TestRenderingFlutterBinding.takeFlutterErrorDetails.', - ); - } - } else { - _errors.forEach(FlutterError.dumpErrorToConsole); - fail( - 'Caught error while rendering frame. See preceding logs for details.', - ); - } - } - } - } - @override void drawFrame() { assert( @@ -315,20 +244,6 @@ void pumpFrame({ TestRenderingFlutterBinding.instance.drawFrame(); } -class TestCallbackPainter extends CustomPainter { - const TestCallbackPainter({required this.onPaint}); - - final VoidCallback onPaint; - - @override - void paint(Canvas canvas, Size size) { - onPaint(); - } - - @override - bool shouldRepaint(TestCallbackPainter oldPainter) => true; -} - class RenderSizedBox extends RenderBox { RenderSizedBox(this._size); @@ -368,70 +283,3 @@ class RenderSizedBox extends RenderBox { @override bool hitTestSelf(Offset position) => true; } - -class TestClipPaintingContext extends PaintingContext { - TestClipPaintingContext() : super(ContainerLayer(), Rect.zero); - - @override - ClipRectLayer? pushClipRect( - bool needsCompositing, - Offset offset, - Rect clipRect, - PaintingContextCallback painter, { - Clip clipBehavior = Clip.hardEdge, - ClipRectLayer? oldLayer, - }) { - this.clipBehavior = clipBehavior; - return null; - } - - Clip clipBehavior = Clip.none; -} - -class TestPushLayerPaintingContext extends PaintingContext { - TestPushLayerPaintingContext() : super(ContainerLayer(), Rect.zero); - - final pushedLayers = []; - - @override - void pushLayer( - ContainerLayer childLayer, - PaintingContextCallback painter, - Offset offset, { - Rect? childPaintBounds, - }) { - pushedLayers.add(childLayer); - super.pushLayer( - childLayer, - painter, - offset, - childPaintBounds: childPaintBounds, - ); - } -} - -// Absorbs errors that don't have "overflowed" in their error details. -void absorbOverflowedErrors() { - final errorDetails = TestRenderingFlutterBinding.instance - .takeAllFlutterErrorDetails(); - final filtered = errorDetails.where((FlutterErrorDetails details) { - return !details.toString().contains('overflowed'); - }); - if (filtered.isNotEmpty) { - filtered.forEach(FlutterError.reportError); - } -} - -// Reports any FlutterErrors. -void expectNoFlutterErrors() { - final errorDetails = TestRenderingFlutterBinding.instance - .takeAllFlutterErrorDetails(); - errorDetails.forEach(FlutterError.reportError); -} - -RenderConstrainedBox get box200x200 => RenderConstrainedBox( - additionalConstraints: const BoxConstraints.tightFor( - height: 200.0, - width: 200.0, - ), -); From 84c44977126dc2d9607d54533cc0c3bbd8da087a Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 13:44:19 -0700 Subject: [PATCH 02/17] formatting --- .../src/mocks/fake_vm_service_wrapper.dart | 28 ++++++++++--------- tool/cpu_sample_intervals.dart | 8 +++--- tool/json_to_map.dart | 12 ++++---- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart b/packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart index 0df17c7f325..c687bb6d4cb 100644 --- a/packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart +++ b/packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart @@ -128,25 +128,27 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper { } @override - Future lookupPackageUris( - String isolateId, - List uris, - ) => Future.syncValue(UriList( - uris: _resolvedUriMap != null - ? (uris.map((e) => _resolvedUriMap[e]).toList()) - : null - )); + Future lookupPackageUris(String isolateId, List uris) => + Future.syncValue( + UriList( + uris: _resolvedUriMap != null + ? (uris.map((e) => _resolvedUriMap[e]).toList()) + : null, + ), + ); @override Future lookupResolvedPackageUris( String isolateId, List uris, { bool? local, - }) => Future.syncValue(UriList( - uris: _reverseResolvedUriMap != null - ? (uris.map((e) => _reverseResolvedUriMap[e]).toList()) - : null, - )); + }) => Future.syncValue( + UriList( + uris: _reverseResolvedUriMap != null + ? (uris.map((e) => _reverseResolvedUriMap[e]).toList()) + : null, + ), + ); @override String get wsUri => 'ws://127.0.0.1:56137/ISsyt6ki0no=/ws'; diff --git a/tool/cpu_sample_intervals.dart b/tool/cpu_sample_intervals.dart index f6b2f07b556..10d50bcbc2f 100644 --- a/tool/cpu_sample_intervals.dart +++ b/tool/cpu_sample_intervals.dart @@ -26,10 +26,10 @@ void main(List arguments) async { final List deltas = []; for (int i = 0; i < cpuSampleTraceEvents.length - 1; i++) { - final Map current = - (cpuSampleTraceEvents[i] as Map).cast(); - final Map next = - (cpuSampleTraceEvents[i + 1] as Map).cast(); + final Map current = (cpuSampleTraceEvents[i] as Map) + .cast(); + final Map next = (cpuSampleTraceEvents[i + 1] as Map) + .cast(); deltas.add((next['ts'] as int) - (current['ts'] as int)); } print(deltas); diff --git a/tool/json_to_map.dart b/tool/json_to_map.dart index dffb32204c0..d3b134174b4 100644 --- a/tool/json_to_map.dart +++ b/tool/json_to_map.dart @@ -30,8 +30,9 @@ void main(List args) { } final jsonFileName = jsonFilePath.split('/').last; - final fileNameWithoutExtension = (jsonFileName.split('.') - ..removeLast()).join('.'); + final fileNameWithoutExtension = (jsonFileName.split( + '.', + )..removeLast()).join('.'); final jsonFileDirectoryPath = Uri.parse( (jsonFilePath.split('/')..removeLast()).join('/'), ); @@ -45,10 +46,9 @@ void main(List args) { // String interpolation. jsonFormattedString = jsonFormattedString.replaceAll('\$', '\\\$'); - final dartFile = - File('$jsonFileDirectoryPath/$fileNameWithoutExtension.dart') - ..createSync() - ..writeAsStringSync(''' + final dartFile = File('$jsonFileDirectoryPath/$fileNameWithoutExtension.dart') + ..createSync() + ..writeAsStringSync(''' // Copyright 2023 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. From 6cc58e76a6a43d3f8351ec2f3b4f710019553f79 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 13:54:47 -0700 Subject: [PATCH 03/17] remove dead code --- .../test/test_infra/flutter_test_environment.dart | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/devtools_app/test/test_infra/flutter_test_environment.dart b/packages/devtools_app/test/test_infra/flutter_test_environment.dart index 42172ef6c8b..be2b98b8a9f 100644 --- a/packages/devtools_app/test/test_infra/flutter_test_environment.dart +++ b/packages/devtools_app/test/test_infra/flutter_test_environment.dart @@ -71,12 +71,6 @@ class FlutterTestEnvironment { /// test/my_test.dart`). final String _flutterExe; - // This function will be called after we have ran the Flutter app and the - // vmService is opened. - Future Function()? _afterNewSetup; - // ignore: unused-code, part of this class's lifecycle. - set afterNewSetup(Future Function() f) => _afterNewSetup = f; - // This function will be called for every call to [setupEnvironment], even // when the setup is not forced or triggered by a new FlutterRunConfiguration. Future Function()? _afterEverySetup; @@ -90,13 +84,6 @@ class FlutterTestEnvironment { set beforeEveryTearDown(Future Function() f) => _beforeEveryTearDown = f; - // The function will be called before the final forced teardown at the end - // of the test suite (which will then stop the Flutter app). - Future Function()? _beforeFinalTearDown; - // ignore: unused-code, part of this class's lifecycle. - set beforeFinalTearDown(Future Function() f) => - _beforeFinalTearDown = f; - bool _needsSetup = true; Completer? _setupInProgress; From 34e36af7c135c14d1db143f8051b7e1f1a7c2096 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 15:30:42 -0700 Subject: [PATCH 04/17] Fix errors. --- .../test/test_infra/flutter_test_environment.dart | 4 ---- .../test/test_infra/utils/rendering_tester.dart | 6 ++---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/devtools_app/test/test_infra/flutter_test_environment.dart b/packages/devtools_app/test/test_infra/flutter_test_environment.dart index be2b98b8a9f..de5d25bc710 100644 --- a/packages/devtools_app/test/test_infra/flutter_test_environment.dart +++ b/packages/devtools_app/test/test_infra/flutter_test_environment.dart @@ -162,8 +162,6 @@ class FlutterTestEnvironment { } finally { _setupInProgress!.complete(!_needsSetup); } - - if (_afterNewSetup != null) await _afterNewSetup!(); } if (_afterEverySetup != null) await _afterEverySetup!(); } @@ -181,8 +179,6 @@ class FlutterTestEnvironment { return; } - if (_beforeFinalTearDown != null) await _beforeFinalTearDown!(); - await serviceConnection.serviceManager.manuallyDisconnect(); await _service.allFuturesCompleted.timeout( diff --git a/packages/devtools_app/test/test_infra/utils/rendering_tester.dart b/packages/devtools_app/test/test_infra/utils/rendering_tester.dart index 6de266902d4..b74d9fcaad3 100644 --- a/packages/devtools_app/test/test_infra/utils/rendering_tester.dart +++ b/packages/devtools_app/test/test_infra/utils/rendering_tester.dart @@ -34,8 +34,7 @@ class TestRenderingFlutterBinding extends BindingBase /// /// If [onErrors] is not null, it is called if [FlutterError] caught any errors /// while drawing the frame. If [onErrors] is null and [FlutterError] caught at least - /// one error, this function fails the test. A test may override [onErrors] and - /// inspect errors using [takeFlutterErrorDetails]. + /// one error, this function fails the test. /// /// Errors caught between frames will cause the test to fail unless /// [FlutterError.onError] has been overridden. @@ -119,8 +118,7 @@ class TestRenderingFlutterBinding extends BindingBase /// A function called after drawing a frame if [FlutterError] caught any errors. /// /// This function is expected to inspect these errors and decide whether they - /// are expected or not. Use [takeFlutterErrorDetails] to take one error at a - /// time, or [takeAllFlutterErrorDetails] to iterate over all errors. + /// are expected or not. VoidCallback? onErrors; EnginePhase phase = EnginePhase.composite; From bbacff4a74e8b6795f6335e065b38d72e643b1d8 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 16:08:18 -0700 Subject: [PATCH 05/17] Fix DCM warnings --- .../lib/src/screens/performance/performance_controller.dart | 3 --- .../scenes/standalone_ui/editor_service/simulated_editor.dart | 1 + packages/devtools_shared/lib/src/server/file_system.dart | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/performance/performance_controller.dart b/packages/devtools_app/lib/src/screens/performance/performance_controller.dart index a41441fcf36..b9e158009c5 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_controller.dart @@ -48,13 +48,10 @@ class PerformanceController extends DevToolsScreenController @override final screenId = ScreenMetaData.performance.id; - // ignore: dispose-class-fields, false positive. See `applyToFeatureControllers` in the dispose() method. late final FlutterFramesController flutterFramesController; - // ignore: dispose-class-fields, false positive. See `applyToFeatureControllers` in the dispose() method. late final TimelineEventsController timelineEventsController; - // ignore: dispose-class-fields, false positive. See `applyToFeatureControllers` in the dispose() method. late final RebuildStatsController rebuildStatsController; // ignore: dispose-class-fields, false positive. See `applyToFeatureControllers` in the dispose() method. diff --git a/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart b/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart index b549d4c79d7..d2d66ef6531 100644 --- a/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart +++ b/packages/devtools_app/test/test_infra/scenes/standalone_ui/editor_service/simulated_editor.dart @@ -44,6 +44,7 @@ class SimulatedEditor { DartToolingDaemon? _dtd; /// A controller for emitting to [log]. + // ignore: dispose-class-fields, only used in tests. final _logger = StreamController(); /// A stream of protocol traffic between the editor and DTD (or postMessage diff --git a/packages/devtools_shared/lib/src/server/file_system.dart b/packages/devtools_shared/lib/src/server/file_system.dart index 450790b47fd..63918084354 100644 --- a/packages/devtools_shared/lib/src/server/file_system.dart +++ b/packages/devtools_shared/lib/src/server/file_system.dart @@ -12,7 +12,7 @@ import 'package:path/path.dart' as path; import 'devtools_store.dart'; /// The real, local file system, which can be avoided in tests. -const FileSystem fileSystem = LocalFileSystem(); +const fileSystem = LocalFileSystem(); extension FileSystemExtension on FileSystem { static String get _userHomeDir { From 0a4d645b7edb21f8f887b3b9f9dad0427f40e18d Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 16:08:51 -0700 Subject: [PATCH 06/17] upgrade dcm --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 125a7ca0e6b..5386271c604 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -74,7 +74,7 @@ jobs: wget -qO- https://dcm.dev/pgp-key.public | sudo gpg --dearmor -o /usr/share/keyrings/dcm.gpg echo 'deb [signed-by=/usr/share/keyrings/dcm.gpg arch=amd64] https://dcm.dev/debian stable main' | sudo tee /etc/apt/sources.list.d/dart_stable.list sudo apt-get update - sudo apt-get install dcm=1.38.1-1 # To avoid errors add `-1` (build number) to the version + sudo apt-get install dcm=1.38.3-1 # To avoid errors add `-1` (build number) to the version sudo chmod +x /usr/bin/dcm echo "$(dcm --version)" - name: Setup Dart SDK From bfc53bdd9dc220b3a3a2deb284ebc4ee2d299044 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 28 Jul 2026 10:56:15 -0700 Subject: [PATCH 07/17] fix inspector golden --- .../custom_widgets/lib/src/widgets.dart | 23 ++++++++++++++++--- .../inspector_service_node_summary.txt | 15 ++++++------ .../inspector_service_tree_summary.txt | 15 ++++++------ 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/packages/devtools_app/test/test_infra/fixtures/custom_widgets/lib/src/widgets.dart b/packages/devtools_app/test/test_infra/fixtures/custom_widgets/lib/src/widgets.dart index 4084be21830..683cf865aab 100644 --- a/packages/devtools_app/test/test_infra/fixtures/custom_widgets/lib/src/widgets.dart +++ b/packages/devtools_app/test/test_infra/fixtures/custom_widgets/lib/src/widgets.dart @@ -65,9 +65,26 @@ class CustomContainer extends StatelessWidget { } } -class CustomCenter extends Align { - const CustomCenter( - {super.key, super.widthFactor, super.heightFactor, super.child}); +class CustomCenter extends StatelessWidget { + const CustomCenter({ + super.key, + this.widthFactor, + this.heightFactor, + this.child, + }); + + final double? widthFactor; + final double? heightFactor; + final Widget? child; + + @override + Widget build(BuildContext context) { + return Align( + widthFactor: widthFactor, + heightFactor: heightFactor, + child: child, + ); + } } class CustomText extends StatelessWidget { diff --git a/packages/devtools_app/test/test_infra/goldens/inspector_service_node_summary.txt b/packages/devtools_app/test/test_infra/goldens/inspector_service_node_summary.txt index 59ed4f8aa6c..77cb6b9b1db 100644 --- a/packages/devtools_app/test/test_infra/goldens/inspector_service_node_summary.txt +++ b/packages/devtools_app/test/test_infra/goldens/inspector_service_node_summary.txt @@ -6,10 +6,11 @@ CustomApp └─Padding └─Container └─CustomCenter - └─CustomButton - └─GestureDetector - └─CustomContainer - └─Padding - └─Container - └─CustomText - └─Text + └─Align + └─CustomButton + └─GestureDetector + └─CustomContainer + └─Padding + └─Container + └─CustomText + └─Text diff --git a/packages/devtools_app/test/test_infra/goldens/inspector_service_tree_summary.txt b/packages/devtools_app/test/test_infra/goldens/inspector_service_tree_summary.txt index 3661c01fad0..6a7e081702c 100644 --- a/packages/devtools_app/test/test_infra/goldens/inspector_service_tree_summary.txt +++ b/packages/devtools_app/test/test_infra/goldens/inspector_service_tree_summary.txt @@ -7,10 +7,11 @@ └─Padding └─Container └─CustomCenter - └─CustomButton - └─GestureDetector - └─CustomContainer - └─Padding - └─Container - └─CustomText - └─Text + └─Align + └─CustomButton + └─GestureDetector + └─CustomContainer + └─Padding + └─Container + └─CustomText + └─Text From 098e9e8e3bcf36bb8e29a690dbad1d33f70ffc4a Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 28 Jul 2026 12:59:57 -0700 Subject: [PATCH 08/17] fix test flakes --- .../cpu_profile_benchmark_test.dart | 2 +- .../inspector/inspector_integration_test.dart | 31 ++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/devtools_app/test/screens/cpu_profiler/cpu_profile_benchmark_test.dart b/packages/devtools_app/test/screens/cpu_profiler/cpu_profile_benchmark_test.dart index 59ed603ebe7..b4e7d430269 100644 --- a/packages/devtools_app/test/screens/cpu_profiler/cpu_profile_benchmark_test.dart +++ b/packages/devtools_app/test/screens/cpu_profiler/cpu_profile_benchmark_test.dart @@ -35,7 +35,7 @@ void main() { final score = await benchmark.measure(); expect( score, - lessThan(110000), + lessThan(120000), reason: 'Exceeded benchmark for run $i: $score', ); } diff --git a/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart b/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart index 946a6665bf5..66ab7348869 100644 --- a/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart +++ b/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart @@ -31,14 +31,39 @@ import '../../test_infra/matchers/matchers.dart'; // reduced to under 1 second without introducing flakes. const inspectorChangeSettleTime = Duration(seconds: 2); +void _copyDirectorySync(Directory source, Directory destination) { + if (!destination.existsSync()) { + destination.createSync(recursive: true); + } + for (final entity in source.listSync(recursive: false)) { + final newPath = p.join(destination.path, p.basename(entity.path)); + if (entity is Directory) { + _copyDirectorySync(entity, Directory(newPath)); + } else if (entity is File) { + entity.copySync(newPath); + } + } +} + void main() { // We need to use real async in this test so we need to use this binding. initializeLiveTestWidgetsFlutterBindingWithAssets(); const windowSize = Size(2600.0, 1200.0); + // We copy the fixture app to a temporary directory because the + // auto-refresh tests modify lib/main.dart in-place. If this used the shared + // 'inspector_app' fixture, it could cause flaky test failures in other tests + // (like inspector_service_test.dart) that run in parallel. + final tempAppDir = + 'test/test_infra/fixtures/inspector_app_temp_${DateTime.now().millisecondsSinceEpoch}'; + _copyDirectorySync( + Directory('test/test_infra/fixtures/inspector_app'), + Directory(tempAppDir), + ); + final env = FlutterTestEnvironment( const FlutterRunConfiguration(withDebugger: true), - testAppDirectory: 'test/test_infra/fixtures/inspector_app', + testAppDirectory: tempAppDir, ); env.afterEverySetup = () async { @@ -67,6 +92,10 @@ void main() { tearDownAll(() { env.finalTeardown(); + final dir = Directory(tempAppDir); + if (dir.existsSync()) { + dir.deleteSync(recursive: true); + } }); group('screenshot tests', () { From 53802b77baecd6a123d8ebaeb90531313b934b78 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 28 Jul 2026 15:32:15 -0700 Subject: [PATCH 09/17] fixes and update flutter --- flutter-candidate.txt | 2 +- .../test/shared/primitives/utils_test.dart | 132 ------------------ .../custom_widgets/lib/src/widgets.dart | 23 +-- .../inspector_service_node_summary.txt | 15 +- .../inspector_service_tree_summary.txt | 15 +- 5 files changed, 18 insertions(+), 169 deletions(-) diff --git a/flutter-candidate.txt b/flutter-candidate.txt index 5900694a6d8..f094eb2ae96 100644 --- a/flutter-candidate.txt +++ b/flutter-candidate.txt @@ -1 +1 @@ -ad80825c24d770a19e33f67800fc0338a3b89ec7 +0f0246377b1c9d8bc365a439c520a7de6c3f590b diff --git a/packages/devtools_app/test/shared/primitives/utils_test.dart b/packages/devtools_app/test/shared/primitives/utils_test.dart index 941165d0443..f71c0cae441 100644 --- a/packages/devtools_app/test/shared/primitives/utils_test.dart +++ b/packages/devtools_app/test/shared/primitives/utils_test.dart @@ -704,135 +704,3 @@ class _SubtractionResult { @override String toString() => '$from - $subtract'; } - -// This was generated from a canvas with font size 14.0. -const asciiMeasurements = [ - 0, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 0, - 3.8896484375, - 3.8896484375, - 3.8896484375, - 3.8896484375, - 3.8896484375, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 4.6619873046875, - 0, - 4.6619873046875, - 4.6619873046875, - 3.8896484375, - 3.8896484375, - 4.9697265625, - 7.7861328125, - 7.7861328125, - 12.4482421875, - 9.337890625, - 2.6728515625, - 4.662109375, - 4.662109375, - 5.4482421875, - 8.17578125, - 3.8896484375, - 4.662109375, - 3.8896484375, - 3.8896484375, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 3.8896484375, - 3.8896484375, - 8.17578125, - 8.17578125, - 8.17578125, - 7.7861328125, - 14.2119140625, - 9.337890625, - 9.337890625, - 10.1103515625, - 10.1103515625, - 9.337890625, - 8.5517578125, - 10.8896484375, - 10.1103515625, - 3.8896484375, - 7, - 9.337890625, - 7.7861328125, - 11.662109375, - 10.1103515625, - 10.8896484375, - 9.337890625, - 10.8896484375, - 10.1103515625, - 9.337890625, - 8.5517578125, - 10.1103515625, - 9.337890625, - 13.2138671875, - 9.337890625, - 9.337890625, - 8.5517578125, - 3.8896484375, - 3.8896484375, - 3.8896484375, - 6.5693359375, - 7.7861328125, - 4.662109375, - 7.7861328125, - 7.7861328125, - 7, - 7.7861328125, - 7.7861328125, - 3.8896484375, - 7.7861328125, - 7.7861328125, - 3.1103515625, - 3.1103515625, - 7, - 3.1103515625, - 11.662109375, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 7.7861328125, - 4.662109375, - 7, - 3.8896484375, - 7.7861328125, - 7, - 10.1103515625, - 7, - 7, - 7, - 4.67578125, - 3.63671875, - 4.67578125, - 8.17578125, - 0, -]; diff --git a/packages/devtools_app/test/test_infra/fixtures/custom_widgets/lib/src/widgets.dart b/packages/devtools_app/test/test_infra/fixtures/custom_widgets/lib/src/widgets.dart index 683cf865aab..4084be21830 100644 --- a/packages/devtools_app/test/test_infra/fixtures/custom_widgets/lib/src/widgets.dart +++ b/packages/devtools_app/test/test_infra/fixtures/custom_widgets/lib/src/widgets.dart @@ -65,26 +65,9 @@ class CustomContainer extends StatelessWidget { } } -class CustomCenter extends StatelessWidget { - const CustomCenter({ - super.key, - this.widthFactor, - this.heightFactor, - this.child, - }); - - final double? widthFactor; - final double? heightFactor; - final Widget? child; - - @override - Widget build(BuildContext context) { - return Align( - widthFactor: widthFactor, - heightFactor: heightFactor, - child: child, - ); - } +class CustomCenter extends Align { + const CustomCenter( + {super.key, super.widthFactor, super.heightFactor, super.child}); } class CustomText extends StatelessWidget { diff --git a/packages/devtools_app/test/test_infra/goldens/inspector_service_node_summary.txt b/packages/devtools_app/test/test_infra/goldens/inspector_service_node_summary.txt index 77cb6b9b1db..59ed4f8aa6c 100644 --- a/packages/devtools_app/test/test_infra/goldens/inspector_service_node_summary.txt +++ b/packages/devtools_app/test/test_infra/goldens/inspector_service_node_summary.txt @@ -6,11 +6,10 @@ CustomApp └─Padding └─Container └─CustomCenter - └─Align - └─CustomButton - └─GestureDetector - └─CustomContainer - └─Padding - └─Container - └─CustomText - └─Text + └─CustomButton + └─GestureDetector + └─CustomContainer + └─Padding + └─Container + └─CustomText + └─Text diff --git a/packages/devtools_app/test/test_infra/goldens/inspector_service_tree_summary.txt b/packages/devtools_app/test/test_infra/goldens/inspector_service_tree_summary.txt index 6a7e081702c..3661c01fad0 100644 --- a/packages/devtools_app/test/test_infra/goldens/inspector_service_tree_summary.txt +++ b/packages/devtools_app/test/test_infra/goldens/inspector_service_tree_summary.txt @@ -7,11 +7,10 @@ └─Padding └─Container └─CustomCenter - └─Align - └─CustomButton - └─GestureDetector - └─CustomContainer - └─Padding - └─Container - └─CustomText - └─Text + └─CustomButton + └─GestureDetector + └─CustomContainer + └─Padding + └─Container + └─CustomText + └─Text From a2960fb4d60fc17277fce36cb814122f83ba0d52 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 28 Jul 2026 15:45:43 -0700 Subject: [PATCH 10/17] remove redundant argument --- .../test/screens/inspector/inspector_integration_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart b/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart index 66ab7348869..970108a134b 100644 --- a/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart +++ b/packages/devtools_app/test/screens/inspector/inspector_integration_test.dart @@ -35,7 +35,7 @@ void _copyDirectorySync(Directory source, Directory destination) { if (!destination.existsSync()) { destination.createSync(recursive: true); } - for (final entity in source.listSync(recursive: false)) { + for (final entity in source.listSync()) { final newPath = p.join(destination.path, p.basename(entity.path)); if (entity is Directory) { _copyDirectorySync(entity, Directory(newPath)); From 09037979b5e527eaf5e41013d66e7c13664e96ae Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 28 Jul 2026 17:09:19 -0700 Subject: [PATCH 11/17] try to fix test timeout --- .../test/server/general_api_test.dart | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/packages/devtools_shared/test/server/general_api_test.dart b/packages/devtools_shared/test/server/general_api_test.dart index c2bb0002803..8fc848dd404 100644 --- a/packages/devtools_shared/test/server/general_api_test.dart +++ b/packages/devtools_shared/test/server/general_api_test.dart @@ -157,8 +157,6 @@ void main() { setUp(() async { app = TestDartApp(); vmServiceUriString = await app!.start(); - // Await a short delay to give the VM a chance to initialize. - await delay(duration: const Duration(milliseconds: 2500)); expect(vmServiceUriString, isNotEmpty); }); @@ -171,13 +169,21 @@ void main() { test('succeeds for a connect event', () async { final vmServiceUri = normalizeVmServiceUri(vmServiceUriString!); expect(vmServiceUri, isNotNull); - final response = - await server.VmServiceHandler.detectRootPackageForVmService( - vmServiceUriAsString: vmServiceUriString!, - vmServiceUri: vmServiceUri!, - connected: true, - dtd: testDtdConnection!, - ); + late server.DetectRootPackageResponse response; + await runWithRetry( + callback: () async { + response = + await server.VmServiceHandler.detectRootPackageForVmService( + vmServiceUriAsString: vmServiceUriString!, + vmServiceUri: vmServiceUri!, + connected: true, + dtd: testDtdConnection!, + ); + if (!response.success) throw Exception('VM not ready'); + }, + maxRetries: 20, + retryDelay: const Duration(milliseconds: 500), + ); expect(response.success, true); expect(response.message, isNull); expect(response.uri, isNotNull); @@ -200,13 +206,21 @@ void main() { () async { final vmServiceUri = normalizeVmServiceUri(vmServiceUriString!); expect(vmServiceUri, isNotNull); - final response = - await server.VmServiceHandler.detectRootPackageForVmService( - vmServiceUriAsString: vmServiceUriString!, - vmServiceUri: vmServiceUri!, - connected: true, - dtd: testDtdConnection!, - ); + late server.DetectRootPackageResponse response; + await runWithRetry( + callback: () async { + response = + await server.VmServiceHandler.detectRootPackageForVmService( + vmServiceUriAsString: vmServiceUriString!, + vmServiceUri: vmServiceUri!, + connected: true, + dtd: testDtdConnection!, + ); + if (!response.success) throw Exception('VM not ready'); + }, + maxRetries: 20, + retryDelay: const Duration(milliseconds: 500), + ); expect(response.success, true); expect(response.message, isNull); expect(response.uri, isNotNull); @@ -215,7 +229,7 @@ void main() { final disconnectResponse = await server.VmServiceHandler.detectRootPackageForVmService( vmServiceUriAsString: vmServiceUriString!, - vmServiceUri: vmServiceUri, + vmServiceUri: vmServiceUri!, connected: false, dtd: testDtdConnection!, ); From 33b17f2d750f32bf582918b564b0d8b580b275dc Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Jul 2026 09:13:06 -0700 Subject: [PATCH 12/17] remove unused import --- packages/devtools_shared/test/server/general_api_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/devtools_shared/test/server/general_api_test.dart b/packages/devtools_shared/test/server/general_api_test.dart index 8fc848dd404..1c57223d7ae 100644 --- a/packages/devtools_shared/test/server/general_api_test.dart +++ b/packages/devtools_shared/test/server/general_api_test.dart @@ -6,7 +6,6 @@ import 'dart:io'; import 'package:devtools_shared/devtools_server.dart'; import 'package:devtools_shared/devtools_shared.dart'; -import 'package:devtools_shared/devtools_test_utils.dart'; import 'package:devtools_shared/src/extensions/extension_manager.dart'; import 'package:devtools_shared/src/server/server_api.dart' as server; import 'package:dtd/dtd.dart'; From 284afc2af1d121892fb34e7b7769a6463ac5de93 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Jul 2026 11:10:34 -0700 Subject: [PATCH 13/17] add timestamp to test app --- packages/devtools_shared/test/helpers/helpers.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/devtools_shared/test/helpers/helpers.dart b/packages/devtools_shared/test/helpers/helpers.dart index 3f174aae7a1..349ccdba328 100644 --- a/packages/devtools_shared/test/helpers/helpers.dart +++ b/packages/devtools_shared/test/helpers/helpers.dart @@ -62,11 +62,16 @@ Future startDtd() async { } class TestDartApp { + TestDartApp() { + directory = Directory( + 'tmp/test_app_${DateTime.now().millisecondsSinceEpoch}', + ); + } static final dartVMServiceRegExp = RegExp( r'The Dart VM service is listening on (http://127.0.0.1:.*)', ); - final directory = Directory('tmp/test_app'); + late final Directory directory; Process? process; @@ -74,7 +79,6 @@ class TestDartApp { await _initTestApp(); process = await Process.start(Platform.resolvedExecutable, [ '--observe=0', - 'run', 'bin/main.dart', ], workingDirectory: directory.path); From c9f57b8046e71014b9ad695e186b60123287a4d7 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Jul 2026 13:09:18 -0700 Subject: [PATCH 14/17] try creating dart_tool for windows --- packages/devtools_shared/test/helpers/helpers.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/devtools_shared/test/helpers/helpers.dart b/packages/devtools_shared/test/helpers/helpers.dart index 349ccdba328..58a5caa554f 100644 --- a/packages/devtools_shared/test/helpers/helpers.dart +++ b/packages/devtools_shared/test/helpers/helpers.dart @@ -114,6 +114,7 @@ class TestDartApp { Future _initTestApp() async { await deleteDirectoryWithRetry(directory); directory.createSync(recursive: true); + Directory(path.join(directory.path, '.dart_tool')).createSync(); final mainFile = File(path.join(directory.path, 'bin', 'main.dart')) ..createSync(recursive: true); From cb07f45d9e26bef25cda611e17546b2a6c51eba7 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Jul 2026 13:23:37 -0700 Subject: [PATCH 15/17] fix github actions scan failures --- .github/workflows/build.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5386271c604..5f94a514ff7 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -11,7 +11,8 @@ on: - master # Declare default permissions as read only. -permissions: read-all +permissions: + contents: read defaults: run: @@ -190,7 +191,7 @@ jobs: run: ./tool/ci/bots.sh - name: Upload Golden Failure Artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a if: failure() with: name: golden_image_failures.${{ matrix.bot }} @@ -263,7 +264,7 @@ jobs: run: ./tool/ci/bots.sh - name: Upload Golden Failure Artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a if: failure() with: name: golden_image_failures.${{ matrix.bot }} From 4ae7d4988f2016aeee47eb7c02d566c781cd6f70 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Jul 2026 13:37:17 -0700 Subject: [PATCH 16/17] keep listeners alive until process is killed --- .../devtools_shared/test/helpers/helpers.dart | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/devtools_shared/test/helpers/helpers.dart b/packages/devtools_shared/test/helpers/helpers.dart index 58a5caa554f..b5ac767e735 100644 --- a/packages/devtools_shared/test/helpers/helpers.dart +++ b/packages/devtools_shared/test/helpers/helpers.dart @@ -74,6 +74,8 @@ class TestDartApp { late final Directory directory; Process? process; + StreamSubscription? _stdoutSub; + StreamSubscription? _stderrSub; Future start() async { await _initTestApp(); @@ -83,28 +85,36 @@ class TestDartApp { ], workingDirectory: directory.path); final serviceUriCompleter = Completer(); - late StreamSubscription sub; - sub = process!.stdout + _stdoutSub = process!.stdout .transform(utf8.decoder) .transform(const LineSplitter()) - .listen((line) async { - if (line.contains(dartVMServiceRegExp)) { - await sub.cancel(); + .listen((line) { + if (!serviceUriCompleter.isCompleted && line.contains(dartVMServiceRegExp)) { serviceUriCompleter.complete( dartVMServiceRegExp.firstMatch(line)!.group(1), ); } }); + + _stderrSub = process!.stderr + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen((line) { + // ignore: avoid_print, deliberate print to monitor errors. + print('TestDartApp stderr: $line'); + }); + return await serviceUriCompleter.future.timeout( const Duration(seconds: 5), - onTimeout: () async { - await sub.cancel(); + onTimeout: () { return ''; }, ); } Future kill() async { + await _stdoutSub?.cancel(); + await _stderrSub?.cancel(); process?.kill(); await process?.exitCode; process = null; From 809a23346b6a0dcf05d6d2b12a3894aff788fa6c Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Jul 2026 13:52:11 -0700 Subject: [PATCH 17/17] formatting --- packages/devtools_shared/test/helpers/helpers.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/devtools_shared/test/helpers/helpers.dart b/packages/devtools_shared/test/helpers/helpers.dart index b5ac767e735..8c03895945d 100644 --- a/packages/devtools_shared/test/helpers/helpers.dart +++ b/packages/devtools_shared/test/helpers/helpers.dart @@ -89,19 +89,20 @@ class TestDartApp { .transform(utf8.decoder) .transform(const LineSplitter()) .listen((line) { - if (!serviceUriCompleter.isCompleted && line.contains(dartVMServiceRegExp)) { + if (!serviceUriCompleter.isCompleted && + line.contains(dartVMServiceRegExp)) { serviceUriCompleter.complete( dartVMServiceRegExp.firstMatch(line)!.group(1), ); } }); - + _stderrSub = process!.stderr .transform(utf8.decoder) .transform(const LineSplitter()) .listen((line) { - // ignore: avoid_print, deliberate print to monitor errors. - print('TestDartApp stderr: $line'); + // ignore: avoid_print, deliberate print to monitor errors. + print('TestDartApp stderr: $line'); }); return await serviceUriCompleter.future.timeout(