blob: 5f0fc92d8c63ea1af1ff25a749eeb0dbd78d9d2d [file] [log] [blame]
// Copyright 2019 The Chromium 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:devtools_app/src/charts/flame_chart.dart';
import 'package:devtools_app/src/common_widgets.dart';
import 'package:devtools_app/src/globals.dart';
import 'package:devtools_app/src/profiler/cpu_profile_bottom_up.dart';
import 'package:devtools_app/src/profiler/cpu_profile_call_tree.dart';
import 'package:devtools_app/src/profiler/cpu_profile_controller.dart';
import 'package:devtools_app/src/profiler/cpu_profile_flame_chart.dart';
import 'package:devtools_app/src/profiler/cpu_profile_model.dart';
import 'package:devtools_app/src/profiler/cpu_profile_transformer.dart';
import 'package:devtools_app/src/profiler/cpu_profiler.dart';
import 'package:devtools_app/src/profiler/profiler_screen.dart';
import 'package:devtools_app/src/profiler/profiler_screen_controller.dart';
import 'package:devtools_app/src/service_manager.dart';
import 'package:devtools_testing/support/cpu_profile_test_data.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'support/mocks.dart';
import 'support/wrappers.dart';
void main() {
CpuProfiler cpuProfiler;
CpuProfileData cpuProfileData;
CpuProfilerController controller;
setUp(() async {
final transformer = CpuProfileTransformer();
controller = CpuProfilerController();
cpuProfileData = CpuProfileData.parse(goldenCpuProfileDataJson);
await transformer.processData(cpuProfileData);
setGlobal(ServiceConnectionManager, FakeServiceManager());
});
group('CpuProfiler', () {
const windowSize = Size(2000.0, 1000.0);
final searchFieldKey = GlobalKey(debugLabel: 'test search field key');
testWidgetsWithWindowSize('builds for null cpuProfileData', windowSize,
(WidgetTester tester) async {
cpuProfiler = CpuProfiler(
data: null,
controller: controller,
searchFieldKey: searchFieldKey,
);
await tester.pumpWidget(wrap(cpuProfiler));
expect(find.byType(TabBar), findsOneWidget);
expect(find.text(CpuProfiler.emptyCpuProfile), findsNothing);
expect(find.byKey(CpuProfiler.dataProcessingKey), findsOneWidget);
expect(find.byType(CpuProfileFlameChart), findsNothing);
expect(find.byType(CpuCallTreeTable), findsNothing);
expect(find.byType(CpuBottomUpTable), findsNothing);
expect(find.byType(UserTagDropdown), findsNothing);
expect(find.byType(ExpandAllButton), findsNothing);
expect(find.byType(CollapseAllButton), findsNothing);
expect(find.byType(FlameChartHelpButton), findsNothing);
expect(find.byKey(searchFieldKey), findsNothing);
});
testWidgetsWithWindowSize('builds for empty cpuProfileData', windowSize,
(WidgetTester tester) async {
cpuProfileData = CpuProfileData.parse(emptyCpuProfileDataJson);
cpuProfiler = CpuProfiler(
data: cpuProfileData,
controller: controller,
searchFieldKey: searchFieldKey,
);
await tester.pumpWidget(wrap(cpuProfiler));
expect(find.byType(TabBar), findsOneWidget);
expect(find.text(CpuProfiler.emptyCpuProfile), findsOneWidget);
expect(find.byKey(CpuProfiler.dataProcessingKey), findsNothing);
expect(find.byType(CpuProfileFlameChart), findsNothing);
expect(find.byType(CpuCallTreeTable), findsNothing);
expect(find.byType(CpuBottomUpTable), findsNothing);
expect(find.byType(UserTagDropdown), findsNothing);
expect(find.byType(ExpandAllButton), findsNothing);
expect(find.byType(CollapseAllButton), findsNothing);
expect(find.byType(FlameChartHelpButton), findsNothing);
expect(find.byKey(searchFieldKey), findsNothing);
});
testWidgetsWithWindowSize('builds for valid cpuProfileData', windowSize,
(WidgetTester tester) async {
cpuProfiler = CpuProfiler(
data: cpuProfileData,
controller: controller,
searchFieldKey: searchFieldKey,
);
await tester.pumpWidget(wrap(cpuProfiler));
expect(find.byType(TabBar), findsOneWidget);
expect(find.text(CpuProfiler.emptyCpuProfile), findsNothing);
expect(find.byKey(CpuProfiler.dataProcessingKey), findsNothing);
expect(find.byType(CpuBottomUpTable), findsOneWidget);
expect(find.byType(UserTagDropdown), findsOneWidget);
expect(find.byType(ExpandAllButton), findsOneWidget);
expect(find.byType(CollapseAllButton), findsOneWidget);
expect(find.byType(FlameChartHelpButton), findsNothing);
expect(find.byKey(searchFieldKey), findsNothing);
});
testWidgetsWithWindowSize('switches tabs', windowSize,
(WidgetTester tester) async {
cpuProfiler = CpuProfiler(
data: cpuProfileData,
controller: controller,
searchFieldKey: searchFieldKey,
);
await tester.pumpWidget(wrap(cpuProfiler));
expect(find.byType(TabBar), findsOneWidget);
expect(find.text(CpuProfiler.emptyCpuProfile), findsNothing);
expect(find.byKey(CpuProfiler.dataProcessingKey), findsNothing);
expect(find.byType(CpuProfileFlameChart), findsNothing);
expect(find.byType(CpuCallTreeTable), findsNothing);
expect(find.byType(CpuBottomUpTable), findsOneWidget);
expect(find.byType(ExpandAllButton), findsOneWidget);
expect(find.byType(CollapseAllButton), findsOneWidget);
expect(find.byType(FlameChartHelpButton), findsNothing);
expect(find.byKey(searchFieldKey), findsNothing);
await tester.tap(find.text('Call Tree'));
await tester.pumpAndSettle();
expect(find.byType(CpuProfileFlameChart), findsNothing);
expect(find.byType(CpuCallTreeTable), findsOneWidget);
expect(find.byType(CpuBottomUpTable), findsNothing);
expect(find.byType(UserTagDropdown), findsOneWidget);
expect(find.byType(ExpandAllButton), findsOneWidget);
expect(find.byType(CollapseAllButton), findsOneWidget);
expect(find.byType(FlameChartHelpButton), findsNothing);
expect(find.byKey(searchFieldKey), findsNothing);
await tester.tap(find.text('CPU Flame Chart'));
await tester.pumpAndSettle();
expect(find.byType(CpuProfileFlameChart), findsOneWidget);
expect(find.byType(CpuCallTreeTable), findsNothing);
expect(find.byType(CpuBottomUpTable), findsNothing);
expect(find.byType(UserTagDropdown), findsOneWidget);
expect(find.byType(ExpandAllButton), findsNothing);
expect(find.byType(CollapseAllButton), findsNothing);
expect(find.byType(FlameChartHelpButton), findsOneWidget);
expect(find.byKey(searchFieldKey), findsOneWidget);
});
testWidgetsWithWindowSize(
'does not include search field without search field key', windowSize,
(WidgetTester tester) async {
cpuProfiler = CpuProfiler(
data: cpuProfileData,
controller: controller,
// No search field key.
// searchFieldKey: searchFieldKey,
);
await tester.pumpWidget(wrap(cpuProfiler));
await tester.pumpAndSettle();
await tester.tap(find.text('CPU Flame Chart'));
await tester.pumpAndSettle();
expect(find.byType(CpuProfileFlameChart), findsOneWidget);
expect(find.byType(CpuCallTreeTable), findsNothing);
expect(find.byType(CpuBottomUpTable), findsNothing);
expect(find.byType(UserTagDropdown), findsOneWidget);
expect(find.byType(ExpandAllButton), findsNothing);
expect(find.byType(CollapseAllButton), findsNothing);
expect(find.byType(FlameChartHelpButton), findsOneWidget);
expect(find.byKey(searchFieldKey), findsNothing);
});
testWidgetsWithWindowSize('can expand and collapse data', windowSize,
(WidgetTester tester) async {
cpuProfiler = CpuProfiler(
data: cpuProfileData,
controller: controller,
searchFieldKey: searchFieldKey,
);
await tester.pumpWidget(wrap(cpuProfiler));
await tester.tap(find.text('Call Tree'));
await tester.pumpAndSettle();
expect(cpuProfileData.cpuProfileRoot.isExpanded, isFalse);
await tester.tap(find.byType(ExpandAllButton));
expect(cpuProfiler.callTreeRoots.first.isExpanded, isTrue);
await tester.tap(find.byType(CollapseAllButton));
expect(cpuProfiler.callTreeRoots.first.isExpanded, isFalse);
await tester.tap(find.text('Bottom Up'));
await tester.pumpAndSettle();
for (final root in cpuProfiler.bottomUpRoots) {
expect(root.isExpanded, isFalse);
}
await tester.tap(find.byType(ExpandAllButton));
for (final root in cpuProfiler.bottomUpRoots) {
expect(root.isExpanded, isTrue);
}
await tester.tap(find.byType(CollapseAllButton));
for (final root in cpuProfiler.bottomUpRoots) {
expect(root.isExpanded, isFalse);
}
});
group('UserTag filters', () {
ProfilerScreenController controller;
setUp(() async {
controller = ProfilerScreenController();
cpuProfileData = CpuProfileData.parse(cpuProfileDataWithUserTagsJson);
await controller.cpuProfilerController.transformer
.processData(cpuProfileData);
// Call this to force the value of `_dataByTag[userTagNone]` to be set.
controller.cpuProfilerController.loadProcessedData(cpuProfileData);
});
testWidgetsWithWindowSize('can filter data by user tag', windowSize,
(WidgetTester tester) async {
// We need to pump the entire `ProfilerScreenBody` widget because the
// CpuProfiler widget has `cpuProfileData` passed in from there, and
// CpuProfiler needs to be rebuilt on data updates.
await tester.pumpWidget(wrapWithControllers(
const ProfilerScreenBody(),
profiler: controller,
));
expect(controller.cpuProfilerController.userTags.length, equals(3));
expect(find.byType(UserTagDropdown), findsOneWidget);
// There is a Text widget and a RichText widget.
expect(find.text('Filter by tag: userTagA'), findsWidgets);
expect(find.text('Filter by tag: userTagB'), findsWidgets);
expect(find.text('Filter by tag: userTagC'), findsWidgets);
await tester.tap(find.text('CPU Flame Chart'));
await tester.pumpAndSettle();
expect(find.byType(CpuProfileFlameChart), findsOneWidget);
expect(
controller
.cpuProfileData.profileMetaData.time.duration.inMicroseconds,
equals(250),
);
expect(find.text('Frame1'), findsOneWidget);
expect(find.text('Frame2'), findsOneWidget);
expect(find.text('Frame3'), findsOneWidget);
expect(find.text('Frame4'), findsOneWidget);
expect(find.text('Frame5'), findsOneWidget);
expect(find.text('Frame6'), findsOneWidget);
await tester.tap(find.byType(UserTagDropdown));
await tester.pumpAndSettle();
await tester.tap(find.text('Filter by tag: userTagA').last);
await tester.pumpAndSettle();
expect(
controller
.cpuProfileData.profileMetaData.time.duration.inMicroseconds,
equals(100),
);
expect(find.text('Frame1'), findsOneWidget);
expect(find.text('Frame2'), findsOneWidget);
expect(find.text('Frame3'), findsOneWidget);
expect(find.text('Frame4'), findsNothing);
expect(find.text('Frame5'), findsOneWidget);
expect(find.text('Frame6'), findsNothing);
await tester.tap(find.byType(UserTagDropdown));
await tester.pumpAndSettle();
await tester.tap(find.text('Filter by tag: userTagB').last);
await tester.pumpAndSettle();
expect(
controller
.cpuProfileData.profileMetaData.time.duration.inMicroseconds,
equals(50),
);
expect(find.text('Frame1'), findsOneWidget);
expect(find.text('Frame2'), findsOneWidget);
expect(find.text('Frame3'), findsNothing);
expect(find.text('Frame4'), findsOneWidget);
expect(find.text('Frame5'), findsNothing);
expect(find.text('Frame6'), findsNothing);
await tester.tap(find.byType(UserTagDropdown));
await tester.pumpAndSettle();
await tester.tap(find.text('Filter by tag: userTagC').last);
await tester.pumpAndSettle();
expect(
controller
.cpuProfileData.profileMetaData.time.duration.inMicroseconds,
equals(100),
);
expect(find.text('Frame1'), findsOneWidget);
expect(find.text('Frame2'), findsNothing);
expect(find.text('Frame3'), findsNothing);
expect(find.text('Frame4'), findsNothing);
expect(find.text('Frame5'), findsOneWidget);
expect(find.text('Frame6'), findsOneWidget);
});
});
});
}