recog 3.1.1 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Gemfile +6 -0
  4. data/Rakefile +7 -5
  5. data/lib/recog/db.rb +67 -68
  6. data/lib/recog/db_manager.rb +22 -21
  7. data/lib/recog/fingerprint/regexp_factory.rb +10 -13
  8. data/lib/recog/fingerprint/test.rb +9 -8
  9. data/lib/recog/fingerprint.rb +252 -262
  10. data/lib/recog/fingerprint_parse_error.rb +3 -1
  11. data/lib/recog/formatter.rb +41 -39
  12. data/lib/recog/match_reporter.rb +82 -83
  13. data/lib/recog/matcher.rb +37 -40
  14. data/lib/recog/matcher_factory.rb +7 -6
  15. data/lib/recog/nizer.rb +218 -224
  16. data/lib/recog/verifier.rb +30 -28
  17. data/lib/recog/verify_reporter.rb +69 -73
  18. data/lib/recog/version.rb +3 -1
  19. data/lib/recog.rb +2 -0
  20. data/recog/bin/recog_match +21 -20
  21. data/recog/xml/apache_modules.xml +2 -0
  22. data/recog/xml/dhcp_vendor_class.xml +1 -1
  23. data/recog/xml/favicons.xml +133 -1
  24. data/recog/xml/ftp_banners.xml +1 -1
  25. data/recog/xml/html_title.xml +140 -1
  26. data/recog/xml/http_cookies.xml +20 -2
  27. data/recog/xml/http_servers.xml +38 -17
  28. data/recog/xml/http_wwwauth.xml +17 -4
  29. data/recog/xml/mdns_device-info_txt.xml +49 -15
  30. data/recog/xml/sip_banners.xml +0 -2
  31. data/recog/xml/sip_user_agents.xml +1 -1
  32. data/recog/xml/snmp_sysdescr.xml +1 -2
  33. data/recog/xml/ssh_banners.xml +8 -0
  34. data/recog/xml/telnet_banners.xml +3 -2
  35. data/recog/xml/tls_jarm.xml +1 -1
  36. data/recog/xml/x11_banners.xml +1 -0
  37. data/recog/xml/x509_issuers.xml +1 -1
  38. data/recog/xml/x509_subjects.xml +0 -1
  39. data/recog.gemspec +14 -13
  40. data/spec/lib/recog/db_spec.rb +37 -36
  41. data/spec/lib/recog/fingerprint/regexp_factory_spec.rb +19 -20
  42. data/spec/lib/recog/fingerprint_spec.rb +44 -42
  43. data/spec/lib/recog/formatter_spec.rb +20 -18
  44. data/spec/lib/recog/match_reporter_spec.rb +35 -30
  45. data/spec/lib/recog/nizer_spec.rb +85 -101
  46. data/spec/lib/recog/verify_reporter_spec.rb +45 -44
  47. data/spec/spec_helper.rb +2 -1
  48. data.tar.gz.sig +1 -3
  49. metadata +3 -3
  50. metadata.gz.sig +0 -0
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'recog/db'
2
4
 
3
5
  describe Recog::DB do
4
-
5
- describe "#fingerprints" do
6
- context "with inline example content" do
6
+ describe '#fingerprints' do
7
+ context 'with inline example content' do
7
8
  let(:xml_file) { File.expand_path File.join('spec', 'data', 'test_fingerprints.xml') }
8
9
  subject { Recog::DB.new(xml_file) }
9
10
 
@@ -11,50 +12,50 @@ describe Recog::DB do
11
12
 
12
13
  it { is_expected.to be_a(Enumerable) }
13
14
 
14
- context "with only a pattern" do
15
+ context 'with only a pattern' do
15
16
  subject(:entry) { described_class.new(xml_file).fingerprints[0] }
16
17
 
17
- it "has a blank name with no description" do
18
+ it 'has a blank name with no description' do
18
19
  expect(entry.name).to be_empty
19
20
  end
