expression_evaluation_test.dart 7.91 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5
// 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';
6

7
import 'package:vm_service/vm_service.dart';
8

9
import '../src/common.dart';
10
import 'test_data/basic_project.dart';
11
import 'test_data/integration_tests_project.dart';
12
import 'test_data/tests_project.dart';
13
import 'test_driver.dart';
14
import 'test_utils.dart';
15

16
void batch1() {
17
  final BasicProject project = BasicProject();
18 19
  late Directory tempDir;
  late FlutterRunTestDriver flutter;
20 21 22

  Future<void> initProject() async {
    tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
23 24
    await project.setUpIn(tempDir);
    flutter = FlutterRunTestDriver(tempDir);
25 26 27
  }

  Future<void> cleanProject() async {
28
    await flutter.stop();
29 30 31 32
    tryToDelete(tempDir);
  }

  Future<void> breakInBuildMethod(FlutterTestDriver flutter) async {
33 34 35
    await flutter.breakAt(
      project.buildMethodBreakpointUri,
      project.buildMethodBreakpointLine,
36 37 38 39
    );
  }

  Future<void> breakInTopLevelFunction(FlutterTestDriver flutter) async {
40 41 42
    await flutter.breakAt(
      project.topLevelFunctionBreakpointUri,
      project.topLevelFunctionBreakpointLine,
43 44 45
    );
  }

46
  testWithoutContext('flutter run expression evaluation - can evaluate trivial expressions in top level function', () async {
47
    await initProject();
48 49 50
    await flutter.run(withDebugger: true);
    await breakInTopLevelFunction(flutter);
    await evaluateTrivialExpressions(flutter);
51 52 53
    await cleanProject();
  });

54
  testWithoutContext('flutter run expression evaluation - can evaluate trivial expressions in build method', () async {
55
    await initProject();
56 57 58
    await flutter.run(withDebugger: true);
    await breakInBuildMethod(flutter);
    await evaluateTrivialExpressions(flutter);
59 60 61
    await cleanProject();
  });

62
  testWithoutContext('flutter run expression evaluation - can evaluate complex expressions in top level function', () async {
63
    await initProject();
64 65 66
    await flutter.run(withDebugger: true);
    await breakInTopLevelFunction(flutter);
    await evaluateComplexExpressions(flutter);
67 68 69
    await cleanProject();
  });

70
  testWithoutContext('flutter run expression evaluation - can evaluate complex expressions in build method', () async {
71
    await initProject();
72 73 74
    await flutter.run(withDebugger: true);
    await breakInBuildMethod(flutter);
    await evaluateComplexExpressions(flutter);
75 76 77
    await cleanProject();
  });

78
  testWithoutContext('flutter run expression evaluation - can evaluate expressions returning complex objects in top level function', () async {
79
    await initProject();
80 81 82
    await flutter.run(withDebugger: true);
    await breakInTopLevelFunction(flutter);
    await evaluateComplexReturningExpressions(flutter);
83 84 85
    await cleanProject();
  });

86
  testWithoutContext('flutter run expression evaluation - can evaluate expressions returning complex objects in build method', () async {
87
    await initProject();
88 89 90
    await flutter.run(withDebugger: true);
    await breakInBuildMethod(flutter);
    await evaluateComplexReturningExpressions(flutter);
91 92 93 94 95
    await cleanProject();
  });
}

void batch2() {
96
  final TestsProject project = TestsProject();
97 98
  late Directory tempDir;
  late FlutterTestTestDriver flutter;
99 100 101

  Future<void> initProject() async {
    tempDir = createResolvedTempDirectorySync('test_expression_eval_test.');
102 103
    await project.setUpIn(tempDir);
    flutter = FlutterTestTestDriver(tempDir);
104 105 106
  }

  Future<void> cleanProject() async {
107
    await flutter.waitForCompletion();
108 109 110
    tryToDelete(tempDir);
  }

111
  testWithoutContext('flutter test expression evaluation - can evaluate trivial expressions in a test', () async {
112
    await initProject();
113
    await flutter.test(
114
      withDebugger: true,
115
      beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
116
    );
117 118
    await flutter.waitForPause();
    await evaluateTrivialExpressions(flutter);
119 120 121 122 123 124

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

125 126 127
    await cleanProject();
  });

128
  testWithoutContext('flutter test expression evaluation - can evaluate complex expressions in a test', () async {
129
    await initProject();
130
    await flutter.test(
131
      withDebugger: true,
132
      beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
133
    );
134 135
    await flutter.waitForPause();
    await evaluateComplexExpressions(flutter);
136 137 138
    await cleanProject();
  });

139
  testWithoutContext('flutter test expression evaluation - can evaluate expressions returning complex objects in a test', () async {
140
    await initProject();
141
    await flutter.test(
142
      withDebugger: true,
143
      beforeStart: () => flutter.addBreakpoint(project.breakpointUri, project.breakpointLine),
144
    );
145 146
    await flutter.waitForPause();
    await evaluateComplexReturningExpressions(flutter);
147 148
    await cleanProject();
  });
149
}
150

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
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);
177 178 179 180 181 182

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

183 184 185 186 187
    await cleanProject();
  });

}

188
Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
189
  ObjRef res;
190 191

  res = await flutter.evaluateInFrame('"test"');
192
  expectValueOfType(res, InstanceKind.kString, 'test');
193 194

  res = await flutter.evaluateInFrame('1');
195
  expectValueOfType(res, InstanceKind.kInt, 1.toString());
196 197

  res = await flutter.evaluateInFrame('true');
198
  expectValueOfType(res, InstanceKind.kBool, true.toString());
199 200 201
}

Future<void> evaluateComplexExpressions(FlutterTestDriver flutter) async {
202 203
  final ObjRef res = await flutter.evaluateInFrame('new DateTime(2000).year');
  expectValueOfType(res, InstanceKind.kInt, '2000');
204 205 206
}

Future<void> evaluateComplexReturningExpressions(FlutterTestDriver flutter) async {
207 208
  final DateTime date = DateTime(2000);
  final ObjRef resp = await flutter.evaluateInFrame('new DateTime(2000)');
209
  expectInstanceOfClass(resp, 'DateTime');
210
  final ObjRef res = await flutter.evaluate(resp.id!, r'"$year-$month-$day"');
211
  expectValue(res, '${date.year}-${date.month}-${date.day}');
212 213 214 215 216
}

void expectInstanceOfClass(ObjRef result, String name) {
  expect(result,
    const TypeMatcher<InstanceRef>()
217
      .having((InstanceRef instance) => instance.classRef!.name, 'resp.classRef.name', name));
218 219 220 221 222 223 224 225 226 227 228 229 230
}

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));
231
}
232 233 234 235

void main() {
  batch1();
  batch2();
236
  batch3();
237
}