| // 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(); | |
| } |