lookout 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/README +645 -0
  2. data/Rakefile +9 -0
  3. data/lib/lookout.rb +34 -0
  4. data/lib/lookout/aphonic.rb +40 -0
  5. data/lib/lookout/benchmark.rb +11 -0
  6. data/lib/lookout/diff.rb +10 -0
  7. data/lib/lookout/diff/algorithms.rb +5 -0
  8. data/lib/lookout/diff/algorithms/difflib.rb +38 -0
  9. data/lib/lookout/diff/algorithms/difflib/position.rb +92 -0
  10. data/lib/lookout/diff/algorithms/difflib/position/to.rb +47 -0
  11. data/lib/lookout/diff/formats.rb +7 -0
  12. data/lib/lookout/diff/formats/hash.rb +53 -0
  13. data/lib/lookout/diff/formats/inline.rb +39 -0
  14. data/lib/lookout/diff/formats/unified.rb +57 -0
  15. data/lib/lookout/diff/group.rb +61 -0
  16. data/lib/lookout/diff/groups.rb +34 -0
  17. data/lib/lookout/diff/match.rb +36 -0
  18. data/lib/lookout/diff/operation.rb +33 -0
  19. data/lib/lookout/diff/operations.rb +36 -0
  20. data/lib/lookout/diff/operations/delete.rb +9 -0
  21. data/lib/lookout/diff/operations/equal.rb +27 -0
  22. data/lib/lookout/diff/operations/insert.rb +9 -0
  23. data/lib/lookout/diff/operations/replace.rb +9 -0
  24. data/lib/lookout/diff/range.rb +91 -0
  25. data/lib/lookout/equality.rb +178 -0
  26. data/lib/lookout/expectation.rb +50 -0
  27. data/lib/lookout/expectations.rb +62 -0
  28. data/lib/lookout/expectations/behavior.rb +20 -0
  29. data/lib/lookout/expectations/state.rb +29 -0
  30. data/lib/lookout/mock.rb +18 -0
  31. data/lib/lookout/mock/method.rb +70 -0
  32. data/lib/lookout/mock/method/arguments.rb +33 -0
  33. data/lib/lookout/mock/method/arguments/any.rb +11 -0
  34. data/lib/lookout/mock/method/arguments/anything.rb +11 -0
  35. data/lib/lookout/mock/method/arguments/list.rb +15 -0
  36. data/lib/lookout/mock/method/arguments/none.rb +11 -0
  37. data/lib/lookout/mock/method/arguments/one.rb +11 -0
  38. data/lib/lookout/mock/method/calls.rb +11 -0
  39. data/lib/lookout/mock/method/calls/class.rb +21 -0
  40. data/lib/lookout/mock/method/calls/exactly.rb +28 -0
  41. data/lib/lookout/mock/method/calls/instance.rb +25 -0
  42. data/lib/lookout/mock/method/calls/lower.rb +22 -0
  43. data/lib/lookout/mock/method/calls/upper.rb +22 -0
  44. data/lib/lookout/mock/methods.rb +12 -0
  45. data/lib/lookout/mock/object.rb +12 -0
  46. data/lib/lookout/object.rb +11 -0
  47. data/lib/lookout/output.rb +21 -0
  48. data/lib/lookout/rake/tasks.rb +36 -0
  49. data/lib/lookout/rake/tasks/gem.rb +49 -0
  50. data/lib/lookout/rake/tasks/tags.rb +16 -0
  51. data/lib/lookout/rake/tasks/test.rb +46 -0
  52. data/lib/lookout/rake/tasks/test/loader.rb +19 -0
  53. data/lib/lookout/recorder.rb +45 -0
  54. data/lib/lookout/recorder/not.rb +11 -0
  55. data/lib/lookout/recorder/tape.rb +21 -0
  56. data/lib/lookout/recorders.rb +6 -0
  57. data/lib/lookout/recorders/reception.rb +47 -0
  58. data/lib/lookout/recorders/state.rb +35 -0
  59. data/lib/lookout/result.rb +23 -0
  60. data/lib/lookout/results.rb +46 -0
  61. data/lib/lookout/results/error.rb +18 -0
  62. data/lib/lookout/results/error/exception.rb +36 -0
  63. data/lib/lookout/results/error/exception/backtrace.rb +41 -0
  64. data/lib/lookout/results/failure.rb +16 -0
  65. data/lib/lookout/results/failures.rb +6 -0
  66. data/lib/lookout/results/failures/behavior.rb +4 -0
  67. data/lib/lookout/results/failures/state.rb +4 -0
  68. data/lib/lookout/results/fulfilled.rb +9 -0
  69. data/lib/lookout/runners.rb +5 -0
  70. data/lib/lookout/runners/console.rb +22 -0
  71. data/lib/lookout/stub.rb +16 -0
  72. data/lib/lookout/stub/method.rb +105 -0
  73. data/lib/lookout/stub/methods.rb +18 -0
  74. data/lib/lookout/stub/object.rb +11 -0
  75. data/lib/lookout/ui.rb +7 -0
  76. data/lib/lookout/ui/console.rb +36 -0
  77. data/lib/lookout/ui/silent.rb +12 -0
  78. data/lib/lookout/version.rb +5 -0
  79. data/lib/lookout/xml.rb +17 -0
  80. data/test/unit/examples.rb +169 -0
  81. data/test/unit/lookout.rb +7 -0
  82. data/test/unit/lookout/diff.rb +4 -0
  83. data/test/unit/lookout/diff/algorithms/difflib.rb +56 -0
  84. data/test/unit/lookout/diff/algorithms/difflib/position.rb +92 -0
  85. data/test/unit/lookout/diff/algorithms/difflib/position/to.rb +12 -0
  86. data/test/unit/lookout/diff/formats/inline.rb +17 -0
  87. data/test/unit/lookout/diff/formats/unified.rb +67 -0
  88. data/test/unit/lookout/diff/group.rb +4 -0
  89. data/test/unit/lookout/diff/groups.rb +102 -0
  90. data/test/unit/lookout/diff/match.rb +5 -0
  91. data/test/unit/lookout/diff/operations.rb +22 -0
  92. data/test/unit/lookout/diff/operations/delete.rb +45 -0
  93. data/test/unit/lookout/diff/operations/equal.rb +45 -0
  94. data/test/unit/lookout/diff/operations/insert.rb +45 -0
  95. data/test/unit/lookout/diff/operations/replace.rb +45 -0
  96. data/test/unit/lookout/diff/range.rb +50 -0
  97. data/test/unit/lookout/equality.rb +113 -0
  98. data/test/unit/lookout/expectation.rb +39 -0
  99. data/test/unit/lookout/expectations.rb +58 -0
  100. data/test/unit/lookout/expectations/behavior.rb +35 -0
  101. data/test/unit/lookout/expectations/state.rb +29 -0
  102. data/test/unit/lookout/mock.rb +4 -0
  103. data/test/unit/lookout/mock/method.rb +143 -0
  104. data/test/unit/lookout/mock/method/arguments.rb +57 -0
  105. data/test/unit/lookout/mock/method/arguments/any.rb +11 -0
  106. data/test/unit/lookout/recorder.rb +11 -0
  107. data/test/unit/lookout/results.rb +30 -0
  108. data/test/unit/lookout/results/error.rb +7 -0
  109. data/test/unit/lookout/results/failures/behavior.rb +7 -0
  110. data/test/unit/lookout/results/failures/state.rb +7 -0
  111. data/test/unit/lookout/results/fulfilled.rb +7 -0
  112. data/test/unit/lookout/runners/console.rb +4 -0
  113. data/test/unit/lookout/stub.rb +4 -0
  114. data/test/unit/lookout/stub/method.rb +48 -0
  115. data/test/unit/lookout/ui/formatters/exception.rb +5 -0
  116. data/test/unit/lookout/ui/formatters/exception/backtrace.rb +11 -0
  117. data/test/unit/lookout/xml.rb +55 -0
  118. metadata +496 -0