20
21
 
21
- it "has a pattern" do
22
- expect(entry.regex.source).to eq(".*\\(iSeries\\).*")
22
+ it 'has a pattern' do
23
+ expect(entry.regex.source).to eq('.*\\(iSeries\\).*')
23
24
  end
24
25
 
25
- it "has no params" do
26
+ it 'has no params' do
26
27
  expect(entry.params).to be_empty
27
28
  end
28
29
 
29
- it "has no tests" do
30
+ it 'has no tests' do
30
31
  expect(entry.tests).to be_empty
31
32
  end
32
33
  end
33
34
 
34
- context "with params" do
35
+ context 'with params' do
35
36
  subject(:entry) { described_class.new(xml_file).fingerprints[1] }
36
37
 
37
- it "has a name" do
38
+ it 'has a name' do
38
39
  expect(entry.name).to eq('PalmOS')
39
40
  end
40
41
 
41
- it "has a pattern" do
42
- expect(entry.regex.source).to eq(".*\\(PalmOS\\).*")
42
+ it 'has a pattern' do
43
+ expect(entry.regex.source).to eq('.*\\(PalmOS\\).*')
43
44
  end
44
45
 
45
- it "has params" do
46
- expect(entry.params).to eq({"os.vendor"=>[1, "Palm"], "os.device"=>[2, "General"]})
46
+ it 'has params' do
47
+ expect(entry.params).to eq({ 'os.vendor' => [1, 'Palm'], 'os.device' => [2, 'General'] })
47
48
  end
48
49
 
49
- it "has no tests" do
50
+ it 'has no tests' do
50
51
  expect(entry.tests).to be_empty
51
52
  end
52
53
  end
53
54
 
54
- context "with pattern flags" do
55
+ context 'with pattern flags' do
55
56
  subject(:entry) { described_class.new(xml_file).fingerprints[2] }
56
57
 
57
- it "has a name and only uses the first value" do
58
+ it 'has a name and only uses the first value' do
58
59
  expect(entry.name).to eq('HP Designjet printer')
59
60
  end
60
61
 
@@ -63,57 +64,57 @@ describe Recog::DB do
63
64
  expect(entry.regex.options).to eq(Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::IGNORECASE)
64
65
  end
65
66
 
66
- it "has a pattern" do
67
+ it 'has a pattern' do
67
68
  expect(entry.regex).to be_a(Regexp)
68
- expect(entry.regex.source).to eq("(designjet \\S+)")
69
+ expect(entry.regex.source).to eq('(designjet \\S+)')
69
70
  end
70
71
 
71
- it "has params" do
72
- expect(entry.params).to eq({"service.vendor"=>[0, "HP"]})
72
+ it 'has params' do
73
+ expect(entry.params).to eq({ 'service.vendor' => [0, 'HP'] })
73
74
  end
74
75
 
75
- it "has no tests" do
76
+ it 'has no tests' do
76
77
  expect(entry.tests).to be_empty
77
78
  end
78
79
  end
79
80
 
80
- context "with test" do
81
+ context 'with test' do
81
82
  subject(:entry) { described_class.new(xml_file).fingerprints[3] }
82
83
 
83
- it "has a name" do
84
+ it 'has a name' do
84
85
  expect(entry.name).to eq('HP JetDirect Printer')
85
86
  end
86
87
 
87
- it "has a pattern" do
88
- expect(entry.regex.source).to eq("laserjet (.*)(?: series)?")
88
+ it 'has a pattern' do
89
+ expect(entry.regex.source).to eq('laserjet (.*)(?: series)?')
89
90
  end
90
91
 
91
- it "has params" do
92
- expect(entry.params).to eq({"service.vendor"=>[0, "HP"]})
92
+ it 'has params' do
93
+ expect(entry.params).to eq({ 'service.vendor' => [0, 'HP'] })
93
94
  end
94
95
 
