Skip to content

Commit

Permalink
Improve tracing (#93086)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hixie committed Dec 10, 2021
1 parent 14cf445 commit 840e109
Show file tree
Hide file tree
Showing 50 changed files with 1,166 additions and 133 deletions.
12 changes: 9 additions & 3 deletions .ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,9 @@ targets:
{"dependency": "goldctl"},
{"dependency": "clang"},
{"dependency": "cmake"},
{"dependency": "ninja"}
{"dependency": "ninja"},
{"dependency": "open_jdk"},
{"dependency": "android_sdk", "version": "version:29.0"}
]
shard: framework_tests
subshard: misc
Expand Down Expand Up @@ -2108,7 +2110,9 @@ targets:
[
{"dependency": "goldctl"},
{"dependency": "xcode"},
{"dependency": "gems"}
{"dependency": "gems"},
{"dependency": "open_jdk"},
{"dependency": "android_sdk", "version": "version:29.0"}
]
shard: framework_tests
subshard: misc
Expand Down Expand Up @@ -3642,7 +3646,9 @@ targets:
dependencies: >-
[
{"dependency": "goldctl"},
{"dependency": "vs_build", "version": "version:vs2019"}
{"dependency": "vs_build", "version": "version:vs2019"},
{"dependency": "open_jdk"},
{"dependency": "android_sdk", "version": "version:29.0"}
]
shard: framework_tests
subshard: misc
Expand Down
2 changes: 1 addition & 1 deletion dev/bots/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ dependencies:
platform: 3.1.0
process: 4.2.4
test: 1.19.5
archive: 3.1.6

_discoveryapis_commons: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
_fe_analyzer_shared: 31.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
analyzer: 2.8.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
archive: 3.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
async: 2.8.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
boolean_selector: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
charcode: 1.3.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
Expand Down
90 changes: 86 additions & 4 deletions dev/bots/test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;
import 'dart:typed_data';

import 'package:archive/archive.dart';
import 'package:file/file.dart' as fs;
import 'package:file/local.dart';
import 'package:path/path.dart' as path;
Expand Down Expand Up @@ -744,6 +746,89 @@ Future<void> _runFrameworkTests() async {
await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers'), options: soundNullSafetyOptions);
}

Future<void> runTracingTests() async {
final String tracingDirectory = path.join(flutterRoot, 'dev', 'tracing_tests');

// run the tests for debug mode
await _runFlutterTest(tracingDirectory, options: <String>['--enable-vmservice']);

Future<List<String>> verifyTracingAppBuild({
required String modeArgument,
required String sourceFile,
required Set<String> allowed,
required Set<String> disallowed,
}) async {
await runCommand(
flutter,
<String>[
'build', 'appbundle', '--$modeArgument', path.join('lib', sourceFile),
],
workingDirectory: tracingDirectory,
);
final Archive archive = ZipDecoder().decodeBytes(File(path.join(tracingDirectory, 'build', 'app', 'outputs', 'bundle', modeArgument, 'app-$modeArgument.aab')).readAsBytesSync());
final ArchiveFile libapp = archive.findFile('base/lib/arm64-v8a/libapp.so')!;
final Uint8List libappBytes = libapp.content as Uint8List; // bytes decompressed here
final String libappStrings = utf8.decode(libappBytes, allowMalformed: true);
await runCommand(flutter, <String>['clean'], workingDirectory: tracingDirectory);
final List<String> results = <String>[];
for (final String pattern in allowed) {
if (!libappStrings.contains(pattern)) {
results.add('When building with --$modeArgument, expected to find "$pattern" in libapp.so but could not find it.');
}
}
for (final String pattern in disallowed) {
if (libappStrings.contains(pattern)) {
results.add('When building with --$modeArgument, expected to not find "$pattern" in libapp.so but did find it.');
}
}
return results;
}

final List<String> results = <String>[];
results.addAll(await verifyTracingAppBuild(
modeArgument: 'profile',
sourceFile: 'control.dart', // this is the control, the other two below are the actual test
allowed: <String>{
'TIMELINE ARGUMENTS TEST CONTROL FILE',
'toTimelineArguments used in non-debug build', // we call toTimelineArguments directly to check the message does exist
},
disallowed: <String>{
'BUILT IN DEBUG MODE', 'BUILT IN RELEASE MODE',
},
));
results.addAll(await verifyTracingAppBuild(
modeArgument: 'profile',
sourceFile: 'test.dart',
allowed: <String>{
'BUILT IN PROFILE MODE', 'RenderTest.performResize called', // controls
'BUILD', 'LAYOUT', 'PAINT', // we output these to the timeline in profile builds
// (LAYOUT and PAINT also exist because of NEEDS-LAYOUT and NEEDS-PAINT in RenderObject.toStringShort)
},
disallowed: <String>{
'BUILT IN DEBUG MODE', 'BUILT IN RELEASE MODE',
'TestWidget.debugFillProperties called', 'RenderTest.debugFillProperties called', // debug only
'toTimelineArguments used in non-debug build', // entire function should get dropped by tree shaker
},
));
results.addAll(await verifyTracingAppBuild(
modeArgument: 'release',
sourceFile: 'test.dart',
allowed: <String>{
'BUILT IN RELEASE MODE', 'RenderTest.performResize called', // controls
},
disallowed: <String>{
'BUILT IN DEBUG MODE', 'BUILT IN PROFILE MODE',
'BUILD', 'LAYOUT', 'PAINT', // these are only used in Timeline.startSync calls that should not appear in release builds
'TestWidget.debugFillProperties called', 'RenderTest.debugFillProperties called', // debug only
'toTimelineArguments used in non-debug build', // not included in release builds
},
));
if (results.isNotEmpty) {
print(results.join('\n'));
exit(1);
}
}

