1// Copyright 2017 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import 'package:flutter/foundation.dart'; 6import '../flutter_test_alternative.dart'; 7 8import 'capture_output.dart'; 9 10void main() { 11 test('debugPrintStack', () { 12 final List<String> log = captureOutput(() { 13 debugPrintStack(label: 'Example label', maxFrames: 7); 14 }); 15 expect(log[0], contains('Example label')); 16 expect(log[1], contains('debugPrintStack')); 17 }); 18 19 test('debugPrintStack', () { 20 final List<String> log = captureOutput(() { 21 final FlutterErrorDetails details = FlutterErrorDetails( 22 exception: 'Example exception', 23 stack: StackTrace.current, 24 library: 'Example library', 25 context: ErrorDescription('Example context'), 26 informationCollector: () sync* { 27 yield ErrorDescription('Example information'); 28 }, 29 ); 30 31 FlutterError.dumpErrorToConsole(details); 32 }); 33 34 expect(log[0], contains('EXAMPLE LIBRARY')); 35 expect(log[1], contains('Example context')); 36 expect(log[2], contains('Example exception')); 37 38 final String joined = log.join('\n'); 39 40 expect(joined, contains('captureOutput')); 41 expect(joined, contains('\nExample information\n')); 42 }); 43 44 test('FlutterErrorDetails.toString', () { 45 expect( 46 FlutterErrorDetails( 47 exception: 'MESSAGE', 48 library: 'LIBRARY', 49 context: ErrorDescription('CONTEXTING'), 50 informationCollector: () sync* { 51 yield ErrorDescription('INFO'); 52 }, 53 ).toString(), 54 '══╡ EXCEPTION CAUGHT BY LIBRARY ╞════════════════════════════════\n' 55 'The following message was thrown CONTEXTING:\n' 56 'MESSAGE\n' 57 '\n' 58 'INFO\n' 59 '═════════════════════════════════════════════════════════════════\n' 60 61 ); 62 expect( 63 FlutterErrorDetails( 64 library: 'LIBRARY', 65 context: ErrorDescription('CONTEXTING'), 66 informationCollector: () sync* { 67 yield ErrorDescription('INFO'); 68 }, 69 ).toString(), 70 '══╡ EXCEPTION CAUGHT BY LIBRARY ╞════════════════════════════════\n' 71 'The following Null object was thrown CONTEXTING:\n' 72 ' null\n' 73 '\n' 74 'INFO\n' 75 '═════════════════════════════════════════════════════════════════\n', 76 ); 77 expect( 78 FlutterErrorDetails( 79 exception: 'MESSAGE', 80 context: ErrorDescription('CONTEXTING'), 81 informationCollector: () sync* { 82 yield ErrorDescription('INFO'); 83 }, 84 ).toString(), 85 '══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════\n' 86 'The following message was thrown CONTEXTING:\n' 87 'MESSAGE\n' 88 '\n' 89 'INFO\n' 90 '═════════════════════════════════════════════════════════════════\n' 91 ); 92 expect( 93 FlutterErrorDetails( 94 exception: 'MESSAGE', 95 context: ErrorDescription('CONTEXTING ${'SomeContext(BlaBla)'}'), 96 informationCollector: () sync* { 97 yield ErrorDescription('INFO'); 98 }, 99 ).toString(), 100 '══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════\n' 101 'The following message was thrown CONTEXTING SomeContext(BlaBla):\n' 102 'MESSAGE\n' 103 '\n' 104 'INFO\n' 105 '═════════════════════════════════════════════════════════════════\n', 106 ); 107 expect( 108 const FlutterErrorDetails( 109 exception: 'MESSAGE', 110 ).toString(), 111 '══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════\n' 112 'The following message was thrown:\n' 113 'MESSAGE\n' 114 '═════════════════════════════════════════════════════════════════\n' 115 ); 116 expect( 117 const FlutterErrorDetails().toString(), 118 '══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════\n' 119 'The following Null object was thrown:\n' 120 ' null\n' 121 '═════════════════════════════════════════════════════════════════\n' 122 ); 123 }); 124 125 test('FlutterErrorDetails.toStringShort', () { 126 expect( 127 FlutterErrorDetails( 128 exception: 'MESSAGE', 129 library: 'library', 130 context: ErrorDescription('CONTEXTING'), 131 informationCollector: () sync* { 132 yield ErrorDescription('INFO'); 133 }, 134 ).toStringShort(), 135 'Exception caught by library', 136 ); 137 }); 138 139 test('FlutterError default constructor', () { 140 FlutterError error = FlutterError( 141 'My Error Summary.\n' 142 'My first description.\n' 143 'My second description.' 144 ); 145 expect(error.diagnostics.length, equals(3)); 146 expect(error.diagnostics[0].level, DiagnosticLevel.summary); 147 expect(error.diagnostics[1].level, DiagnosticLevel.info); 148 expect(error.diagnostics[2].level, DiagnosticLevel.info); 149 expect(error.diagnostics[0].toString(), 'My Error Summary.'); 150 expect(error.diagnostics[1].toString(), 'My first description.'); 151 expect(error.diagnostics[2].toString(), 'My second description.'); 152 expect( 153 error.toStringDeep(), 154 'FlutterError\n' 155 ' My Error Summary.\n' 156 ' My first description.\n' 157 ' My second description.\n' 158 ); 159 160 error = FlutterError( 161 'My Error Summary.\n' 162 'My first description.\n' 163 'My second description.\n' 164 '\n' 165 ); 166 167 expect(error.diagnostics.length, equals(5)); 168 expect(error.diagnostics[0].level, DiagnosticLevel.summary); 169 expect(error.diagnostics[1].level, DiagnosticLevel.info); 170 expect(error.diagnostics[2].level, DiagnosticLevel.info); 171 expect(error.diagnostics[0].toString(), 'My Error Summary.'); 172 expect(error.diagnostics[1].toString(), 'My first description.'); 173 expect(error.diagnostics[2].toString(), 'My second description.'); 174 expect(error.diagnostics[3].toString(), ''); 175 expect(error.diagnostics[4].toString(), ''); 176 expect( 177 error.toStringDeep(), 178 'FlutterError\n' 179 ' My Error Summary.\n' 180 ' My first description.\n' 181 ' My second description.\n' 182 '\n' 183 '\n' 184 ); 185 186 error = FlutterError( 187 'My Error Summary.\n' 188 'My first description.\n' 189 '\n' 190 'My second description.' 191 ); 192 expect(error.diagnostics.length, equals(4)); 193 expect(error.diagnostics[0].level, DiagnosticLevel.summary); 194 expect(error.diagnostics[1].level, DiagnosticLevel.info); 195 expect(error.diagnostics[2].level, DiagnosticLevel.info); 196 expect(error.diagnostics[3].level, DiagnosticLevel.info); 197 expect(error.diagnostics[0].toString(), 'My Error Summary.'); 198 expect(error.diagnostics[1].toString(), 'My first description.'); 199 expect(error.diagnostics[2].toString(), ''); 200 expect(error.diagnostics[3].toString(), 'My second description.'); 201 202 expect( 203 error.toStringDeep(), 204 'FlutterError\n' 205 ' My Error Summary.\n' 206 ' My first description.\n' 207 '\n' 208 ' My second description.\n' 209 ); 210 error = FlutterError('My Error Summary.'); 211 expect(error.diagnostics.length, 1); 212 expect(error.diagnostics.first.level, DiagnosticLevel.summary); 213 expect(error.diagnostics.first.toString(), 'My Error Summary.'); 214 215 expect( 216 error.toStringDeep(), 217 'FlutterError\n' 218 ' My Error Summary.\n' 219 ); 220 }); 221 222 test('Malformed FlutterError objects', () { 223 { 224 AssertionError error; 225 try { 226 throw FlutterError.fromParts(<DiagnosticsNode>[]); 227 } on AssertionError catch (e) { 228 error = e; 229 } 230 expect( 231 FlutterErrorDetails(exception: error).toString(), 232 '══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════\n' 233 'The following assertion was thrown:\n' 234 'Empty FlutterError\n' 235 '═════════════════════════════════════════════════════════════════\n', 236 ); 237 } 238 239 { 240 AssertionError error; 241 try { 242 throw FlutterError.fromParts(<DiagnosticsNode>[ 243 (ErrorDescription('Error description without a summary'))]); 244 } on AssertionError catch (e) { 245 error = e; 246 } 247 expect( 248 FlutterErrorDetails(exception: error).toString(), 249 '══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════\n' 250 'The following assertion was thrown:\n' 251 'FlutterError is missing a summary.\n' 252 'All FlutterError objects should start with a short (one line)\n' 253 'summary description of the problem that was detected.\n' 254 'Malformed FlutterError:\n' 255 ' Error description without a summary\n' 256 '\n' 257 'This error should still help you solve your problem, however\n' 258 'please also report this malformed error in the framework by\n' 259 'filing a bug on GitHub:\n' 260 ' https://github.com/flutter/flutter/issues/new?template=BUG.md\n' 261 '═════════════════════════════════════════════════════════════════\n', 262 ); 263 } 264 265 { 266 AssertionError error; 267 try { 268 throw FlutterError.fromParts(<DiagnosticsNode>[ 269 ErrorSummary('Error Summary A'), 270 ErrorDescription('Some descriptionA'), 271 ErrorSummary('Error Summary B'), 272 ErrorDescription('Some descriptionB'), 273 ]); 274 } on AssertionError catch (e) { 275 error = e; 276 } 277 expect( 278 FlutterErrorDetails(exception: error).toString(), 279 '══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════\n' 280 'The following assertion was thrown:\n' 281 'FlutterError contained multiple error summaries.\n' 282 'All FlutterError objects should have only a single short (one\n' 283 'line) summary description of the problem that was detected.\n' 284 'Malformed FlutterError:\n' 285 ' Error Summary A\n' 286 ' Some descriptionA\n' 287 ' Error Summary B\n' 288 ' Some descriptionB\n' 289 '\n' 290 'The malformed error has 2 summaries.\n' 291 'Summary 1: Error Summary A\n' 292 'Summary 2: Error Summary B\n' 293 '\n' 294 'This error should still help you solve your problem, however\n' 295 'please also report this malformed error in the framework by\n' 296 'filing a bug on GitHub:\n' 297 ' https://github.com/flutter/flutter/issues/new?template=BUG.md\n' 298 '═════════════════════════════════════════════════════════════════\n', 299 ); 300 } 301 302 { 303 AssertionError error; 304 try { 305 throw FlutterError.fromParts(<DiagnosticsNode>[ 306 ErrorDescription('Some description'), 307 ErrorSummary('Error summary'), 308 ]); 309 } on AssertionError catch (e) { 310 error = e; 311 } 312 expect( 313 FlutterErrorDetails(exception: error).toString(), 314 '══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════\n' 315 'The following assertion was thrown:\n' 316 'FlutterError is missing a summary.\n' 317 'All FlutterError objects should start with a short (one line)\n' 318 'summary description of the problem that was detected.\n' 319 'Malformed FlutterError:\n' 320 ' Some description\n' 321 ' Error summary\n' 322 '\n' 323 'This error should still help you solve your problem, however\n' 324 'please also report this malformed error in the framework by\n' 325 'filing a bug on GitHub:\n' 326 ' https://github.com/flutter/flutter/issues/new?template=BUG.md\n' 327 '═════════════════════════════════════════════════════════════════\n', 328 ); 329 } 330 }); 331 332 test('User-thrown exceptions have ErrorSummary properties', () { 333 { 334 DiagnosticsNode node; 335 try { 336 throw 'User thrown string'; 337 } catch (e) { 338 node = FlutterErrorDetails(exception: e).toDiagnosticsNode(); 339 } 340 final ErrorSummary summary = node.getProperties().whereType<ErrorSummary>().single; 341 expect(summary.value, equals(<String>['User thrown string'])); 342 } 343 344 { 345 DiagnosticsNode node; 346 try { 347 throw ArgumentError.notNull('myArgument'); 348 } catch (e) { 349 node = FlutterErrorDetails(exception: e).toDiagnosticsNode(); 350 } 351 final ErrorSummary summary = node.getProperties().whereType<ErrorSummary>().single; 352 expect(summary.value, equals(<String>['Invalid argument(s) (myArgument): Must not be null'])); 353 } 354 }); 355} 356