@@ -0,0 +1,61 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Group
4
+ include Enumerable
5
+
6
+ def initialize(*operations)
7
+ @operations = operations
8
+ end
9
+
10
+ def empty?
11
+ operations.empty?
12
+ end
13
+
14
+ def <<(operation)
15
+ operations << operation
16
+ self
17
+ end
18
+
19
+ def fold(context)
20
+ operations[-1] = operations[-1] << context
21
+ self
22
+ end
23
+
24
+ def parity?
25
+ operations.size == 1 and operations.first.parity?
26
+ end
27
+
28
+ def each
29
+ operations.each do |operation|
30
+ yield operation
31
+ end
32
+ self
33
+ end
34
+
35
+ def from
36
+ range(:from)
37
+ end
38
+
39
+ def to
40
+ range(:to)
41
+ end
42
+
43
+ def ==(other)
44
+ operations == other.operations
45
+ end
46
+
47
+ def inspect
48
+ '<#%s %p>' % [self.class, operations]
49
+ end
50
+
51
+ protected
52
+
53
+ attr_reader :operations
54
+
55
+ private
56
+
57
+ def range(target)
58
+ operations.first.send(target).
59
+ at(operations.first.send(target).begin..operations.last.send(target).end)
60
+ end
61
+ end
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Groups
4
+ include Enumerable
5
+
6
+ def initialize(operations, context = 3)
7
+ @operations, @context = operations, context
8
+ end
9
+
10
+ def each
11
+ saved = nil
12
+ group = Lookout::Diff::Group.new
13
+ @operations.each do |operation|
14
+ if saved
15
+ yield saved
16
+ saved = nil
17
+ end
18
+ if group.empty?
19
+ operation = operation >> @context
20
+ group << operation
21
+ elsif operation.foldable? @context * 2
22
+ saved = group << (operation << @context)
23
+ group = Lookout::Diff::Group.new(operation >> @context)
24
+ else
25
+ group << operation
26
+ end
27
+ end
28
+ if saved
29
+ yield saved
30
+ elsif not group.empty?
31
+ yield group.fold(@context)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Match
4
+ include Comparable
5
+
6
+ def initialize(from, to)
7
+ @from, @to = from, to
8
+ end
9
+
10
+ def empty?
11
+ from.empty?
12
+ end
13
+
14
+ def size
15
+ from.size
16
+ end
17
+
18
+ def +(other)
19
+ self.class.new(from + other.from, to + other.to)
20
+ end
21
+
22
+ def touches?(other)
23
+ from.end + 1 == other.from.begin and to.end + 1 == other.to.begin
24
+ end
25
+
26
+ def <=>(other)
27
+ [from.begin, from.end, to.begin, to.end] <=>
28
+ [other.from.begin, other.from.end, other.to.begin, other.to.end]
29
+ end
30
+
31
+ def inspect
32
+ '#<%s %p==%p>' % [self.class, from, to]
33
+ end
34
+
35
+ attr_reader :from, :to
36
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Diff::Operation
4
+ def initialize(from, to)
5
+ @from, @to = from, to
6
+ end
7
+
8
+ def foldable?(window)
9
+ false
10
+ end
11
+
12
+ def >>(size)
13
+ self
14
+ end
15
+
16
+ def <<(size)
17
+ self
18
+ end
19
+
20
+ def parity?
21
+ false
22
+ end
23
+
24
+ def ==(other)
25
+ from == other.from and to == other.to
26
+ end
27
+
28
+ def inspect
29
+ '#<%s %p,%p>' % [self.class, from, to]
30
+ end
31
+
32
+ attr_reader :from, :to
33
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Operations
4
+ autoload :Delete, 'lookout/diff/operations/delete'
5
+ autoload :Equal, 'lookout/diff/operations/equal'
6
+ autoload :Insert, 'lookout/diff/operations/insert'
7
+ autoload :Replace, 'lookout/diff/operations/replace'
8
+
9
+ include Enumerable
10
+
11
+ def initialize(matches)
12
+ @matches = matches
13
+ end
14
+
15
+ def each
16
+ from = to = 0
17
+ @matches.each do |match|
18
+ type = typeify(from, to, match)
19
+ yield type.new(match.from.at(from...match.from.begin),
20
+ match.to.at(to...match.to.begin)) unless type == Equal
21
+ yield Equal.new(match.from, match.to) unless match.empty?
22
+ from, to = match.from.end + 1, match.to.end + 1
23
+ end
24
+ self
25
+ end
26
+
27
+ private
28
+
29
+ def typeify(from, to, match)
30
+ if from < match.from.begin and to < match.to.begin then Replace
31
+ elsif from < match.from.begin then Delete
32
+ elsif to < match.to.begin then Insert
33
+ else Equal
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Operations::Delete
4
+ include Lookout::Diff::Operation
5
+
6
+ def apply(object)
7
+ object.delete(self)
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Operations::Equal
4
+ include Lookout::Diff::Operation
5
+
6
+ def foldable?(window)
7
+ from.size > window
8
+ end
9
+
10
+ def >>(size)
11
+ self.class.new(from.begin_at([from.begin, from.end - size + 1].max),
12
+ to.begin_at([to.begin, to.end - size + 1].max))
13
+ end
14
+
15
+ def <<(size)
16
+ self.class.new(from.end_at([from.end, from.begin + size - 1].min),
17
+ to.end_at([to.end, to.begin + size - 1].min))
18
+ end
19
+
20
+ def parity?
21
+ from == to
22
+ end
23
+
24
+ def apply(object)
25
+ object.equal(self)
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Operations::Insert
4
+ include Lookout::Diff::Operation
5
+
6
+ def apply(object)
7
+ object.insert(self)
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Operations::Replace
4
+ include Lookout::Diff::Operation
5
+
6
+ def apply(object)
7
+ object.replace(self)
8
+ end
9
+ end
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Lookout::Diff::Range
4
+ include Enumerable
5
+
6
+ def initialize(items, range = 0...items.size)
7
+ @items, @range = items, range.exclude_end? ? range.begin..range.end - 1 : range
8
+ end
9
+
10
+ def empty?
11
+ size < 1
12
+ end
13
+
14
+ def size
15
+ range.end - range.begin + 1
16
+ end
17
+
18
+ def begins_before?(other)
19
+ range.begin < other.range.begin
20
+ end
21
+
22
+ def ends_after?(other)
23
+ range.end > other.range.end
24
+ end
25
+
26
+ def begin_after(other)
27
+ self.class.new(items, other.range.end + 1..range.end)
28
+ end
29
+
30
+ def end_before(other)
31
+ self.class.new(items, range.begin...other.range.begin)
32
+ end
33
+
34
+ def at(range)
35
+ self.class.new(items, range)
36
+ end
37
+
38
+ def +(other)
39
+ self.class.new(items, range.begin..other.range.end)
40
+ end
41
+
42
+ def begin_at(index)
43
+ self.class.new(items, index..range.end)
44
+ end
45
+
46
+ def end_at(index)
47
+ self.class.new(items, range.begin..index)
48
+ end
49
+
50
+ def each
51
+ range.each do |index|
52
+ yield items[index]
53
+ end
54
+ self
55
+ end
56
+
57
+ def each_with_index
58
+ range.each do |index|
59
+ yield items[index], index
60
+ end
61
+ self
62
+ end
63
+
64
+ def to_items
65
+ items[range]
66
+ end
67
+
68
+ def [](index)
69
+ items[index]
70
+ end
71
+
72
+ def begin
73
+ range.begin
74
+ end
75
+
76
+ def end
77
+ range.end
78
+ end
79
+
80
+ def ==(other)
81
+ range == other.range and items == other.items
82
+ end
83
+
84
+ def inspect
85
+ '%p[%p]' % [items, range]
86
+ end
87
+
88
+ protected
89
+
90
+ attr_reader :items, :range
91
+ end
@@ -0,0 +1,178 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Lookout::Equality
4
+ class << self
5
+ def register(equality, *types)
6
+ eq = equality.new
7
+ types.each do |type|
8
+ equalities[type] = eq
9
+ end
10
+ end
11
+
12
+ def equal?(expected, actual)
13
+ self[expected].equal? expected, actual
14
+ end
15
+
16
+ def message(expected, actual)
17
+ self[expected].message expected, actual
18
+ end
19
+
20
+ def diff(expected, actual)
21
+ self[expected].diff expected, actual
22
+ end
23
+
24
+ private
25
+
26
+ def [](expected)
27
+ equalities[expected.class.ancestors.find{ |type| equalities[type] }]
28
+ end
29
+
30
+ def equalities
31
+ @equalities ||= {}
32
+ end
33
+ end
34
+ end
35
+
36
+ class Lookout::Equality::Object
37
+ Lookout::Equality.register self, Object
38
+
39
+ def equal?(expected, actual)
40
+ expected == actual
41
+ end
42
+
43
+ def message(expected, actual)
44
+ format = format(expected, actual)
45
+ return format unless diff = diff(expected, actual)
46
+ (diff.include?("\n") ? "%s\n%s" : '%s: %s') % [format, diff]
47
+ end
48
+
49
+ def diff(expected, actual)
50
+ end
51
+
52
+ private
53
+
54
+ def format(expected, actual)
55
+ '%p≠%p' % [actual, expected]
56
+ end
57
+ end
58
+
59
+ class Lookout::Equality::Includes < Lookout::Equality::Object
60
+ Lookout::Equality.register self, Module, Range, Regexp
61
+
62
+ def equal?(expected, actual)
63
+ expected === actual or expected == actual
64
+ end
65
+ end
66
+
67
+ class Lookout::Equality::Boolean < Lookout::Equality::Object
68
+ Lookout::Equality.register self, TrueClass, FalseClass
69
+
70
+ def equal?(expected, actual)
71
+ expected == !!actual
72
+ end
73
+ end
74
+
75
+ class Lookout::Equality::String < Lookout::Equality::Object
76
+ Lookout::Equality.register self, String
77
+
78
+ def diff(expected, actual)
79
+ return unless String === actual
80
+ (expected.include? "\n" or actual.include? "\n") ?
81
+ Lookout::Diff::Formats::Unified.
82
+ new(Lookout::Diff::Groups.
83
+ new(Lookout::Diff::Operations.
84
+ new(Lookout::Diff::Algorithms::Difflib.
85
+ new(actual.split("\n"),
86
+ expected.split("\n"))))).to_a.join("\n") :
87
+ Lookout::Diff::Formats::Inline.
88
+ new(Lookout::Diff::Operations.
89
+ new(Lookout::Diff::Algorithms::Difflib.new(actual, expected))).to_s
90
+ end
91
+ end
92
+
93
+ class Lookout::Equality::Array < Lookout::Equality::Object
94
+ Lookout::Equality.register self, Array
95
+
96
+ def equal?(expected, actual)
97
+ return false unless Array === actual and expected.size == actual.size
98
+ expected.each_with_index do |v, i|
99
+ return false unless Lookout::Equality.equal? v, actual[i]
100
+ end
101
+ true
102
+ end
103
+
104
+ def diff(expected, actual)
105
+ return if expected.size == 1 or not Array === actual
106
+ Lookout::Diff::Formats::Unified.
107
+ new(Lookout::Diff::Groups.
108
+ new(Lookout::Diff::Operations.
109
+ new(Lookout::Diff::Algorithms::Difflib.
110
+ new(actual, expected)))).to_a.join("\n")
111
+ end
112
+ end
113
+
114
+ class Lookout::Equality::Hash < Lookout::Equality::Object
115
+ Lookout::Equality.register self, Hash
116
+
117
+ def equal?(expected, actual)
118
+ return false unless Hash === actual and expected.size == actual.size
119
+ expected.all?{ |k, v| Lookout::Equality.equal? v, actual[k] }
120
+ end
121
+
122
+ def diff(expected, actual)
123
+ return if expected.size == 1 or not Hash === actual
124
+ Lookout::Diff::Formats::Hash.
125
+ new(Lookout::Diff::Operations.
126
+ new(Lookout::Diff::Algorithms::Difflib.
127
+ new(array(actual), array(expected)))).to_a.join("\n")
128
+ end
129
+
130
+ private
131
+
132
+ def array(hash)
133
+ hash.to_a.sort_by{ |k, v| k }.map{ |k, v| '%p => %p' % [k, v] }
134
+ end
135
+ end
136
+
137
+ class Lookout::Equality::StandardError < Lookout::Equality::Object
138
+ Lookout::Equality.register self, ::StandardError
139
+
140
+ def equal?(expected, actual)
141
+ expected.equal?(actual) or
142
+ ((actual.respond_to? :message rescue false) and
143
+ ((Regexp === expected.message and expected.message === actual.message) or
144
+ expected.message == actual.message))
145
+ end
146
+
147
+ def diff(expected, actual)
148
+ return super unless String === expected.message and
149
+ StandardError === actual and (actual.respond_to? :message rescue false)
150
+ Lookout::Equality.diff(expected.message, actual.message)
151
+ end
152
+
153
+ private
154
+
155
+ def format(expected, actual)
156
+ Regexp === expected.message ?
157
+ '%p≠#<%s: %p>' % [actual, expected.class, expected.message] :
158
+ super
159
+ end
160
+ end
161
+
162
+ class Lookout::Equality::Output < Lookout::Equality::Object
163
+ Lookout::Equality.register self, Lookout::Output
164
+
165
+ def equal?(expected, _actual)
166
+ expected.expected == expected.actual
167
+ end
168
+
169
+ def diff(expected, _actual)
170
+ Lookout::Equality.diff(expected.expected, expected.actual)
171
+ end
172
+
173
+ private
174
+
175
+ def format(expected, _actual)
176
+ '%p≠%p' % [Lookout::Output.new(expected.actual), expected]
177
+ end
178
+ end