Future<void> runFixTests() async {
final List<String> args = <String>[
'fix',
Expand Down Expand Up @@ -808,10 +893,7 @@ Future<void> _runFrameworkTests() async {
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'fuchsia_remote_debug_protocol'), options: soundNullSafetyOptions);
await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'non_nullable'), options: mixedModeNullSafetyOptions);
await _runFlutterTest(
path.join(flutterRoot, 'dev', 'tracing_tests'),
options: <String>['--enable-vmservice'],
);
await runTracingTests();
await runFixTests();
await runPrivateTests();
const String httpClientWarning =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,12 @@ class _VideoDemoState extends State<VideoDemo> with SingleTickerProviderStateMix
super.initState();

Future<void> initController(VideoPlayerController controller, String name) async {
print('> VideoDemo initController "$name" ${isDisposed ? "DISPOSED" : ""}');
controller.setLooping(true);
controller.setVolume(0.0);
controller.play();
await connectedCompleter.future;
await controller.initialize();
if (mounted) {
print('< VideoDemo initController "$name" done ${isDisposed ? "DISPOSED" : ""}');
setState(() { });
}
}
Expand All @@ -403,11 +401,9 @@ class _VideoDemoState extends State<VideoDemo> with SingleTickerProviderStateMix

@override
void dispose() {
print('> VideoDemo dispose');
isDisposed = true;
butterflyController.dispose();
beeController.dispose();
print('< VideoDemo dispose');
super.dispose();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

export 'package:flutter_goldens/flutter_goldens.dart' show testExecutable;
import 'dart:async';

import 'package:flutter/rendering.dart';
import 'package:flutter_goldens/flutter_goldens.dart' as flutter_goldens show testExecutable;
import 'package:flutter_test/flutter_test.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) {
// Enable extra checks since this package exercises a lot of the framework.
debugCheckIntrinsicSizes = true;

// Make tap() et al fail if the given finder specifies a widget that would not
// receive the event.
WidgetController.hitTestWarningShouldBeFatal = true;

// Enable golden file testing using Skia Gold.
return flutter_goldens.testExecutable(testMain);
}
2 changes: 1 addition & 1 deletion dev/integration_tests/flutter_gallery/test/smoke_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ Future<void> smokeOptionsPage(WidgetTester tester) async {
// Switch back to system theme setting: first menu button, choose 'System Default'
await tester.tap(find.byIcon(Icons.arrow_drop_down).first);
await tester.pumpAndSettle();
await tester.tap(find.text('System Default').at(1));
await tester.tap(find.text('System Default').at(1), warnIfMissed: false); // https://github.com/flutter/flutter/issues/82908
await tester.pumpAndSettle();

// Switch text direction: first switch
Expand Down
11 changes: 11 additions & 0 deletions dev/tracing_tests/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Tracing tests

## "Application"

The `lib/test.dart` and `lib/control.dart` files in this directory are
used by `dev/bots/test.dart`'s `runTracingTests` function to check
whether aspects of the tracing logic in the framework get compiled out
in profile and release builds. They're not meant to be run directly.

The strings in these files are used in `dev/bots/test.dart`.

## Tests

The tests in this folder must be run with `flutter test --enable-vmservice`,
since they test that trace data is written to the timeline by connecting to
the observatory.
Expand Down
13 changes: 13 additions & 0 deletions dev/tracing_tests/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
72 changes: 72 additions & 0 deletions dev/tracing_tests/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// 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.

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion flutter.compileSdkVersion

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = '1.8'
}

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.tracing_tests"
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}

flutter {
source '../..'
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
11 changes: 11 additions & 0 deletions dev/tracing_tests/android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- 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. -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tracing_tests">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
38 changes: 38 additions & 0 deletions dev/tracing_tests/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!-- 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. -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tracing_tests">
<application
android:label="tracing_tests"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.tracing_tests

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!-- 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. -->

<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />

<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

0 comments on commit 840e109

Please sign in to comment.