recog 2.3.22 → 2.3.23
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.
- 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
|
|