95
- it "has tests" do
96
- expect(entry.tests.map(&:content)).to match_array(["HP LaserJet 4100 Series", "HP LaserJet 2200"])
96
+ it 'has tests' do
97
+ expect(entry.tests.map(&:content)).to match_array(['HP LaserJet 4100 Series', 'HP LaserJet 2200'])
97
98
  end
98
99
  end
99
100
  end
100
101
 
101
- context "with external example content" do
102
+ context 'with external example content' do
102
103
  let(:xml_file) { File.expand_path File.join('spec', 'data', 'external_example_fingerprint.xml') }
103
104
  subject { Recog::DB.new(xml_file) }
104
105
 
105
106
  subject(:entry) { described_class.new(xml_file).fingerprints[0] }
106
107
 
107
- it "has tests" do
108
- expect(entry.tests.map(&:content)).to match_array(["HP LaserJet 4100 Series", "HP LaserJet 2200"])
108
+ it 'has tests' do
109
+ expect(entry.tests.map(&:content)).to match_array(['HP LaserJet 4100 Series', 'HP LaserJet 2200'])
109
110
  end
110
111
  end
111
112
 
112
- context "with external example content illegal path" do
113
+ context 'with external example content illegal path' do
113
114
  let(:xml_file) { File.expand_path File.join('spec', 'data', 'external_example_illegal_path_fingerprint.xml') }
114
115
  subject { Recog::DB.new(xml_file) }
115
116
 
116
- it "raises an illegal file path error" do
117
+ it 'raises an illegal file path error' do
117
118
  expect { subject }.to raise_error(/an example specifies an illegal file path '.+'/)
118
119
  end
119
120
  end
@@ -1,12 +1,12 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require 'recog/fingerprint/regexp_factory'
3
4
 
4
5
  describe Recog::Fingerprint::RegexpFactory do
5
-
6
6
  describe 'FLAG_MAP' do
7
7
  subject { described_class::FLAG_MAP }
8
8
 
9
- it "should have the right number of flags" do
9
+ it 'should have the right number of flags' do
10
10
  expect(subject.size).to be 5
11
11
  end
12
12
  end
@@ -15,56 +15,55 @@ describe Recog::Fingerprint::RegexpFactory do
15
15
  subject { described_class.build(pattern, options) }
16
16
 
17
17
  let(:pattern) { 'Apache/(\d+)' }
18
- let(:options) { [ 'REG_ICASE' ] }
18
+ let(:options) { ['REG_ICASE'] }
19
19
 
20
20
  it { is_expected.to be_a(Regexp) }
21
21
  it { is_expected.to match('Apache/2') }
22
-
23
22
  end
24
23
 
25
24
  describe '.build_options' do
26
25
  subject { described_class.build_options(flags) }
27
26
 
28
- let(:flags) { [ ] }
27
+ let(:flags) { [] }
29
28
  it { is_expected.to be_a(Integer) }
30
29
 
31
30
  context 'without any explicit flags' do
32
- let(:flags) { [ ] }
33
- specify "sets default flags" do
31
+ let(:flags) { [] }
32
+ specify 'sets default flags' do
34
33
  expect(subject).to be Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS
35
34
  end
36
35
  end
37
36
 
38
37
  context 'with REG_ICASE' do
39
- let(:flags) { [ 'REG_ICASE' ] }
40
- specify "sets IGNORECASE" do
41
- expect(subject).to be (Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::IGNORECASE)
38
+ let(:flags) { ['REG_ICASE'] }
39
+ specify 'sets IGNORECASE' do
40
+ expect(subject).to be(Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::IGNORECASE)
42
41
  end
43
42
  end
44
43
 
45
44
  context 'with REG_DOT_NEWLINE' do
46
- let(:flags) { [ 'REG_DOT_NEWLINE' ] }
47
- specify "sets MULTILINE" do
48
- expect(subject).to be (Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::MULTILINE)
45
+ let(:flags) { ['REG_DOT_NEWLINE'] }
46
+ specify 'sets MULTILINE' do
47
+ expect(subject).to be(Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::MULTILINE)
49
48
  end
