mspec 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +22 -0
- data/README +101 -0
- data/Rakefile +44 -0
- data/bin/mkspec +7 -0
- data/bin/mspec +7 -0
- data/bin/mspec-ci +8 -0
- data/bin/mspec-run +8 -0
- data/bin/mspec-tag +8 -0
- data/lib/mspec.rb +6 -0
- data/lib/mspec/commands/mkspec.rb +147 -0
- data/lib/mspec/commands/mspec-ci.rb +71 -0
- data/lib/mspec/commands/mspec-run.rb +80 -0
- data/lib/mspec/commands/mspec-tag.rb +87 -0
- data/lib/mspec/commands/mspec.rb +143 -0
- data/lib/mspec/expectations.rb +2 -0
- data/lib/mspec/expectations/expectations.rb +12 -0
- data/lib/mspec/expectations/should.rb +23 -0
- data/lib/mspec/guards.rb +13 -0
- data/lib/mspec/guards/bug.rb +27 -0
- data/lib/mspec/guards/compliance.rb +18 -0
- data/lib/mspec/guards/conflict.rb +16 -0
- data/lib/mspec/guards/endian.rb +40 -0
- data/lib/mspec/guards/extensions.rb +12 -0
- data/lib/mspec/guards/guard.rb +120 -0
- data/lib/mspec/guards/noncompliance.rb +12 -0
- data/lib/mspec/guards/platform.rb +38 -0
- data/lib/mspec/guards/quarantine.rb +15 -0
- data/lib/mspec/guards/runner.rb +30 -0
- data/lib/mspec/guards/superuser.rb +15 -0
- data/lib/mspec/guards/support.rb +12 -0
- data/lib/mspec/guards/version.rb +40 -0
- data/lib/mspec/helpers.rb +6 -0
- data/lib/mspec/helpers/bignum.rb +5 -0
- data/lib/mspec/helpers/const_lookup.rb +5 -0
- data/lib/mspec/helpers/flunk.rb +5 -0
- data/lib/mspec/helpers/io.rb +13 -0
- data/lib/mspec/helpers/scratch.rb +17 -0
- data/lib/mspec/helpers/tmp.rb +32 -0
- data/lib/mspec/matchers.rb +16 -0
- data/lib/mspec/matchers/base.rb +95 -0
- data/lib/mspec/matchers/be_ancestor_of.rb +24 -0
- data/lib/mspec/matchers/be_close.rb +27 -0
- data/lib/mspec/matchers/be_empty.rb +20 -0
- data/lib/mspec/matchers/be_false.rb +20 -0
- data/lib/mspec/matchers/be_kind_of.rb +24 -0
- data/lib/mspec/matchers/be_nil.rb +20 -0
- data/lib/mspec/matchers/be_true.rb +20 -0
- data/lib/mspec/matchers/complain.rb +56 -0
- data/lib/mspec/matchers/eql.rb +26 -0
- data/lib/mspec/matchers/equal.rb +26 -0
- data/lib/mspec/matchers/equal_utf16.rb +34 -0
- data/lib/mspec/matchers/include.rb +32 -0
- data/lib/mspec/matchers/output.rb +67 -0
- data/lib/mspec/matchers/output_to_fd.rb +71 -0
- data/lib/mspec/matchers/raise_error.rb +48 -0
- data/lib/mspec/mocks.rb +3 -0
- data/lib/mspec/mocks/mock.rb +123 -0
- data/lib/mspec/mocks/object.rb +28 -0
- data/lib/mspec/mocks/proxy.rb +112 -0
- data/lib/mspec/runner.rb +13 -0
- data/lib/mspec/runner/actions.rb +6 -0
- data/lib/mspec/runner/actions/debug.rb +17 -0
- data/lib/mspec/runner/actions/filter.rb +40 -0
- data/lib/mspec/runner/actions/gdb.rb +17 -0
- data/lib/mspec/runner/actions/tag.rb +97 -0
- data/lib/mspec/runner/actions/tally.rb +80 -0
- data/lib/mspec/runner/actions/timer.rb +22 -0
- data/lib/mspec/runner/filters.rb +4 -0
- data/lib/mspec/runner/filters/match.rb +22 -0
- data/lib/mspec/runner/filters/profile.rb +54 -0
- data/lib/mspec/runner/filters/regexp.rb +7 -0
- data/lib/mspec/runner/filters/tag.rb +29 -0
- data/lib/mspec/runner/formatters.rb +7 -0
- data/lib/mspec/runner/formatters/dotted.rb +81 -0
- data/lib/mspec/runner/formatters/html.rb +87 -0
- data/lib/mspec/runner/formatters/specdoc.rb +27 -0
- data/lib/mspec/runner/formatters/spinner.rb +89 -0
- data/lib/mspec/runner/formatters/summary.rb +8 -0
- data/lib/mspec/runner/formatters/unit.rb +25 -0
- data/lib/mspec/runner/formatters/yaml.rb +43 -0
- data/lib/mspec/runner/mspec.rb +232 -0
- data/lib/mspec/runner/object.rb +20 -0
- data/lib/mspec/runner/shared.rb +12 -0
- data/lib/mspec/runner/state.rb +116 -0
- data/lib/mspec/runner/tag.rb +20 -0
- data/lib/mspec/utils/name_map.rb +130 -0
- data/lib/mspec/utils/options.rb +344 -0
- data/lib/mspec/utils/script.rb +77 -0
- data/lib/mspec/version.rb +3 -0
- data/spec/commands/mkspec_spec.rb +321 -0
- data/spec/commands/mspec_ci_spec.rb +139 -0
- data/spec/commands/mspec_run_spec.rb +146 -0
- data/spec/commands/mspec_spec.rb +359 -0
- data/spec/commands/mspec_tag_spec.rb +131 -0
- data/spec/expectations/expectations_spec.rb +16 -0
- data/spec/expectations/should_spec.rb +99 -0
- data/spec/guards/bug_spec.rb +137 -0
- data/spec/guards/compliance_spec.rb +70 -0
- data/spec/guards/conflict_spec.rb +20 -0
- data/spec/guards/endian_spec.rb +42 -0
- data/spec/guards/extensions_spec.rb +36 -0
- data/spec/guards/guard_spec.rb +355 -0
- data/spec/guards/noncompliance_spec.rb +36 -0
- data/spec/guards/platform_spec.rb +84 -0
- data/spec/guards/quarantine_spec.rb +19 -0
- data/spec/guards/runner_spec.rb +75 -0
- data/spec/guards/superuser_spec.rb +22 -0
- data/spec/guards/support_spec.rb +22 -0
- data/spec/guards/version_spec.rb +133 -0
- data/spec/helpers/bignum_spec.rb +11 -0
- data/spec/helpers/const_lookup_spec.rb +19 -0
- data/spec/helpers/flunk_spec.rb +15 -0
- data/spec/helpers/io_spec.rb +34 -0
- data/spec/helpers/scratch_spec.rb +22 -0
- data/spec/helpers/tmp_spec.rb +72 -0
- data/spec/matchers/base_spec.rb +180 -0
- data/spec/matchers/be_ancestor_of_spec.rb +28 -0
- data/spec/matchers/be_close_spec.rb +46 -0
- data/spec/matchers/be_empty_spec.rb +26 -0
- data/spec/matchers/be_false_spec.rb +28 -0
- data/spec/matchers/be_kind_of_spec.rb +29 -0
- data/spec/matchers/be_nil_spec.rb +27 -0
- data/spec/matchers/be_true_spec.rb +28 -0
- data/spec/matchers/complain_spec.rb +52 -0
- data/spec/matchers/eql_spec.rb +33 -0
- data/spec/matchers/equal_spec.rb +33 -0
- data/spec/matchers/equal_utf16_spec.rb +47 -0
- data/spec/matchers/include_spec.rb +37 -0
- data/spec/matchers/output_spec.rb +74 -0
- data/spec/matchers/output_to_fd_spec.rb +33 -0
- data/spec/matchers/raise_error_spec.rb +56 -0
- data/spec/mocks/mock_spec.rb +272 -0
- data/spec/mocks/proxy_spec.rb +259 -0
- data/spec/runner/actions/debug_spec.rb +61 -0
- data/spec/runner/actions/filter_spec.rb +84 -0
- data/spec/runner/actions/gdb_spec.rb +61 -0
- data/spec/runner/actions/tag_spec.rb +253 -0
- data/spec/runner/actions/tally_spec.rb +107 -0
- data/spec/runner/actions/timer_spec.rb +42 -0
- data/spec/runner/filters/a.yaml +4 -0
- data/spec/runner/filters/b.yaml +11 -0
- data/spec/runner/filters/match_spec.rb +44 -0
- data/spec/runner/filters/profile_spec.rb +117 -0
- data/spec/runner/filters/regexp_spec.rb +13 -0
- data/spec/runner/filters/tag_spec.rb +77 -0
- data/spec/runner/formatters/dotted_spec.rb +184 -0
- data/spec/runner/formatters/html_spec.rb +191 -0
- data/spec/runner/formatters/specdoc_spec.rb +57 -0
- data/spec/runner/formatters/spinner_spec.rb +78 -0
- data/spec/runner/formatters/summary_spec.rb +29 -0
- data/spec/runner/formatters/unit_spec.rb +71 -0
- data/spec/runner/formatters/yaml_spec.rb +123 -0
- data/spec/runner/mspec_spec.rb +393 -0
- data/spec/runner/shared_spec.rb +41 -0
- data/spec/runner/state_spec.rb +535 -0
- data/spec/runner/tag_spec.rb +93 -0
- data/spec/runner/tags.txt +3 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/utils/name_map_spec.rb +178 -0
- data/spec/utils/options_spec.rb +862 -0
- data/spec/utils/script_spec.rb +240 -0
- metadata +217 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class BeAncestorOfMatcher
|
|
2
|
+
def initialize(expected)
|
|
3
|
+
@expected = expected
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def matches?(actual)
|
|
7
|
+
@actual = actual
|
|
8
|
+
@expected.ancestors.include? @actual
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def failure_message
|
|
12
|
+
["Expected #{@actual}", "to be an ancestor of #{@expected}"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def negative_failure_message
|
|
16
|
+
["Expected #{@actual}", "not to be an ancestor of #{@expected}"]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Object
|
|
21
|
+
def be_ancestor_of(expected)
|
|
22
|
+
BeAncestorOfMatcher.new(expected)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
TOLERANCE = 0.00003 unless Object.const_defined?(:TOLERANCE)
|
|
2
|
+
|
|
3
|
+
class BeCloseMatcher
|
|
4
|
+
def initialize(expected, tolerance)
|
|
5
|
+
@expected = expected
|
|
6
|
+
@tolerance = tolerance
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def matches?(actual)
|
|
10
|
+
@actual = actual
|
|
11
|
+
(@actual - @expected).abs < @tolerance
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def failure_message
|
|
15
|
+
["Expected #{@expected}", "to be within +/- #{@tolerance} of #{@actual}"]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def negative_failure_message
|
|
19
|
+
["Expected #{@expected}", "not to be within +/- #{@tolerance} of #{@actual}"]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Object
|
|
24
|
+
def be_close(expected, tolerance)
|
|
25
|
+
BeCloseMatcher.new(expected, tolerance)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class BeEmptyMatcher
|
|
2
|
+
def matches?(actual)
|
|
3
|
+
@actual = actual
|
|
4
|
+
@actual.empty?
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def failure_message
|
|
8
|
+
["Expected #{@actual.inspect}", "to be empty"]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def negative_failure_message
|
|
12
|
+
["Expected #{@actual.inspect}", "not to be empty"]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Object
|
|
17
|
+
def be_empty
|
|
18
|
+
BeEmptyMatcher.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class BeFalseMatcher
|
|
2
|
+
def matches?(actual)
|
|
3
|
+
@actual = actual
|
|
4
|
+
@actual == false
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def failure_message
|
|
8
|
+
["Expected #{@actual.inspect}", "to be false"]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def negative_failure_message
|
|
12
|
+
["Expected #{@actual.inspect}", "not to be false"]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Object
|
|
17
|
+
def be_false
|
|
18
|
+
BeFalseMatcher.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class BeKindOfMatcher
|
|
2
|
+
def initialize(expected)
|
|
3
|
+
@expected = expected
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def matches?(actual)
|
|
7
|
+
@actual = actual
|
|
8
|
+
@actual.is_a?(@expected)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def failure_message
|
|
12
|
+
["Expected #{@actual.inspect} (#{@actual.class})", "to be kind of #{@expected}"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def negative_failure_message
|
|
16
|
+
["Expected #{@actual.inspect} (#{@actual.class})", "not to be kind of #{@expected}"]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Object
|
|
21
|
+
def be_kind_of(expected)
|
|
22
|
+
BeKindOfMatcher.new(expected)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class BeNilMatcher
|
|
2
|
+
def matches?(actual)
|
|
3
|
+
@actual = actual
|
|
4
|
+
@actual.nil?
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def failure_message
|
|
8
|
+
["Expected #{@actual.inspect}", "to be nil"]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def negative_failure_message
|
|
12
|
+
["Expected #{@actual.inspect}", "not to be nil"]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Object
|
|
17
|
+
def be_nil
|
|
18
|
+
BeNilMatcher.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class BeTrueMatcher
|
|
2
|
+
def matches?(actual)
|
|
3
|
+
@actual = actual
|
|
4
|
+
@actual == true
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def failure_message
|
|
8
|
+
["Expected #{@actual.inspect}", "to be true"]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def negative_failure_message
|
|
12
|
+
["Expected #{@actual.inspect}", "not to be true"]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Object
|
|
17
|
+
def be_true
|
|
18
|
+
BeTrueMatcher.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'mspec/helpers/io'
|
|
2
|
+
|
|
3
|
+
class ComplainMatcher
|
|
4
|
+
def initialize(complaint)
|
|
5
|
+
@complaint = complaint
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def matches?(proc)
|
|
9
|
+
@saved_err = $stderr
|
|
10
|
+
@stderr = $stderr = IOStub.new
|
|
11
|
+
@verbose = $VERBOSE
|
|
12
|
+
$VERBOSE = false
|
|
13
|
+
|
|
14
|
+
proc.call
|
|
15
|
+
|
|
16
|
+
unless @complaint.nil?
|
|
17
|
+
case @complaint
|
|
18
|
+
when Regexp
|
|
19
|
+
return false unless $stderr =~ @complaint
|
|
20
|
+
else
|
|
21
|
+
return false unless $stderr == @complaint
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
return $stderr.empty? ? false : true
|
|
26
|
+
ensure
|
|
27
|
+
$VERBOSE = @verbose
|
|
28
|
+
$stderr = @saved_err
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def failure_message
|
|
32
|
+
if @complaint.nil?
|
|
33
|
+
["Expected a warning", "but received none"]
|
|
34
|
+
elsif @complaint.kind_of? Regexp
|
|
35
|
+
["Expected warning to match:", @complaint.inspect]
|
|
36
|
+
else
|
|
37
|
+
["Expected warning: #{@complaint.inspect}", "but got: #{@stderr.chomp.inspect}"]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def negative_failure_message
|
|
42
|
+
if @complaint.nil?
|
|
43
|
+
["Unexpected warning: ", @stderr.chomp.inspect]
|
|
44
|
+
elsif @complaint.kind_of? Regexp
|
|
45
|
+
["Expected warning not to match:", @complaint.inspect]
|
|
46
|
+
else
|
|
47
|
+
["Expected warning: #{@complaint.inspect}", "but got: #{@stderr.chomp.inspect}"]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class Object
|
|
53
|
+
def complain(complaint=nil)
|
|
54
|
+
ComplainMatcher.new(complaint)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class EqlMatcher
|
|
2
|
+
def initialize(expected)
|
|
3
|
+
@expected = expected
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def matches?(actual)
|
|
7
|
+
@actual = actual
|
|
8
|
+
@actual.eql?(@expected)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def failure_message
|
|
12
|
+
["Expected #{@actual.pretty_inspect}",
|
|
13
|
+
"to have same value and type as #{@expected.pretty_inspect}"]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def negative_failure_message
|
|
17
|
+
["Expected #{@actual.pretty_inspect}",
|
|
18
|
+
"not to have same value or type as #{@expected.pretty_inspect}"]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Object
|
|
23
|
+
def eql(expected)
|
|
24
|
+
EqlMatcher.new(expected)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class EqualMatcher
|
|
2
|
+
def initialize(expected)
|
|
3
|
+
@expected = expected
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def matches?(actual)
|
|
7
|
+
@actual = actual
|
|
8
|
+
@actual.equal?(@expected)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def failure_message
|
|
12
|
+
["Expected #{@actual.pretty_inspect}",
|
|
13
|
+
"to be identical to #{@expected.pretty_inspect}"]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def negative_failure_message
|
|
17
|
+
["Expected #{@actual.pretty_inspect}",
|
|
18
|
+
"not to be identical to #{@expected.pretty_inspect}"]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Object
|
|
23
|
+
def equal(expected)
|
|
24
|
+
EqualMatcher.new(expected)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class EqualUtf16Matcher
|
|
2
|
+
def initialize(expected)
|
|
3
|
+
@expected = expected
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def matches?(actual)
|
|
7
|
+
@actual = actual
|
|
8
|
+
@actual == @expected || @actual == expected_swapped
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def expected_swapped
|
|
12
|
+
if @expected.respond_to?(:to_str)
|
|
13
|
+
@expected_swapped ||= @expected.to_str.gsub(/(.)(.)/, '\2\1')
|
|
14
|
+
else
|
|
15
|
+
@expected_swapped ||= @expected.collect { |s| s.to_str.gsub(/(.)(.)/, '\2\1') }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def failure_message
|
|
20
|
+
["Expected #{@actual.pretty_inspect}",
|
|
21
|
+
"to equal #{@expected.pretty_inspect} or #{expected_swapped.pretty_inspect}"]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def negative_failure_message
|
|
25
|
+
["Expected #{@actual.pretty_inspect}",
|
|
26
|
+
"not to equal #{@expected.pretty_inspect} nor #{expected_swapped.pretty_inspect}"]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class Object
|
|
31
|
+
def equal_utf16(expected)
|
|
32
|
+
EqualUtf16Matcher.new(expected)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class IncludeMatcher
|
|
2
|
+
def initialize(*expected)
|
|
3
|
+
@expected = expected
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def matches?(actual)
|
|
7
|
+
@actual = actual
|
|
8
|
+
@expected.each do |e|
|
|
9
|
+
@element = e
|
|
10
|
+
unless @actual.include?(e)
|
|
11
|
+
return false
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
return true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def failure_message
|
|
18
|
+
["Expected #{@actual.inspect}", "to include #{@element.inspect}"]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def negative_failure_message
|
|
22
|
+
["Expected #{@actual.inspect}", "not to include #{@element.inspect}"]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Cannot override #include at the toplevel in MRI
|
|
27
|
+
module MSpec
|
|
28
|
+
def include(*expected)
|
|
29
|
+
IncludeMatcher.new(*expected)
|
|
30
|
+
end
|
|
31
|
+
module_function :include
|
|
32
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'mspec/helpers/io'
|
|
2
|
+
|
|
3
|
+
class OutputMatcher
|
|
4
|
+
def initialize(stdout, stderr)
|
|
5
|
+
@out = stdout
|
|
6
|
+
@err = stderr
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def matches?(proc)
|
|
10
|
+
@saved_out = $stdout
|
|
11
|
+
@saved_err = $stderr
|
|
12
|
+
@stdout = $stdout = IOStub.new
|
|
13
|
+
@stderr = $stderr = IOStub.new
|
|
14
|
+
|
|
15
|
+
proc.call
|
|
16
|
+
|
|
17
|
+
unless @out.nil?
|
|
18
|
+
case @out
|
|
19
|
+
when Regexp
|
|
20
|
+
return false unless $stdout =~ @out
|
|
21
|
+
else
|
|
22
|
+
return false unless $stdout == @out
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
unless @err.nil?
|
|
27
|
+
case @err
|
|
28
|
+
when Regexp
|
|
29
|
+
return false unless $stderr =~ @err
|
|
30
|
+
else
|
|
31
|
+
return false unless $stderr == @err
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
return true
|
|
36
|
+
ensure
|
|
37
|
+
$stdout = @saved_out
|
|
38
|
+
$stderr = @saved_err
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def failure_message
|
|
42
|
+
expected_out = "\n"
|
|
43
|
+
actual_out = "\n"
|
|
44
|
+
unless @out.nil?
|
|
45
|
+
expected_out << " $stdout: #{@out.inspect}\n"
|
|
46
|
+
actual_out << " $stdout: #{@stdout.chomp.inspect}\n"
|
|
47
|
+
end
|
|
48
|
+
unless @err.nil?
|
|
49
|
+
expected_out << " $stderr: #{@err.inspect}\n"
|
|
50
|
+
actual_out << " $stderr: #{@stderr.chomp.inspect}\n"
|
|
51
|
+
end
|
|
52
|
+
["Expected:#{expected_out}", " got:#{actual_out}"]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def negative_failure_message
|
|
56
|
+
out = ""
|
|
57
|
+
out << " $stdout: #{@stdout.chomp.dump}\n" unless @out.nil?
|
|
58
|
+
out << " $stderr: #{@stderr.chomp.dump}\n" unless @err.nil?
|
|
59
|
+
["Expected output not to be:\n", out]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class Object
|
|
64
|
+
def output(stdout=nil, stderr=nil)
|
|
65
|
+
OutputMatcher.new(stdout, stderr)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'mspec/helpers/tmp'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
# Lower-level output speccing mechanism for a single
|
|
5
|
+
# output stream. Unlike OutputMatcher which provides
|
|
6
|
+
# methods to capture the output, we actually replace
|
|
7
|
+
# the FD itself so that there is no reliance on a
|
|
8
|
+
# certain method being used.
|
|
9
|
+
class OutputToFDMatcher
|
|
10
|
+
def initialize(expected, to)
|
|
11
|
+
@to, @expected = to, expected
|
|
12
|
+
|
|
13
|
+
case @to
|
|
14
|
+
when STDOUT
|
|
15
|
+
@to_name = "STDOUT"
|
|
16
|
+
when STDERR
|
|
17
|
+
@to_name = "STDERR"
|
|
18
|
+
when IO
|
|
19
|
+
@to_name = @to.object_id.to_s
|
|
20
|
+
else
|
|
21
|
+
raise ArgumentError, "#{@to.inspect} is not a supported output target"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def matches?(block)
|
|
26
|
+
old_to = @to.dup
|
|
27
|
+
out = File.open(tmp("mspec_output_to_#{$$}_#{Time.now.to_i}"), 'w+')
|
|
28
|
+
|
|
29
|
+
# Replacing with a file handle so that Readline etc. work
|
|
30
|
+
@to.reopen out
|
|
31
|
+
|
|
32
|
+
block.call
|
|
33
|
+
|
|
34
|
+
ensure
|
|
35
|
+
begin
|
|
36
|
+
@to.reopen old_to
|
|
37
|
+
|
|
38
|
+
out.rewind
|
|
39
|
+
@actual = out.read
|
|
40
|
+
|
|
41
|
+
case @expected
|
|
42
|
+
when Regexp
|
|
43
|
+
return !(@actual =~ @expected).nil?
|
|
44
|
+
else
|
|
45
|
+
return @actual == @expected
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Clean up
|
|
49
|
+
ensure
|
|
50
|
+
out.close unless out.closed?
|
|
51
|
+
FileUtils.rm out.path
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
return true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def failure_message()
|
|
58
|
+
["Expected (#{@to_name}): #{@expected.inspect}\n",
|
|
59
|
+
"#{'but got'.rjust(@to_name.length + 10)}: #{@actual.inspect}\nBacktrace"]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def negative_failure_message()
|
|
63
|
+
["Expected output (#{@to_name}) to NOT be:\n", @actual.inspect]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class Object
|
|
68
|
+
def output_to_fd(what, where = STDOUT)
|
|
69
|
+
OutputToFDMatcher.new what, where
|
|
70
|
+
end
|
|
71
|
+
end
|