OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library unittest.utils; | 5 library unittest.utils; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:stack_trace/stack_trace.dart'; | 9 import 'package:stack_trace/stack_trace.dart'; |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 /// | 21 /// |
22 /// Many exceptions include the exception class name at the beginning of their | 22 /// Many exceptions include the exception class name at the beginning of their |
23 /// [toString], so we remove that if it exists. | 23 /// [toString], so we remove that if it exists. |
24 String getErrorMessage(error) => | 24 String getErrorMessage(error) => |
25 error.toString().replaceFirst(_exceptionPrefix, ''); | 25 error.toString().replaceFirst(_exceptionPrefix, ''); |
26 | 26 |
27 /// Indent each line in [str] by two spaces. | 27 /// Indent each line in [str] by two spaces. |
28 String indent(String str) => | 28 String indent(String str) => |
29 str.replaceAll(new RegExp("^", multiLine: true), " "); | 29 str.replaceAll(new RegExp("^", multiLine: true), " "); |
30 | 30 |
31 /// A pair of values. | |
32 class Pair<E, F> { | |
33 final E first; | |
34 final F last; | |
35 | |
36 Pair(this.first, this.last); | |
37 | |
38 String toString() => '($first, $last)'; | |
39 | |
40 bool operator ==(other) { | |
41 if (other is! Pair) return false; | |
42 return other.first == first && other.last == last; | |
43 } | |
44 | |
45 int get hashCode => first.hashCode ^ last.hashCode; | |
46 } | |
47 | |
48 /// A regular expression matching the path to a temporary file used to start an | 31 /// A regular expression matching the path to a temporary file used to start an |
49 /// isolate. | 32 /// isolate. |
50 /// | 33 /// |
51 /// These paths aren't relevant and are removed from stack traces. | 34 /// These paths aren't relevant and are removed from stack traces. |
52 final _isolatePath = | 35 final _isolatePath = |
53 new RegExp(r"/unittest_[A-Za-z0-9]{6}/runInIsolate\.dart$"); | 36 new RegExp(r"/unittest_[A-Za-z0-9]{6}/runInIsolate\.dart$"); |
54 | 37 |
55 /// Returns [stackTrace] converted to a [Chain] with all irrelevant frames | 38 /// Returns [stackTrace] converted to a [Chain] with all irrelevant frames |
56 /// folded together. | 39 /// folded together. |
57 Chain terseChain(StackTrace stackTrace) { | 40 Chain terseChain(StackTrace stackTrace) { |
58 return new Chain.forTrace(stackTrace).foldFrames((frame) { | 41 return new Chain.forTrace(stackTrace).foldFrames((frame) { |
59 if (frame.package == 'unittest') return true; | 42 if (frame.package == 'unittest') return true; |
60 | 43 |
61 // Filter out frames from our isolate bootstrap as well. | 44 // Filter out frames from our isolate bootstrap as well. |
62 if (frame.uri.scheme != 'file') return false; | 45 if (frame.uri.scheme != 'file') return false; |
63 return frame.uri.path.contains(_isolatePath); | 46 return frame.uri.path.contains(_isolatePath); |
64 }, terse: true); | 47 }, terse: true); |
65 } | 48 } |
66 | 49 |
67 /// Returns a Trace object from a StackTrace object or a String, or the | |
68 /// unchanged input if formatStacks is false; | |
69 Trace getTrace(stack, bool formatStacks, bool filterStacks) { | |
70 Trace trace; | |
71 if (stack == null || !formatStacks) return null; | |
72 if (stack is String) { | |
73 trace = new Trace.parse(stack); | |
74 } else if (stack is StackTrace) { | |
75 trace = new Trace.from(stack); | |
76 } else { | |
77 throw new Exception('Invalid stack type ${stack.runtimeType} for $stack.'); | |
78 } | |
79 | |
80 if (!filterStacks) return trace; | |
81 | |
82 // Format the stack trace by removing everything above TestCase._runTest, | |
83 // which is usually going to be irrelevant. Also fold together unittest and | |
84 // core library calls so only the function the user called is visible. | |
85 return new Trace(trace.frames.takeWhile((frame) { | |
86 return frame.package != 'unittest' || frame.member != 'TestCase._runTest'; | |
87 })).terse.foldFrames((frame) => frame.package == 'unittest' || frame.isCore); | |
88 } | |
89 | |
90 /// Flattens nested [Iterable]s inside an [Iterable] into a single [List] | 50 /// Flattens nested [Iterable]s inside an [Iterable] into a single [List] |
91 /// containing only non-[Iterable] elements. | 51 /// containing only non-[Iterable] elements. |
92 List flatten(Iterable nested) { | 52 List flatten(Iterable nested) { |
93 var result = []; | 53 var result = []; |
94 helper(iter) { | 54 helper(iter) { |
95 for (var element in iter) { | 55 for (var element in iter) { |
96 if (element is Iterable) { | 56 if (element is Iterable) { |
97 helper(element); | 57 helper(element); |
98 } else { | 58 } else { |
99 result.add(element); | 59 result.add(element); |
100 } | 60 } |
101 } | 61 } |
102 } | 62 } |
103 helper(nested); | 63 helper(nested); |
104 return result; | 64 return result; |
105 } | 65 } |
OLD | NEW |