50
49
  end
51
50
 
52
51
  context 'with REG_LINE_ANY_CRLF' do
53
- let(:flags) { [ 'REG_LINE_ANY_CRLF' ] }
54
- specify "sets MULTILINE" do
55
- expect(subject).to be (Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::MULTILINE)
52
+ let(:flags) { ['REG_LINE_ANY_CRLF'] }
53
+ specify 'sets MULTILINE' do
54
+ expect(subject).to be(Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::MULTILINE)
56
55
  end
57
56
  end
58
57
 
59
58
  context 'with multiple flags' do
60
- let(:flags) { [ 'REG_LINE_ANY_CRLF', 'REG_ICASE' ] }
61
- specify "sets correct flags" do
62
- expect(subject).to be (Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::MULTILINE | Regexp::IGNORECASE)
59
+ let(:flags) { %w[REG_LINE_ANY_CRLF REG_ICASE] }
60
+ specify 'sets correct flags' do
61
+ expect(subject).to be(Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::MULTILINE | Regexp::IGNORECASE)
63
62
  end
64
63
  end
65
64
 
66
65
  context 'with invalid flags' do
67
- let(:flags) { %w(SYN ACK FIN) } # oh, wrong flags!
66
+ let(:flags) { %w[SYN ACK FIN] } # oh, wrong flags!
68
67
  specify 'raises and lists supported/unsupported flags' do
69
68
  expect { subject }.to raise_error(/SYN,ACK,FIN. Must be one of: .+/)
70
69
  end
@@ -1,112 +1,114 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
2
4
  require 'recog/fingerprint'
3
5
 
4
6
  describe Recog::Fingerprint do
5
- context "whitespace" do
7
+ context 'whitespace' do
6
8
  let(:xml) do
7
9
  path = File.expand_path(File.join('spec', 'data', 'whitespaced_fingerprint.xml'))
8
10
  doc = Nokogiri::XML(IO.read(path))
9
- doc.xpath("//fingerprint").first
11
+ doc.xpath('//fingerprint').first
10
12
  end
11
13
  subject { Recog::Fingerprint.new(xml) }
12
14
 
13
- describe "#name" do
14
- it "properly squashes whitespace" do
15
+ describe '#name' do
16
+ it 'properly squashes whitespace' do
15
17
  expect(subject.name).to eq('I love whitespace!')
16
18
  end
17
19
  end
18
20
  end
19
21
 
20
- describe "#verification" do
22
+ describe '#verification' do
21
23
  let(:xml_file) { File.expand_path(File.join('spec', 'data', 'verification_fingerprints.xml')) }
22
24
  let(:doc) { Nokogiri::XML(IO.read(xml_file)) }
23
25
 
24
- context "0 params" do
25
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[0]) }
26
+ context '0 params' do
27
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[0]) }
26
28
 
27
- it "does not yield if a fingerprint has 0 parameters" do
29
+ it 'does not yield if a fingerprint has 0 parameters' do
28
30
  expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.not_to yield_control
29
31
  end
30
32
  end
31
33
 
32
- context "0 capture groups" do
33
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[1]) }
34
+ context '0 capture groups' do
35
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[1]) }
34
36
 
35
- it "does not yield if a fingerprint has parameters, but 0 are defined by a capture group " do
37
+ it 'does not yield if a fingerprint has parameters, but 0 are defined by a capture group ' do
36
38
  expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.not_to yield_control
37
39
  end
38
40
  end
39
41
 
40
- context "0 examples" do
41
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[2]) }
42
+ context '0 examples' do
43
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[2]) }
42
44
 
43
- it "does not yield if a fingerprint has 0 examples" do
45
+ it 'does not yield if a fingerprint has 0 examples' do
44
46
  expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.not_to yield_control
45
47
  end
46
48
  end
47
49
 
