recog 2.3.22 → 2.3.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/.github/workflows/verify.yml +1 -1
- data/.vscode/bin/monitor-recog-fingerprints.sh +54 -0
- data/.vscode/extensions.json +5 -0
- data/.vscode/settings.json +8 -0
- data/.vscode/tasks.json +77 -0
- data/CONTRIBUTING.md +2 -0
- data/bin/recog_verify +42 -7
- data/cpe-remap.yaml +20 -2
- data/features/data/schema_failure.xml +4 -0
- data/features/data/tests_with_failures.xml +6 -0
- data/features/support/hooks.rb +9 -0
- data/features/verify.feature +81 -17
- data/identifiers/hw_device.txt +2 -0
- data/identifiers/hw_product.txt +2 -0
- data/identifiers/os_device.txt +2 -0
- data/identifiers/os_family.txt +1 -0
- data/identifiers/os_product.txt +8 -1
- data/identifiers/service_product.txt +14 -0
- data/identifiers/vendor.txt +13 -1
- data/lib/recog/fingerprint.rb +21 -7
- data/lib/recog/fingerprint_parse_error.rb +10 -0
- data/lib/recog/verifier.rb +4 -4
- data/lib/recog/verify_reporter.rb +7 -6
- data/lib/recog/version.rb +1 -1
- data/requirements.txt +1 -1
- data/spec/data/external_example_fingerprint/hp_printer_ex_01.txt +1 -0
- data/spec/data/external_example_fingerprint/hp_printer_ex_02.txt +1 -0
- data/spec/data/external_example_fingerprint.xml +8 -0
- data/spec/data/external_example_illegal_path_fingerprint.xml +7 -0
- data/spec/lib/recog/db_spec.rb +84 -61
- data/spec/lib/recog/fingerprint_spec.rb +4 -4
- data/spec/lib/recog/verify_reporter_spec.rb +8 -8
- data/update_cpes.py +129 -36
- data/xml/apache_os.xml +61 -19
- data/xml/architecture.xml +15 -1
- data/xml/dhcp_vendor_class.xml +1 -1
- data/xml/dns_versionbind.xml +16 -13
- data/xml/favicons.xml +87 -5
- data/xml/fingerprints.xsd +9 -1
- data/xml/ftp_banners.xml +131 -141
- data/xml/h323_callresp.xml +2 -2
- data/xml/hp_pjl_id.xml +81 -81
- data/xml/html_title.xml +178 -9
- data/xml/http_cookies.xml +83 -27
- data/xml/http_servers.xml +409 -269
- data/xml/http_wwwauth.xml +70 -37
- data/xml/imap_banners.xml +2 -2
- data/xml/nntp_banners.xml +8 -5
- data/xml/ntp_banners.xml +33 -33
- data/xml/operating_system.xml +92 -77
- data/xml/pop_banners.xml +17 -17
- data/xml/sip_banners.xml +16 -5
- data/xml/sip_user_agents.xml +122 -27
- data/xml/smb_native_lm.xml +5 -5
- data/xml/smb_native_os.xml +25 -25
- data/xml/smtp_banners.xml +132 -131
- data/xml/smtp_help.xml +1 -1
- data/xml/snmp_sysdescr.xml +1227 -1227
- data/xml/snmp_sysobjid.xml +2 -2
- data/xml/ssh_banners.xml +9 -5
- data/xml/telnet_banners.xml +49 -0
- data/xml/tls_jarm.xml +22 -2
- data/xml/x11_banners.xml +3 -3
- data/xml/x509_issuers.xml +3 -2
- data/xml/x509_subjects.xml +3 -3
- metadata +19 -3
- data/lib/recog/verifier_factory.rb +0 -13
@@ -20,6 +20,7 @@ Active Directory Controller
|
|
20
20
|
Active Intelligence Engine
|
21
21
|
ActiveMQ
|
22
22
|
AdGuard Home
|
23
|
+
Adminer
|
23
24
|
AirTunes
|
24
25
|
Airflow
|
25
26
|
Alteon Web Switch
|
@@ -30,6 +31,7 @@ Apache Tomcat HTTP Connector
|
|
30
31
|
AppleShare IP Mail Server
|
31
32
|
Application Load Balancer
|
32
33
|
Application Protection System, Enterprise
|
34
|
+
Application Server
|
33
35
|
Application Server Portal
|
34
36
|
Application Server Web Cache
|
35
37
|
Appweb
|
@@ -50,6 +52,7 @@ BlackJumboDog
|
|
50
52
|
BladeSystems
|
51
53
|
Boa
|
52
54
|
Bugzilla
|
55
|
+
CALDERA
|
53
56
|
CCProxy
|
54
57
|
CMS
|
55
58
|
CMS400.NET
|
@@ -90,6 +93,7 @@ CouchDB
|
|
90
93
|
Couchbase Server
|
91
94
|
Courier IMAP
|
92
95
|
Courier POP
|
96
|
+
Covenant
|
93
97
|
Cowboy
|
94
98
|
Coyote
|
95
99
|
Cross Web Server
|
@@ -194,6 +198,7 @@ HttpProxy
|
|
194
198
|
Hummingbird Exceed X server
|
195
199
|
IBM Domino
|
196
200
|
IIS
|
201
|
+
ILOM
|
197
202
|
IMail Server
|
198
203
|
IOS
|
199
204
|
IPVA
|
@@ -451,7 +456,9 @@ SmartDNS
|
|
451
456
|
SmartSense Tool
|
452
457
|
SmbFTPD
|
453
458
|
Snowball
|
459
|
+
Solr
|
454
460
|
SonarQube
|
461
|
+
Spark
|
455
462
|
SpeedTouch
|
456
463
|
Splunk
|
457
464
|
Squeezebox
|
@@ -473,6 +480,7 @@ TCPIP POP server
|
|
473
480
|
TUX Web Server
|
474
481
|
Tableau Server
|
475
482
|
TeamCity
|
483
|
+
TeamSpeak
|
476
484
|
Tengine
|
477
485
|
TestCenter IQ
|
478
486
|
Thin
|
@@ -531,6 +539,7 @@ WebGUI
|
|
531
539
|
WebLogic
|
532
540
|
WebServer
|
533
541
|
WebShield
|
542
|
+
WebSocket++
|
534
543
|
WebSphere
|
535
544
|
WebSphere Load Balancer
|
536
545
|
WebTrends
|
@@ -581,6 +590,7 @@ gSOAP
|
|
581
590
|
gdnsd
|
582
591
|
httpd
|
583
592
|
iLO
|
593
|
+
iPlanet Web Server
|
584
594
|
iScale
|
585
595
|
inetutils ftpd
|
586
596
|
ipGENADevice
|
@@ -590,6 +600,7 @@ libupnp
|
|
590
600
|
lighttpd
|
591
601
|
micro_httpd
|
592
602
|
mini_httpd
|
603
|
+
mitmproxy
|
593
604
|
mod_access
|
594
605
|
mod_access_compat
|
595
606
|
mod_actions
|
@@ -737,17 +748,20 @@ mod_vhost_alias
|
|
737
748
|
mod_watchdog
|
738
749
|
mod_wsgi
|
739
750
|
mod_xml2enc
|
751
|
+
mongo-express
|
740
752
|
nginx
|
741
753
|
noVNC
|
742
754
|
ntopng
|
743
755
|
ownCloud Server
|
744
756
|
perl
|
745
757
|
pfSense
|
758
|
+
phpMyAdmin
|
746
759
|
qmail
|
747
760
|
qpopper-mysql
|
748
761
|
raptor
|
749
762
|
rbldnsd
|
750
763
|
sfcb
|
764
|
+
sofia-sip
|
751
765
|
sshlib
|
752
766
|
thttpd
|
753
767
|
tnftpd
|
data/identifiers/vendor.txt
CHANGED
@@ -36,6 +36,7 @@ Accelerated Technology
|
|
36
36
|
AdGuard
|
37
37
|
Adaptec
|
38
38
|
AdminDroid
|
39
|
+
Adminer
|
39
40
|
Adobe
|
40
41
|
Adtran
|
41
42
|
Aerohive
|
@@ -227,6 +228,7 @@ Eclipse
|
|
227
228
|
Ektron
|
228
229
|
Elastic
|
229
230
|
Eltek
|
231
|
+
Eltex
|
230
232
|
EmbedThis
|
231
233
|
Embedthis
|
232
234
|
Emby
|
@@ -410,6 +412,7 @@ Lucent
|
|
410
412
|
Lynx Technology
|
411
413
|
Lyris
|
412
414
|
MBP Kommunikationssysteme GmbH
|
415
|
+
MITRE
|
413
416
|
MPI Technologies
|
414
417
|
MPS Software
|
415
418
|
MRV Communications
|
@@ -478,6 +481,7 @@ NetData
|
|
478
481
|
NetIQ
|
479
482
|
NetSarang Computer, Inc.
|
480
483
|
NetWin
|
484
|
+
Netgate
|
481
485
|
Netgear
|
482
486
|
Netia
|
483
487
|
Netopia
|
@@ -645,6 +649,7 @@ Segger
|
|
645
649
|
Sendmail
|
646
650
|
Sequent
|
647
651
|
Sercomm
|
652
|
+
SerenityOS
|
648
653
|
Serome Technology, Inc.
|
649
654
|
Serv-U
|
650
655
|
ServerTech
|
@@ -710,6 +715,7 @@ Tableau
|
|
710
715
|
Tandberg
|
711
716
|
Taobao
|
712
717
|
Tasman Networks
|
718
|
+
TeamSpeak
|
713
719
|
Technicolor
|
714
720
|
Tektronix
|
715
721
|
Teldat H. Kruszynski, M. Cichocki Sp. J.
|
@@ -732,6 +738,8 @@ Tinyproxy Project
|
|
732
738
|
Tivo
|
733
739
|
Tobit Software
|
734
740
|
Tokutek
|
741
|
+
Tomato
|
742
|
+
TomatoUSB
|
735
743
|
Tor Project
|
736
744
|
TornadoWeb
|
737
745
|
Toshiba
|
@@ -797,7 +805,7 @@ XAMPP
|
|
797
805
|
XFree86
|
798
806
|
XRoads
|
799
807
|
Xerox
|
800
|
-
Xiongmai
|
808
|
+
Xiongmai Technology
|
801
809
|
Xiph
|
802
810
|
Xiph.org
|
803
811
|
Xitami
|
@@ -812,6 +820,7 @@ Youngzsoft
|
|
812
820
|
ZMailer
|
813
821
|
ZTE
|
814
822
|
Zabbix
|
823
|
+
Zaphoyd Studios
|
815
824
|
ZebraNet
|
816
825
|
Zed Shaw
|
817
826
|
Zyxel
|
@@ -833,14 +842,17 @@ iXsystems
|
|
833
842
|
innovaphone
|
834
843
|
libssh
|
835
844
|
lighttpd
|
845
|
+
mitmproxy
|
836
846
|
mod_ssl
|
837
847
|
mod_wsgi
|
848
|
+
mongo-express Project
|
838
849
|
nginx
|
839
850
|
ninenines
|
840
851
|
noVNC
|
841
852
|
ntop
|
842
853
|
ownCloud
|
843
854
|
pfSense
|
855
|
+
phpMyAdmin
|
844
856
|
port25
|
845
857
|
qmail
|
846
858
|
rPath
|
data/lib/recog/fingerprint.rb
CHANGED
@@ -5,6 +5,7 @@ module Recog
|
|
5
5
|
class Fingerprint
|
6
6
|
require 'set'
|
7
7
|
|
8
|
+
require 'recog/fingerprint_parse_error'
|
8
9
|
require 'recog/fingerprint/regexp_factory'
|
9
10
|
require 'recog/fingerprint/test'
|
10
11
|
|
@@ -28,20 +29,27 @@ class Fingerprint
|
|
28
29
|
# @return (see #parse_examples)
|
29
30
|
attr_reader :tests
|
30
31
|
|
32
|
+
# The line number of the XML entity in the source file for this
|
33
|
+
# fingerprint.
|
34
|
+
#
|
35
|
+
# @return [Integer] The line number of this entity.
|
36
|
+
attr_reader :line
|
37
|
+
|
31
38
|
# @param xml [Nokogiri::XML::Element]
|
32
39
|
# @param match_key [String] See Recog::DB
|
33
40
|
# @param protocol [String] Protocol such as ftp, mssql, http, etc.
|
34
|
-
# @param
|
35
|
-
def initialize(xml, match_key=nil, protocol=nil,
|
41
|
+
# @param example_path [String] Directory path for fingerprint example files
|
42
|
+
def initialize(xml, match_key=nil, protocol=nil, example_path=nil)
|
36
43
|
@match_key = match_key
|
37
44
|
@protocol = protocol
|
38
45
|
@name = parse_description(xml)
|
39
46
|
@regex = create_regexp(xml)
|
47
|
+
@line = xml.line
|
40
48
|
@params = {}
|
41
49
|
@tests = []
|
42
50
|
|
43
51
|
@protocol.downcase! if @protocol
|
44
|
-
parse_examples(xml,
|
52
|
+
parse_examples(xml, example_path)
|
45
53
|
parse_params(xml)
|
46
54
|
end
|
47
55
|
|
@@ -161,6 +169,7 @@ class Fingerprint
|
|
161
169
|
# look for the presence of test cases
|
162
170
|
if tests.size == 0
|
163
171
|
yield :warn, "'#{@name}' has no test cases"
|
172
|
+
return
|
164
173
|
end
|
165
174
|
|
166
175
|
# make sure each test case passes
|
@@ -226,7 +235,7 @@ class Fingerprint
|
|
226
235
|
if !param_used
|
227
236
|
message = "'#{@name}' is missing an example that checks for parameter '#{param_name}' " +
|
228
237
|
"which is derived from a capture group"
|
229
|
-
yield :
|
238
|
+
yield :fail, message
|
230
239
|
end
|
231
240
|
end
|
232
241
|
end
|
@@ -249,9 +258,9 @@ class Fingerprint
|
|
249
258
|
end
|
250
259
|
|
251
260
|
# @param xml [Nokogiri::XML::Element]
|
252
|
-
# @param
|
261
|
+
# @param example_path [String] Directory path for fingerprint example files
|
253
262
|
# @return [void]
|
254
|
-
def parse_examples(xml,
|
263
|
+
def parse_examples(xml, example_path)
|
255
264
|
elements = xml.xpath('example')
|
256
265
|
|
257
266
|
elements.each do |elem|
|
@@ -259,7 +268,12 @@ class Fingerprint
|
|
259
268
|
attrs = elem.attributes.values.reduce({}) { |a,e| a.merge(e.name => e.value) }
|
260
269
|
if attrs["_filename"]
|
261
270
|
contents = ""
|
262
|
-
|
271
|
+
filename = attrs["_filename"]
|
272
|
+
fn = File.expand_path(File.join(example_path, filename))
|
273
|
+
unless fn.start_with?(File.expand_path(example_path) + File::Separator)
|
274
|
+
raise FingerprintParseError.new("an example specifies an illegal file path '#{filename}'", line_number = @line)
|
275
|
+
end
|
276
|
+
|
263
277
|
File.open(fn, "rb") do |file|
|
264
278
|
contents = file.read
|
265
279
|
contents.force_encoding(Encoding::ASCII_8BIT)
|
data/lib/recog/verifier.rb
CHANGED
@@ -15,9 +15,9 @@ class Verifier
|
|
15
15
|
fp.verify_params do |status, message|
|
16
16
|
case status
|
17
17
|
when :warn
|
18
|
-
reporter.warning
|
18
|
+
reporter.warning message, fp.line
|
19
19
|
when :fail
|
20
|
-
reporter.failure
|
20
|
+
reporter.failure message, fp.line
|
21
21
|
when :success
|
22
22
|
reporter.success(message)
|
23
23
|
end
|
@@ -25,9 +25,9 @@ class Verifier
|
|
25
25
|
fp.verify_tests do |status, message|
|
26
26
|
case status
|
27
27
|
when :warn
|
28
|
-
reporter.warning
|
28
|
+
reporter.warning message, fp.line
|
29
29
|
when :fail
|
30
|
-
reporter.failure
|
30
|
+
reporter.failure message, fp.line
|
31
31
|
when :success
|
32
32
|
reporter.success(message)
|
33
33
|
end
|
@@ -24,15 +24,15 @@ class VerifyReporter
|
|
24
24
|
formatter.success_message("#{padding}#{text}") if detail?
|
25
25
|
end
|
26
26
|
|
27
|
-
def warning(text)
|
27
|
+
def warning(text, line=nil)
|
28
28
|
return unless @options.warnings
|
29
29
|
@warning_count += 1
|
30
|
-
formatter.warning_message("#{path_label}#{padding}#{text}")
|
30
|
+
formatter.warning_message("#{path_label(line)}#{padding}WARN: #{text}")
|
31
31
|
end
|
32
32
|
|
33
|
-
def failure(text)
|
33
|
+
def failure(text, line=nil)
|
34
34
|
@failure_count += 1
|
35
|
-
formatter.failure_message("#{path_label}#{padding}#{text}")
|
35
|
+
formatter.failure_message("#{path_label(line)}#{padding}FAIL: #{text}")
|
36
36
|
end
|
37
37
|
|
38
38
|
def print_name(fingerprint)
|
@@ -65,9 +65,10 @@ class VerifyReporter
|
|
65
65
|
@options.detail
|
66
66
|
end
|
67
67
|
|
68
|
-
def path_label
|
68
|
+
def path_label(line=nil)
|
69
69
|
unless detail?
|
70
|
-
|
70
|
+
line_label = line ? line.to_s + ":" : ""
|
71
|
+
@path.to_s.empty? ? "" : "#{@path}:#{line_label} "
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
data/lib/recog/version.rb
CHANGED
data/requirements.txt
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
lxml==4.6.
|
1
|
+
lxml==4.6.5
|
2
2
|
pyyaml
|
@@ -0,0 +1 @@
|
|
1
|
+
HP LaserJet 4100 Series
|
@@ -0,0 +1 @@
|
|
1
|
+
HP LaserJet 2200
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<fingerprints>
|
2
|
+
<fingerprint pattern="laserjet (.*)(?: series)?" flags="REG_ICASE">
|
3
|
+
<description>HP JetDirect Printer</description>
|
4
|
+
<example _filename="hp_printer_ex_01.txt"/>
|
5
|
+
<example _filename="hp_printer_ex_02.txt"/>
|
6
|
+
<param pos="0" name="service.vendor" value="HP"/>
|
7
|
+
</fingerprint>
|
8
|
+
</fingerprints>
|
data/spec/lib/recog/db_spec.rb
CHANGED
@@ -1,97 +1,120 @@
|
|
1
1
|
require 'recog/db'
|
2
2
|
|
3
3
|
describe Recog::DB do
|
4
|
-
let(:xml_file) { File.expand_path File.join('spec', 'data', 'test_fingerprints.xml') }
|
5
|
-
subject { Recog::DB.new(xml_file) }
|
6
4
|
|
7
5
|
describe "#fingerprints" do
|
8
|
-
|
6
|
+
context "with inline example content" do
|
7
|
+
let(:xml_file) { File.expand_path File.join('spec', 'data', 'test_fingerprints.xml') }
|
8
|
+
subject { Recog::DB.new(xml_file) }
|
9
9
|
|
10
|
-
|
10
|
+
subject(:fingerprints) { described_class.new(xml_file).fingerprints }
|
11
11
|
|
12
|
-
|
13
|
-
subject(:entry) { described_class.new(xml_file).fingerprints[0] }
|
12
|
+
it { is_expected.to be_a(Enumerable) }
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
end
|
14
|
+
context "with only a pattern" do
|
15
|
+
subject(:entry) { described_class.new(xml_file).fingerprints[0] }
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
it "has a blank name with no description" do
|
18
|
+
expect(entry.name).to be_empty
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
it "has a pattern" do
|
22
|
+
expect(entry.regex.source).to eq(".*\\(iSeries\\).*")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "has no params" do
|
26
|
+
expect(entry.params).to be_empty
|
27
|
+
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
it "has no tests" do
|
30
|
+
expect(entry.tests).to be_empty
|
31
|
+
end
|
29
32
|
end
|
30
|
-
end
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
+
context "with params" do
|
35
|
+
subject(:entry) { described_class.new(xml_file).fingerprints[1] }
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
it "has a name" do
|
38
|
+
expect(entry.name).to eq('PalmOS')
|
39
|
+
end
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
it "has a pattern" do
|
42
|
+
expect(entry.regex.source).to eq(".*\\(PalmOS\\).*")
|
43
|
+
end
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
it "has params" do
|
46
|
+
expect(entry.params).to eq({"os.vendor"=>[1, "Palm"], "os.device"=>[2, "General"]})
|
47
|
+
end
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
+
it "has no tests" do
|
50
|
+
expect(entry.tests).to be_empty
|
51
|
+
end
|
49
52
|
end
|
50
|
-
end
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
+
context "with pattern flags" do
|
55
|
+
subject(:entry) { described_class.new(xml_file).fingerprints[2] }
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
|
57
|
+
it "has a name and only uses the first value" do
|
58
|
+
expect(entry.name).to eq('HP Designjet printer')
|
59
|
+
end
|
58
60
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
it 'creates a Regexp with expected flags' do
|
62
|
+
expect(entry.regex).to be_a(Regexp)
|
63
|
+
expect(entry.regex.options).to eq(Recog::Fingerprint::RegexpFactory::DEFAULT_FLAGS | Regexp::IGNORECASE)
|
64
|
+
end
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
66
|
+
it "has a pattern" do
|
67
|
+
expect(entry.regex).to be_a(Regexp)
|
68
|
+
expect(entry.regex.source).to eq("(designjet \\S+)")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "has params" do
|
72
|
+
expect(entry.params).to eq({"service.vendor"=>[0, "HP"]})
|
73
|
+
end
|
68
74
|
|
69
|
-
|
70
|
-
|
75
|
+
it "has no tests" do
|
76
|
+
expect(entry.tests).to be_empty
|
77
|
+
end
|
71
78
|
end
|
72
79
|
|
73
|
-
|
74
|
-
|
80
|
+
context "with test" do
|
81
|
+
subject(:entry) { described_class.new(xml_file).fingerprints[3] }
|
82
|
+
|
83
|
+
it "has a name" do
|
84
|
+
expect(entry.name).to eq('HP JetDirect Printer')
|
85
|
+
end
|
86
|
+
|
87
|
+
it "has a pattern" do
|
88
|
+
expect(entry.regex.source).to eq("laserjet (.*)(?: series)?")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "has params" do
|
92
|
+
expect(entry.params).to eq({"service.vendor"=>[0, "HP"]})
|
93
|
+
end
|
94
|
+
|
95
|
+
it "has tests" do
|
96
|
+
expect(entry.tests.map(&:content)).to match_array(["HP LaserJet 4100 Series", "HP LaserJet 2200"])
|
97
|
+
end
|
75
98
|
end
|
76
99
|
end
|
77
100
|
|
78
|
-
context "with
|
79
|
-
|
101
|
+
context "with external example content" do
|
102
|
+
let(:xml_file) { File.expand_path File.join('spec', 'data', 'external_example_fingerprint.xml') }
|
103
|
+
subject { Recog::DB.new(xml_file) }
|
80
104
|
|
81
|
-
|
82
|
-
expect(entry.name).to eq('HP JetDirect Printer')
|
83
|
-
end
|
105
|
+
subject(:entry) { described_class.new(xml_file).fingerprints[0] }
|
84
106
|
|
85
|
-
it "has
|
86
|
-
expect(entry.
|
107
|
+
it "has tests" do
|
108
|
+
expect(entry.tests.map(&:content)).to match_array(["HP LaserJet 4100 Series", "HP LaserJet 2200"])
|
87
109
|
end
|
110
|
+
end
|
88
111
|
|
89
|
-
|
90
|
-
|
91
|
-
|
112
|
+
context "with external example content illegal path" do
|
113
|
+
let(:xml_file) { File.expand_path File.join('spec', 'data', 'external_example_illegal_path_fingerprint.xml') }
|
114
|
+
subject { Recog::DB.new(xml_file) }
|
92
115
|
|
93
|
-
it "
|
94
|
-
expect
|
116
|
+
it "raises an illegal file path error" do
|
117
|
+
expect { subject }.to raise_error(/an example specifies an illegal file path '.+'/)
|
95
118
|
end
|
96
119
|
end
|
97
120
|
end
|
@@ -75,7 +75,7 @@ describe Recog::Fingerprint do
|
|
75
75
|
let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[6]) }
|
76
76
|
|
77
77
|
it "identifies when a parameter defined by a capture group is not included in one example" do
|
78
|
-
expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:
|
78
|
+
expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:fail, String])
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -83,7 +83,7 @@ describe Recog::Fingerprint do
|
|
83
83
|
let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[7]) }
|
84
84
|
|
85
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([:
|
86
|
+
expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:fail, String], [:fail, String])
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -92,7 +92,7 @@ describe Recog::Fingerprint do
|
|
92
92
|
let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[8]) }
|
93
93
|
|
94
94
|
it "identifies when a parameter defined by a capture group is not included in one example" do
|
95
|
-
expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:
|
95
|
+
expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:fail, String])
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
@@ -100,7 +100,7 @@ describe Recog::Fingerprint do
|
|
100
100
|
let(:entry) { described_class.new(doc.xpath("//fingerprints/fingerprint")[9]) }
|
101
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([:
|
103
|
+
expect { |unused| entry.verify_tests_have_capture_groups(&unused) }.to yield_successive_args([:fail, String], [:fail, String])
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
@@ -22,12 +22,12 @@ describe Recog::VerifyReporter do
|
|
22
22
|
|
23
23
|
describe "#report" do
|
24
24
|
it "prints warnings" do
|
25
|
-
expect(formatter).to receive(:warning_message).with('a warning')
|
25
|
+
expect(formatter).to receive(:warning_message).with('WARN: a warning')
|
26
26
|
run_report
|
27
27
|
end
|
28
28
|
|
29
29
|
it "prints failures" do
|
30
|
-
expect(formatter).to receive(:failure_message).with('a failure')
|
30
|
+
expect(formatter).to receive(:failure_message).with('FAIL: a failure')
|
31
31
|
run_report
|
32
32
|
end
|
33
33
|
|
@@ -50,12 +50,12 @@ describe Recog::VerifyReporter do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it "prints warnings" do
|
53
|
-
expect(formatter).to receive(:warning_message).with(' a warning')
|
53
|
+
expect(formatter).to receive(:warning_message).with(' WARN: a warning')
|
54
54
|
run_report
|
55
55
|
end
|
56
56
|
|
57
57
|
it "prints failures" do
|
58
|
-
expect(formatter).to receive(:failure_message).with(' a failure')
|
58
|
+
expect(formatter).to receive(:failure_message).with(' FAIL: a failure')
|
59
59
|
run_report
|
60
60
|
end
|
61
61
|
|
@@ -84,12 +84,12 @@ describe Recog::VerifyReporter do
|
|
84
84
|
subject { Recog::VerifyReporter.new(double(detail: false, quiet: false, warnings: true), formatter, path) }
|
85
85
|
|
86
86
|
it "prints warnings" do
|
87
|
-
expect(formatter).to receive(:warning_message).with("#{path}: a warning")
|
87
|
+
expect(formatter).to receive(:warning_message).with("#{path}: WARN: a warning")
|
88
88
|
run_report
|
89
89
|
end
|
90
90
|
|
91
91
|
it "prints failures" do
|
92
|
-
expect(formatter).to receive(:failure_message).with("#{path}: a failure")
|
92
|
+
expect(formatter).to receive(:failure_message).with("#{path}: FAIL: a failure")
|
93
93
|
run_report
|
94
94
|
end
|
95
95
|
|
@@ -118,12 +118,12 @@ describe Recog::VerifyReporter do
|
|
118
118
|
end
|
119
119
|
|
120
120
|
it "prints warnings" do
|
121
|
-
expect(formatter).to receive(:warning_message).with(' a warning')
|
121
|
+
expect(formatter).to receive(:warning_message).with(' WARN: a warning')
|
122
122
|
run_report
|
123
123
|
end
|
124
124
|
|
125
125
|
it "prints failures" do
|
126
|
-
expect(formatter).to receive(:failure_message).with(' a failure')
|
126
|
+
expect(formatter).to receive(:failure_message).with(' FAIL: a failure')
|
127
127
|
run_report
|
128
128
|
end
|
129
129
|
|