| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 // VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked | |
| 5 | |
| 6 import 'package:observatory/service_io.dart'; | |
| 7 import 'package:observatory/debugger.dart'; | |
| 8 import 'package:unittest/unittest.dart'; | |
| 9 import 'test_helper.dart'; | |
| 10 import 'dart:async'; | |
| 11 | |
| 12 void testFunction() { | |
| 13 int i = 0; | |
| 14 while (true) { | |
| 15 if (++i % 100000000 == 0) { // line 15 | |
| 16 print(i); | |
| 17 } | |
| 18 } | |
| 19 } | |
| 20 | |
| 21 class TestDebugger extends Debugger { | |
| 22 TestDebugger(this.isolate, this.stack); | |
| 23 | |
| 24 VM get vm => isolate.vm; | |
| 25 Isolate isolate; | |
| 26 ServiceMap stack; | |
| 27 int currentFrame = 0; | |
| 28 } | |
| 29 | |
| 30 void source_location_dummy_function() { | |
| 31 } | |
| 32 | |
| 33 class SourceLocationTestFoo { | |
| 34 SourceLocationTestFoo(this.field); | |
| 35 SourceLocationTestFoo.named(); | |
| 36 | |
| 37 void method() {} | |
| 38 void madness() {} | |
| 39 | |
| 40 int field; | |
| 41 } | |
| 42 | |
| 43 class SourceLocationTestBar { | |
| 44 } | |
| 45 | |
| 46 Future<Debugger> initDebugger(Isolate isolate) { | |
| 47 return isolate.getStack().then((stack) { | |
| 48 return new TestDebugger(isolate, stack); | |
| 49 }); | |
| 50 } | |
| 51 | |
| 52 var tests = [ | |
| 53 | |
| 54 // Bring the isolate to a breakpoint at line 15. | |
| 55 (Isolate isolate) { | |
| 56 return isolate.rootLib.load().then((_) { | |
| 57 // Listen for breakpoint event. | |
| 58 Completer completer = new Completer(); | |
| 59 isolate.vm.events.stream.listen((ServiceEvent event) { | |
| 60 if (event.eventType == ServiceEvent.kPauseBreakpoint) { | |
| 61 completer.complete(); | |
| 62 } | |
| 63 }); | |
| 64 | |
| 65 // Add the breakpoint. | |
| 66 var script = isolate.rootLib.scripts[0]; | |
| 67 return isolate.addBreakpoint(script, 15).then((ServiceObject bpt) { | |
| 68 return completer.future; // Wait for breakpoint events. | |
| 69 }); | |
| 70 }); | |
| 71 }, | |
| 72 | |
| 73 // Parse '' => current position | |
| 74 (Isolate isolate) { | |
| 75 return initDebugger(isolate).then((debugger) { | |
| 76 return SourceLocation.parse(debugger, '').then((SourceLocation loc) { | |
| 77 expect(loc.valid, isTrue); | |
| 78 expect(loc.toString(), equals('source_location_test.dart:15')); | |
| 79 }); | |
| 80 }); | |
| 81 }, | |
| 82 | |
| 83 // Parse line | |
| 84 (Isolate isolate) { | |
| 85 return initDebugger(isolate).then((debugger) { | |
| 86 return SourceLocation.parse(debugger, '16').then((SourceLocation loc) { | |
| 87 expect(loc.valid, isTrue); | |
| 88 expect(loc.toString(), equals('source_location_test.dart:16')); | |
| 89 }); | |
| 90 }); | |
| 91 }, | |
| 92 | |
| 93 // Parse line + col | |
| 94 (Isolate isolate) { | |
| 95 return initDebugger(isolate).then((debugger) { | |
| 96 return SourceLocation.parse(debugger, '16:11').then((SourceLocation loc) { | |
| 97 expect(loc.valid, isTrue); | |
| 98 expect(loc.toString(), equals('source_location_test.dart:16:11')); | |
| 99 }); | |
| 100 }); | |
| 101 }, | |
| 102 | |
| 103 // Parse script + line | |
| 104 (Isolate isolate) { | |
| 105 return initDebugger(isolate).then((debugger) { | |
| 106 return SourceLocation.parse(debugger, 'unittest.dart:15') | |
| 107 .then((SourceLocation loc) { | |
| 108 expect(loc.valid, isTrue); | |
| 109 expect(loc.toString(), equals('unittest.dart:15')); | |
| 110 }); | |
| 111 }); | |
| 112 }, | |
| 113 | |
| 114 // Parse script + line + col | |
| 115 (Isolate isolate) { | |
| 116 return initDebugger(isolate).then((debugger) { | |
| 117 return SourceLocation.parse(debugger, 'unittest.dart:15:10') | |
| 118 .then((SourceLocation loc) { | |
| 119 expect(loc.valid, isTrue); | |
| 120 expect(loc.toString(), equals('unittest.dart:15:10')); | |
| 121 }); | |
| 122 }); | |
| 123 }, | |
| 124 | |
| 125 // Parse bad script | |
| 126 (Isolate isolate) { | |
| 127 return initDebugger(isolate).then((debugger) { | |
| 128 return SourceLocation.parse(debugger, 'bad.dart:15') | |
| 129 .then((SourceLocation loc) { | |
| 130 expect(loc.valid, isFalse); | |
| 131 expect(loc.toString(), equals( | |
| 132 'invalid source location (Script \'bad.dart\' not found)')); | |
| 133 }); | |
| 134 }); | |
| 135 }, | |
| 136 | |
| 137 // Parse function | |
| 138 (Isolate isolate) { | |
| 139 return initDebugger(isolate).then((debugger) { | |
| 140 return SourceLocation.parse(debugger, 'testFunction') | |
| 141 .then((SourceLocation loc) { | |
| 142 expect(loc.valid, isTrue); | |
| 143 expect(loc.toString(), equals('testFunction')); | |
| 144 }); | |
| 145 }); | |
| 146 }, | |
| 147 | |
| 148 // Parse bad function | |
| 149 (Isolate isolate) { | |
| 150 return initDebugger(isolate).then((debugger) { | |
| 151 return SourceLocation.parse(debugger, 'doesNotReallyExit') | |
| 152 .then((SourceLocation loc) { | |
| 153 expect(loc.valid, isFalse); | |
| 154 expect(loc.toString(), equals( | |
| 155 'invalid source location (Function \'doesNotReallyExit\' not found)'
)); | |
| 156 }); | |
| 157 }); | |
| 158 }, | |
| 159 | |
| 160 // Parse constructor | |
| 161 (Isolate isolate) { | |
| 162 return initDebugger(isolate).then((debugger) { | |
| 163 return SourceLocation.parse(debugger, 'SourceLocationTestFoo') | |
| 164 .then((SourceLocation loc) { | |
| 165 expect(loc.valid, isTrue); | |
| 166 // TODO(turnidge): Printing a constructor currently adds | |
| 167 // another class qualifier at the front. Do we want to change | |
| 168 // this to be more consistent? | |
| 169 expect(loc.toString(), equals( | |
| 170 'SourceLocationTestFoo.SourceLocationTestFoo')); | |
| 171 }); | |
| 172 }); | |
| 173 }, | |
| 174 | |
| 175 // Parse named constructor | |
| 176 (Isolate isolate) { | |
| 177 return initDebugger(isolate).then((debugger) { | |
| 178 return SourceLocation.parse(debugger, 'SourceLocationTestFoo.named') | |
| 179 .then((SourceLocation loc) { | |
| 180 expect(loc.valid, isTrue); | |
| 181 // TODO(turnidge): Printing a constructor currently adds | |
| 182 // another class qualifier at the front. Do we want to change | |
| 183 // this to be more consistent? | |
| 184 expect(loc.toString(), equals( | |
| 185 'SourceLocationTestFoo.SourceLocationTestFoo.named')); | |
| 186 }); | |
| 187 }); | |
| 188 }, | |
| 189 | |
| 190 // Parse method | |
| 191 (Isolate isolate) { | |
| 192 return initDebugger(isolate).then((debugger) { | |
| 193 return SourceLocation.parse(debugger, 'SourceLocationTestFoo.method') | |
| 194 .then((SourceLocation loc) { | |
| 195 expect(loc.valid, isTrue); | |
| 196 expect(loc.toString(), equals('SourceLocationTestFoo.method')); | |
| 197 }); | |
| 198 }); | |
| 199 }, | |
| 200 | |
| 201 // Parse method | |
| 202 (Isolate isolate) { | |
| 203 return initDebugger(isolate).then((debugger) { | |
| 204 return SourceLocation.parse(debugger, 'SourceLocationTestFoo.field=') | |
| 205 .then((SourceLocation loc) { | |
| 206 expect(loc.valid, isTrue); | |
| 207 expect(loc.toString(), equals('SourceLocationTestFoo.field=')); | |
| 208 }); | |
| 209 }); | |
| 210 }, | |
| 211 | |
| 212 // Parse bad method | |
| 213 (Isolate isolate) { | |
| 214 return initDebugger(isolate).then((debugger) { | |
| 215 return SourceLocation.parse(debugger, 'SourceLocationTestFoo.missing') | |
| 216 .then((SourceLocation loc) { | |
| 217 expect(loc.valid, isFalse); | |
| 218 expect(loc.toString(), equals( | |
| 219 'invalid source location ' | |
| 220 '(Function \'SourceLocationTestFoo.missing\' not found)')); | |
| 221 }); | |
| 222 }); | |
| 223 }, | |
| 224 | |
| 225 // Complete function + script | |
| 226 (Isolate isolate) { | |
| 227 return initDebugger(isolate).then((debugger) { | |
| 228 return SourceLocation.complete(debugger, 'source_loc') | |
| 229 .then((List<String> completions) { | |
| 230 expect(completions.toString(), equals( | |
| 231 '[source_location_dummy_function, ' | |
| 232 'source_location.dart:, source_location_test.dart:]')); | |
| 233 }); | |
| 234 }); | |
| 235 }, | |
| 236 | |
| 237 // Complete class | |
| 238 (Isolate isolate) { | |
| 239 return initDebugger(isolate).then((debugger) { | |
| 240 return SourceLocation.complete(debugger, 'SourceLocationTe') | |
| 241 .then((List<String> completions) { | |
| 242 expect(completions.toString(), equals( | |
| 243 '[SourceLocationTestBar, SourceLocationTestFoo]')); | |
| 244 }); | |
| 245 }); | |
| 246 }, | |
| 247 | |
| 248 // No completions: unqualified name | |
| 249 (Isolate isolate) { | |
| 250 return initDebugger(isolate).then((debugger) { | |
| 251 return SourceLocation.complete(debugger, 'source_locXYZZY') | |
| 252 .then((List<String> completions) { | |
| 253 expect(completions.toString(), equals('[]')); | |
| 254 }); | |
| 255 }); | |
| 256 }, | |
| 257 | |
| 258 // Complete method | |
| 259 (Isolate isolate) { | |
| 260 return initDebugger(isolate).then((debugger) { | |
| 261 return SourceLocation.complete(debugger, 'SourceLocationTestFoo.m') | |
| 262 .then((List<String> completions) { | |
| 263 expect(completions.toString(), equals( | |
| 264 '[SourceLocationTestFoo.madness, SourceLocationTestFoo.method]')); | |
| 265 }); | |
| 266 }); | |
| 267 }, | |
| 268 | |
| 269 // No completions: qualified name | |
| 270 (Isolate isolate) { | |
| 271 return initDebugger(isolate).then((debugger) { | |
| 272 return SourceLocation.complete(debugger, 'SourceLocationTestFoo.q') | |
| 273 .then((List<String> completions) { | |
| 274 expect(completions.toString(), equals('[]')); | |
| 275 }); | |
| 276 }); | |
| 277 }, | |
| 278 | |
| 279 ]; | |
| 280 | |
| 281 main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction); | |
| OLD | NEW |