48
- context "1 capture group, 1 example" do
49
-
50
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[3]) }
50
+ context '1 capture group, 1 example' do
51
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[3]) }
51
52
 
52
- it "does not yield when one capture group parameter is tested for in one example" do
53
+ it 'does not yield when one capture group parameter is tested for in one example' do
53
54
  expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.not_to yield_control
54
55
  end
55
56
  end
56
57
 
57
- context "2 capture groups, 1 example" do
58
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[4]) }
58
+ context '2 capture groups, 1 example' do
59
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[4]) }
59
60
 
60
- it "does not yield when two capture group parameters are tested for in one example" do
61
+ it 'does not yield when two capture group parameters are tested for in one example' do
61
62
  expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.not_to yield_control
62
63
  end
63
64
  end
64
65
 
65
- context "2 capture groups, 2 examples, 1 in each" do
66
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[5]) }
66
+ context '2 capture groups, 2 examples, 1 in each' do
67
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[5]) }
67
68
 
68
- it "does not yield when two capture group parameters are tested for in two examples, one parameter in each" do
69
+ it 'does not yield when two capture group parameters are tested for in two examples, one parameter in each' do
69
70
  expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.not_to yield_control
70
71
  end
71
72
  end
72
73
 
73
- context "1 missing capture group, 1 example" do
74
-
75
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[6]) }
74
+ context '1 missing capture group, 1 example' do
75
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[6]) }
76
76
 
77
- it "identifies when a parameter defined by a capture group is not included in one example" do
77
+ it 'identifies when a parameter defined by a capture group is not included in one example' do
78
78
  expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:fail, String])
79
79
  end
80
80
  end
81
81
 
82
- context "2 missing capture groups, 1 example" do
83
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[7]) }
82
+ context '2 missing capture groups, 1 example' do
83
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[7]) }
84
84
 
85
- it "identifies when two parameters defined by a capture groups are not included in one example" do
86
- expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:fail, String], [:fail, String])
85
+ it 'identifies when two parameters defined by a capture groups are not included in one example' do
86
+ expect do |unused|
87
+ entry.verify_tests_have_capture_groups(&unused)
88
+ end.to yield_successive_args([:fail, String], [:fail, String])
87
89
  end
88
90
  end
89
91
 
90
- context "1 missing capture group, 2 examples" do
92
+ context '1 missing capture group, 2 examples' do
93
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[8]) }
91
94
 
92
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[8]) }
93
-
94
- it "identifies when a parameter defined by a capture group is not included in one example" do
95
+ it 'identifies when a parameter defined by a capture group is not included in one example' do
95
96
  expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:fail, String])
96
97
  end
97
98
  end
98
99
 
99
- context "2 missing capture groups, 2 examples" do
100
- let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[9]) }
100
+ context '2 missing capture groups, 2 examples' do
101
+ let(:entry) { described_class.new(doc.xpath('//fingerprints/fingerprint')[9]) }
101
102
 
102
- it "identifies when two parameters defined by a capture groups are not included in one example" do
103
- expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:fail, String], [:fail, String])
103
+ it 'identifies when two parameters defined by a capture groups are not included in one example' do
104
+ expect do |unused|
105
+ entry.verify_tests_have_capture_groups(&unused)
106
+ end.to yield_successive_args([:fail, String], [:fail, String])
104
107
  end
105
108
  end
106
-
107
109
  end
108
110
 
109
- skip "value interpolation" do
111
+ skip 'value interpolation' do
110
112
  # TODO
111
113
  end
112
114
  end
@@ -1,66 +1,68 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'recog/formatter'
2
4
 
3
5
  describe Recog::Formatter do
4
6
  let(:output) { StringIO.new }
5
7
 
6
- context "with no color" do
8
+ context 'with no color' do
7
9
  subject { Recog::Formatter.new(double(color: false), output) }
8
10
 
9
- describe "#message" do
10
- it "outputs the text" do
11
+ describe '#message' do
12
+ it 'outputs the text' do
11
13
  subject.status_message 'some text'
