| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| // IMPORTANT: keep this in sync with the same constant defined |
| // in foundation/timeline.dart |
| const int kSliceSize = 500; |
| |
| void main() { |
| setUp(() { |
| FlutterTimeline.debugReset(); |
| FlutterTimeline.debugCollectionEnabled = false; |
| }); |
| |
| test('Does not collect when collection not enabled', () { |
| FlutterTimeline.startSync('TEST'); |
| FlutterTimeline.finishSync(); |
| expect( |
| () => FlutterTimeline.debugCollect(), |
| throwsStateError, |
| ); |
| }); |
| |
| test('Collects when collection is enabled', () { |
| FlutterTimeline.debugCollectionEnabled = true; |
| FlutterTimeline.startSync('TEST'); |
| FlutterTimeline.finishSync(); |
| final AggregatedTimings data = FlutterTimeline.debugCollect(); |
| expect(data.timedBlocks, hasLength(1)); |
| expect(data.aggregatedBlocks, hasLength(1)); |
| |
| final AggregatedTimedBlock block = data.getAggregated('TEST'); |
| expect(block.name, 'TEST'); |
| expect(block.count, 1); |
| |
| // After collection the timeline is reset back to empty. |
| final AggregatedTimings data2 = FlutterTimeline.debugCollect(); |
| expect(data2.timedBlocks, isEmpty); |
| expect(data2.aggregatedBlocks, isEmpty); |
| }); |
| |
| test('Deletes old data when reset', () { |
| FlutterTimeline.debugCollectionEnabled = true; |
| FlutterTimeline.startSync('TEST'); |
| FlutterTimeline.finishSync(); |
| FlutterTimeline.debugReset(); |
| |
| final AggregatedTimings data = FlutterTimeline.debugCollect(); |
| expect(data.timedBlocks, isEmpty); |
| expect(data.aggregatedBlocks, isEmpty); |
| }); |
| |
| test('Reports zero aggregation when requested missing block', () { |
| FlutterTimeline.debugCollectionEnabled = true; |
| |
| final AggregatedTimings data = FlutterTimeline.debugCollect(); |
| final AggregatedTimedBlock block = data.getAggregated('MISSING'); |
| expect(block.name, 'MISSING'); |
| expect(block.count, 0); |
| expect(block.duration, 0); |
| }); |
| |
| test('Measures the runtime of a function', () { |
| FlutterTimeline.debugCollectionEnabled = true; |
| |
| // The off-by-one values for `start` and `end` are for web's sake where |
| // timer values are reported as float64 and toInt/toDouble conversions |
| // are noops, so there's no value truncation happening, which makes it |
| // a bit inconsistent with Stopwatch. |
| final int start = FlutterTimeline.now - 1; |
| FlutterTimeline.timeSync('TEST', () { |
| final Stopwatch watch = Stopwatch()..start(); |
| while (watch.elapsedMilliseconds < 5) {} |
| watch.stop(); |
| }); |
| final int end = FlutterTimeline.now + 1; |
| |
| final AggregatedTimings data = FlutterTimeline.debugCollect(); |
| expect(data.timedBlocks, hasLength(1)); |
| expect(data.aggregatedBlocks, hasLength(1)); |
| |
| final TimedBlock block = data.timedBlocks.single; |
| expect(block.name, 'TEST'); |
| expect(block.start, greaterThanOrEqualTo(start)); |
| expect(block.end, lessThanOrEqualTo(end)); |
| expect(block.duration, greaterThan(0)); |
| |
| final AggregatedTimedBlock aggregated = data.getAggregated('TEST'); |
| expect(aggregated.name, 'TEST'); |
| expect(aggregated.count, 1); |
| expect(aggregated.duration, block.duration); |
| }); |
| |
| test('FlutterTimeline.instanceSync does not collect anything', () { |
| FlutterTimeline.debugCollectionEnabled = true; |
| FlutterTimeline.instantSync('TEST'); |
| |
| final AggregatedTimings data = FlutterTimeline.debugCollect(); |
| expect(data.timedBlocks, isEmpty); |
| expect(data.aggregatedBlocks, isEmpty); |
| }); |
| |
| test('FlutterTimeline.now returns a value', () { |
| FlutterTimeline.debugCollectionEnabled = true; |
| expect(FlutterTimeline.now, isNotNull); |
| }); |
| |
| test('Can collect more than one slice of data', () { |
| FlutterTimeline.debugCollectionEnabled = true; |
| |
| for (int i = 0; i < 10 * kSliceSize; i++) { |
| FlutterTimeline.startSync('TEST'); |
| FlutterTimeline.finishSync(); |
| } |
| final AggregatedTimings data = FlutterTimeline.debugCollect(); |
| expect(data.timedBlocks, hasLength(10 * kSliceSize)); |
| expect(data.aggregatedBlocks, hasLength(1)); |
| |
| final AggregatedTimedBlock block = data.getAggregated('TEST'); |
| expect(block.name, 'TEST'); |
| expect(block.count, 10 * kSliceSize); |
| }); |
| |
| test('Collects blocks in a correct order', () { |
| FlutterTimeline.debugCollectionEnabled = true; |
| const int testCount = 7 * kSliceSize ~/ 2; |
| |
| for (int i = 0; i < testCount; i++) { |
| FlutterTimeline.startSync('TEST$i'); |
| FlutterTimeline.finishSync(); |
| } |
| |
| final AggregatedTimings data = FlutterTimeline.debugCollect(); |
| expect(data.timedBlocks, hasLength(testCount)); |
| expect( |
| data.timedBlocks.map<String>((TimedBlock block) => block.name).toList(), |
| List<String>.generate(testCount, (int i) => 'TEST$i'), |
| ); |
| }); |
| } |