mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

This test was skipped in https://github.com/flutter/flutter/pull/148737
because it had became flaky because instances created in expression
evaluation were being collected quickly. The change in
ffbbdb5a10
prevents things in the VM Service's ring buffer from being GC'd which
should resolve the issue.
I am unable to reproduce this test flaking locally on latest code.
Fixes https://github.com/flutter/flutter/issues/148704
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-new channel
on [Discord].
<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
[Data Driven Fixes]:
https://github.com/flutter/flutter/wiki/Data-driven-Fixes
238 lines
7.9 KiB
Dart
238 lines
7.9 KiB
Dart
// 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:file/file.dart';
|
|
|
|
import 'package:vm_service/vm_service.dart';
|
|
|
|
import '../src/common.dart';
|
|
import 'test_data/basic_project.dart';
|
|
import 'test_data/integration_tests_project.dart';
|
|
import 'test_data/tests_project.dart';
|
|
import 'test_driver.dart';
|
|
import 'test_utils.dart';
|
|
|
|
void batch1() {
|
|
final BasicProject project = BasicProject();
|
|
late Directory tempDir;
|
|
late FlutterRunTestDriver flutter;
|
|
|
|
Future<void> initProject() async {
|
|
tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
|
|
await project.setUpIn(tempDir);
|
|
flutter = FlutterRunTestDriver(tempDir);
|
|
}
|
|
|
|
Future<void> cleanProject() async {
|
|
await flutter.stop();
|
|
tryToDelete(tempDir);
|
|
}
|
|
|
|
Future<void> breakInBuildMethod(FlutterTestDriver flutter) async {
|
|
await flutter.breakAt(
|
|
project.buildMethodBreakpointUri,
|
|
project.buildMethodBreakpointLine,
|
|
);
|
|
}
|
|
|
|
Future<void> breakInTopLevelFunction(FlutterTestDriver flutter) async {
|
|
await flutter.breakAt(
|
|
project.topLevelFunctionBreakpointUri,
|
|
project.topLevelFunctionBreakpointLine,
|
|
);
|
|
}
|
|
|
|
testWithoutContext('flutter run expression evaluation - can evaluate trivial expressions in top level function', () async {
|
|
await initProject();
|
|
await flutter.run(withDebugger: true);
|
|
await breakInTopLevelFunction(flutter);
|
|
await evaluateTrivialExpressions(flutter);
|
|
await cleanProject();
|
|
});
|
|
|
|
testWithoutContext('flutter run expression evaluation - can evaluate trivial expressions in build method', () async {
|
|
await initProject();
|
|
await flutter.run(withDebugger: true);
|
|
await breakInBuildMethod(flutter);
|
|
await evaluateTrivialExpressions(flutter);
|
|
await cleanProject();
|
|
});
|
|
|
|
testWithoutContext('flutter run expression evaluation - can evaluate complex expressions in top level function', () async {
|
|
await initProject();
|
|
await flutter.run(withDebugger: true);
|
|
await breakInTopLevelFunction(flutter);
|
|
await evaluateComplexExpressions(flutter);
|
|
await cleanProject();
|
|
});
|
|
|
|
testWithoutContext('flutter run expression evaluation - can evaluate complex expressions in build method', () async {
|
|
await initProject();
|
|
await flutter.run(withDebugger: true);
|
|
await breakInBuildMethod(flutter);
|
|
await evaluateComplexExpressions(flutter);
|
|
await cleanProject();
|
|
});
|
|
|
|
testWithoutContext('flutter run expression evaluation - can evaluate expressions returning complex objects in top level function', () async {
|
|
await initProject();
|
|
await flutter.run(withDebugger: true);
|
|
await breakInTopLevelFunction(flutter);
|
|
await evaluateComplexReturningExpressions(flutter);
|
|
await cleanProject();
|
|
});
|
|
|
|
testWithoutContext('flutter run expression evaluation - can evaluate expressions returning complex objects in build method', () async {
|
|
await initProject();
|
|
await flutter.run(withDebugger: true);
|
|
await breakInBuildMethod(flutter);
|
|
await evaluateComplexReturningExpressions(flutter);
|
|
await cleanProject();
|
|
});
|
|
}
|
|
|
|
void batch2() {
|
|
final TestsProject project = TestsProject();
|
|
late Directory tempDir;
|
|
late FlutterTestTestDriver flutter;
|
|
|
|
Future<void> initProject() async {
|
|
tempDir = createResolvedTempDirectorySync('test_expression_eval_test.');
|
|
await project.setUpIn(tempDir);
|
|
flutter = FlutterTestTestDriver(tempDir);
|
|
}
|
|
|
|
Future<void> cleanProject() async {
|
|
await flutter.waitForCompletion();
|
|
tryToDelete(tempDir);
|
|
}
|
|
|
|
testWithoutContext('flutter test expression evaluation - can evaluate trivial expressions in a test', () async {
|
|
await initProject();
|
|
await flutter.test(
|
|
withDebugger: true,
|
|
beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
|
|
);
|
|
await flutter.waitForPause();
|
|
await evaluateTrivialExpressions(flutter);
|
|
|
|
// Ensure we did not leave a dill file alongside the test.
|
|
// https://github.com/Dart-Code/Dart-Code/issues/4243.
|
|
final String dillFilename = '${project.testFilePath}.dill';
|
|
expect(fileSystem.file(dillFilename).existsSync(), isFalse);
|
|
|
|
await cleanProject();
|
|
});
|
|
|
|
testWithoutContext('flutter test expression evaluation - can evaluate complex expressions in a test', () async {
|
|
await initProject();
|
|
await flutter.test(
|
|
withDebugger: true,
|
|
beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
|
|
);
|
|
await flutter.waitForPause();
|
|
await evaluateComplexExpressions(flutter);
|
|
await cleanProject();
|
|
});
|
|
|
|
testWithoutContext('flutter test expression evaluation - can evaluate expressions returning complex objects in a test', () async {
|
|
await initProject();
|
|
await flutter.test(
|
|
withDebugger: true,
|
|
beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
|
|
);
|
|
await flutter.waitForPause();
|
|
await evaluateComplexReturningExpressions(flutter);
|
|
await cleanProject();
|
|
});
|
|
}
|
|
|
|
void batch3() {
|
|
final IntegrationTestsProject project = IntegrationTestsProject();
|
|
late Directory tempDir;
|
|
late FlutterTestTestDriver flutter;
|
|
|
|
Future<void> initProject() async {
|
|
tempDir = createResolvedTempDirectorySync('integration_test_expression_eval_test.');
|
|
await project.setUpIn(tempDir);
|
|
flutter = FlutterTestTestDriver(tempDir);
|
|
}
|
|
|
|
Future<void> cleanProject() async {
|
|
await flutter.waitForCompletion();
|
|
tryToDelete(tempDir);
|
|
}
|
|
|
|
testWithoutContext('flutter integration test expression evaluation - can evaluate expressions in a test', () async {
|
|
await initProject();
|
|
await flutter.test(
|
|
deviceId: 'flutter-tester',
|
|
testFile: project.testFilePath,
|
|
withDebugger: true,
|
|
beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
|
|
);
|
|
await flutter.waitForPause();
|
|
await evaluateTrivialExpressions(flutter);
|
|
|
|
// Ensure we did not leave a dill file alongside the test.
|
|
// https://github.com/Dart-Code/Dart-Code/issues/4243.
|
|
final String dillFilename = '${project.testFilePath}.dill';
|
|
expect(fileSystem.file(dillFilename).existsSync(), isFalse);
|
|
|
|
await cleanProject();
|
|
});
|
|
|
|
}
|
|
|
|
Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
|
|
ObjRef res;
|
|
|
|
res = await flutter.evaluateInFrame('"test"');
|
|
expectValueOfType(res, InstanceKind.kString, 'test');
|
|
|
|
res = await flutter.evaluateInFrame('1');
|
|
expectValueOfType(res, InstanceKind.kInt, 1.toString());
|
|
|
|
res = await flutter.evaluateInFrame('true');
|
|
expectValueOfType(res, InstanceKind.kBool, true.toString());
|
|
}
|
|
|
|
Future<void> evaluateComplexExpressions(FlutterTestDriver flutter) async {
|
|
final ObjRef res = await flutter.evaluateInFrame('new DateTime(2000).year');
|
|
expectValueOfType(res, InstanceKind.kInt, '2000');
|
|
}
|
|
|
|
Future<void> evaluateComplexReturningExpressions(FlutterTestDriver flutter) async {
|
|
final DateTime date = DateTime(2000);
|
|
final ObjRef resp = await flutter.evaluateInFrame('new DateTime(2000)');
|
|
expectInstanceOfClass(resp, 'DateTime');
|
|
final ObjRef res = await flutter.evaluate(resp.id!, r'"$year-$month-$day"');
|
|
expectValue(res, '${date.year}-${date.month}-${date.day}');
|
|
}
|
|
|
|
void expectInstanceOfClass(ObjRef result, String name) {
|
|
expect(result,
|
|
const TypeMatcher<InstanceRef>()
|
|
.having((InstanceRef instance) => instance.classRef!.name, 'resp.classRef.name', name));
|
|
}
|
|
|
|
void expectValueOfType(ObjRef result, String kind, String message) {
|
|
expect(result,
|
|
const TypeMatcher<InstanceRef>()
|
|
.having((InstanceRef instance) => instance.kind, 'kind', kind)
|
|
.having((InstanceRef instance) => instance.valueAsString, 'valueAsString', message));
|
|
}
|
|
|
|
void expectValue(ObjRef result, String message) {
|
|
expect(result,
|
|
const TypeMatcher<InstanceRef>()
|
|
.having((InstanceRef instance) => instance.valueAsString, 'valueAsString', message));
|
|
}
|
|
|
|
void main() {
|
|
batch1();
|
|
batch2();
|
|
batch3();
|
|
}
|