12
14
  expect(output.string).to eq("some text\n")
13
15
  end
14
16
  end
15
17
 
16
- describe "#success_message" do
17
- it "outputs the text" do
18
+ describe '#success_message' do
19
+ it 'outputs the text' do
18
20
  subject.success_message 'a success'
19
21
  expect(output.string).to eq("a success\n")
20
22
  end
21
23
  end
22
24
 
23
- describe "#warning_message" do
24
- it "outputs the text" do
25
+ describe '#warning_message' do
26
+ it 'outputs the text' do
25
27
  subject.warning_message 'a warning'
26
28
  expect(output.string).to eq("a warning\n")
27
29
  end
28
30
  end
29
31
 
30
- describe "#failure_message" do
31
- it "outputs the text" do
32
+ describe '#failure_message' do
33
+ it 'outputs the text' do
32
34
  subject.failure_message 'a failure'
33
35
  expect(output.string).to eq("a failure\n")
34
36
  end
35
37
  end
36
38
  end
37
39
 
38
- context "with color" do
40
+ context 'with color' do
39
41
  subject { Recog::Formatter.new(double(color: true), output) }
40
42
 
41
- describe "#message" do
42
- it "outputs the text in white" do
43
+ describe '#message' do
44
+ it 'outputs the text in white' do
43
45
  subject.status_message 'some text'
44
46
  expect(output.string).to eq("\e[15msome text\e[0m\n")
45
47
  end
46
48
  end
47
49
 
48
- describe "#success_message" do
49
- it "outputs the text in green" do
50
+ describe '#success_message' do
51
+ it 'outputs the text in green' do
50
52
  subject.success_message 'a success'
51
53
  expect(output.string).to eq("\e[32ma success\e[0m\n")
52
54
  end
53
55
  end
54
56
 
55
- describe "#warning_message" do
56
- it "outputs the text in yellow" do
57
+ describe '#warning_message' do
58
+ it 'outputs the text in yellow' do
57
59
  subject.warning_message 'a warning'
58
60
  expect(output.string).to eq("\e[33ma warning\e[0m\n")
59
61
  end
60
62
  end
61
63
 
62
- describe "#failure_message" do
63
- it "outputs the text in red" do
64
+ describe '#failure_message' do
65
+ it 'outputs the text in red' do
64
66
  subject.failure_message 'a failure'
65
67
  expect(output.string).to eq("\e[31ma failure\e[0m\n")
66
68
  end
@@ -1,103 +1,108 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'recog/match_reporter'
2
4
 
3
5
  describe Recog::MatchReporter do
4
- let(:options) { double(detail: false, json_format: false, quiet: false, multi_match: false) }
6
+ let(:options) { double(detail: false, json_format: false, quiet: false, multi_match: false) }
5
7
  let(:formatter) { double('formatter').as_null_object }
6
8
  subject { Recog::MatchReporter.new(options, formatter) }
7
9
 
8
10
  def run_report
9
11
  subject.report do
10
- subject.increment_line_count
11
- subject.match [{'data' => 'a match'}]
12
- subject.failure 'a failure'
12
+ subject.increment_line_count
13
+ subject.match [{ 'data' => 'a match' }]
14
+ subject.failure 'a failure'
13
15
  end
14
16
  end
15
17
 
16
- describe "#report" do
17
- it "prints matches" do
18
+ describe '#report' do
19
+ it 'prints matches' do
18
20
  expect(formatter).to receive(:success_message).with('MATCH: {"data"=>"a match"}')
19
21
  run_report
20
22
  end
21
23
 
22
- it "prints failures" do
24
+ it 'prints failures' do
23
25
  expect(formatter).to receive(:failure_message).with('FAIL: a failure')
24
26
  run_report
25
27
  end
26
28
 
27
- context "with detail" do
28
- subject { Recog::MatchReporter.new(double(detail: true, json_format: false, quiet: false, multi_match: false), formatter) }
29
+ context 'with detail' do
30
+ subject do
31
+ Recog::MatchReporter.new(double(detail: true, json_format: false, quiet: false, multi_match: false), formatter)
32
+ end
29
33
 
30
- it "prints the lines processed" do
34
+ it 'prints the lines processed' do
31
35
  expect(formatter).to receive(:status_message).with("\nProcessed 1 lines")
32
36
  run_report
33
37
  end
34
38
 
35
- it "prints summary" do
36
- expect(formatter).to receive(:failure_message).with("SUMMARY: 1 matches and 1 failures")
39
+ it 'prints summary' do
40
+ expect(formatter).to receive(:failure_message).with('SUMMARY: 1 matches and 1 failures')
37
41
  run_report
38
42
  end
39
43
  end
40
44
 
41
- context "with JSON" do
42
- subject { Recog::MatchReporter.new(double(detail: false, json_format: true, quiet: false, multi_match: false), formatter) }
45
+ context 'with JSON' do
46
+ subject do
47
+ Recog::MatchReporter.new(double(detail: false, json_format: true, quiet: false, multi_match: false), formatter)
48
+ end
43
49
 
44
- it "prints matches" do
50
+ it 'prints matches' do
45
51
  expect(formatter).to receive(:success_message).with('{"data":"a match","match":{}}')
46
52
  run_report
47
53
  end
48
54
 
49
- it "prints failures" do
55
+ it 'prints failures' do
50
56
  expect(formatter).to receive(:failure_message).with('{"data":"a failure","match_failure":true,"match":null}')
51
57
  run_report
52
58
  end
53
59
  end
54
60
  end
55
61
 
56
- describe "#print_summary" do
57
- context "with all matches" do
62
+ describe '#print_summary' do
63
+ context 'with all matches' do
58
64
  before { subject.match ['match'] }
59
65
 
60
- it "prints a successful summary" do
61
- msg = "SUMMARY: 1 matches and 0 failures"
66
+ it 'prints a successful summary' do
67
+ msg = 'SUMMARY: 1 matches and 0 failures'
62
68
  expect(formatter).to receive(:success_message).with(msg)
63
69
  subject.print_summary
64
70
  end
65
71
  end
66
72
 
67
- context "with failures" do
73
+ context 'with failures' do
68
74
  before { subject.failure 'fail' }
69
75
 
70
- it "prints a failure summary" do
71
- msg = "SUMMARY: 0 matches and 1 failures"
76
+ it 'prints a failure summary' do
77
+ msg = 'SUMMARY: 0 matches and 1 failures'
72
78
  expect(formatter).to receive(:failure_message).with(msg)
73
79
  subject.print_summary
74
80
  end
75
81
  end
76
82
  end
77
83
 
78
- describe "#stop?" do
79
- context "with a failure limit" do
80
-
84
+ describe '#stop?' do
85
+ context 'with a failure limit' do
81
86
  let(:options) { double(fail_fast: true, stop_after: 3, detail: false, json_format: false, multi_match: false) }
82
87
  before do
83
88
  subject.failure 'first'
84
89
  subject.failure 'second'
85
90
  end
86
91
 
87
- it "returns true when the limit is reached " do
92
+ it 'returns true when the limit is reached ' do
88
93
  subject.failure 'third'
89
94
  expect(subject.stop?).to be true
90
95
  end
91
96
 
92
- it "returns false when under the limit" do
97
+ it 'returns false when under the limit' do
93
98
  expect(subject.stop?).to be false
94
99
  end
95
100
  end
96
101
 
97
- context "with no failure limit" do
102
+ context 'with no failure limit' do
98
103
  let(:options) { double(fail_fast: false, detail: false, json_format: false, multi_match: false) }
99
104
 
100
- it "return false" do
105
+ it 'return false' do
101
106
  expect(subject.stop?).to be false
102
107
  end
103
108
  end