threatinator 0.1.1
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 +7 -0
- data/CHANGELOG.md +23 -0
- data/CONTRIBUTING.md +119 -0
- data/Gemfile +28 -0
- data/LICENSE +165 -0
- data/README.md +45 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/bin/threatinator +5 -0
- data/lib/threatinator.rb +3 -0
- data/lib/threatinator/action.rb +14 -0
- data/lib/threatinator/actions/list.rb +2 -0
- data/lib/threatinator/actions/list/action.rb +53 -0
- data/lib/threatinator/actions/list/config.rb +10 -0
- data/lib/threatinator/actions/run.rb +2 -0
- data/lib/threatinator/actions/run/action.rb +45 -0
- data/lib/threatinator/actions/run/config.rb +32 -0
- data/lib/threatinator/actions/run/coverage_observer.rb +54 -0
- data/lib/threatinator/actions/run/output_config.rb +59 -0
- data/lib/threatinator/cli.rb +13 -0
- data/lib/threatinator/cli/action_builder.rb +33 -0
- data/lib/threatinator/cli/list_action_builder.rb +19 -0
- data/lib/threatinator/cli/parser.rb +113 -0
- data/lib/threatinator/cli/run_action_builder.rb +41 -0
- data/lib/threatinator/config.rb +6 -0
- data/lib/threatinator/config/base.rb +35 -0
- data/lib/threatinator/config/feed_search.rb +25 -0
- data/lib/threatinator/decoder.rb +24 -0
- data/lib/threatinator/decoders/gzip.rb +30 -0
- data/lib/threatinator/event.rb +27 -0
- data/lib/threatinator/event_builder.rb +41 -0
- data/lib/threatinator/exceptions.rb +61 -0
- data/lib/threatinator/feed.rb +82 -0
- data/lib/threatinator/feed_builder.rb +156 -0
- data/lib/threatinator/feed_registry.rb +47 -0
- data/lib/threatinator/feed_runner.rb +118 -0
- data/lib/threatinator/fetcher.rb +22 -0
- data/lib/threatinator/fetchers/http.rb +46 -0
- data/lib/threatinator/filter.rb +12 -0
- data/lib/threatinator/filters/block.rb +18 -0
- data/lib/threatinator/filters/comments.rb +16 -0
- data/lib/threatinator/filters/whitespace.rb +19 -0
- data/lib/threatinator/output.rb +50 -0
- data/lib/threatinator/parser.rb +23 -0
- data/lib/threatinator/parsers/csv.rb +7 -0
- data/lib/threatinator/parsers/csv/parser.rb +77 -0
- data/lib/threatinator/parsers/getline.rb +8 -0
- data/lib/threatinator/parsers/getline/parser.rb +45 -0
- data/lib/threatinator/parsers/json.rb +8 -0
- data/lib/threatinator/parsers/json/adapters/oj.rb +65 -0
- data/lib/threatinator/parsers/json/parser.rb +45 -0
- data/lib/threatinator/parsers/json/record.rb +20 -0
- data/lib/threatinator/parsers/xml.rb +8 -0
- data/lib/threatinator/parsers/xml/node.rb +79 -0
- data/lib/threatinator/parsers/xml/node_builder.rb +39 -0
- data/lib/threatinator/parsers/xml/parser.rb +44 -0
- data/lib/threatinator/parsers/xml/path.rb +70 -0
- data/lib/threatinator/parsers/xml/pattern.rb +53 -0
- data/lib/threatinator/parsers/xml/record.rb +14 -0
- data/lib/threatinator/parsers/xml/sax_document.rb +64 -0
- data/lib/threatinator/plugin_loader.rb +115 -0
- data/lib/threatinator/plugins/output/csv.rb +47 -0
- data/lib/threatinator/plugins/output/null.rb +17 -0
- data/lib/threatinator/plugins/output/rubydebug.rb +16 -0
- data/lib/threatinator/property_definer.rb +101 -0
- data/lib/threatinator/record.rb +22 -0
- data/lib/threatinator/registry.rb +53 -0
- data/lib/threatinator/util.rb +15 -0
- data/spec/feeds/ET_compromised-ip_reputation_spec.rb +50 -0
- data/spec/feeds/alienvault-ip_reputation_spec.rb +50 -0
- data/spec/feeds/arbor_fastflux-domain_reputation_spec.rb +50 -0
- data/spec/feeds/arbor_ssh-ip_reputation_spec.rb +50 -0
- data/spec/feeds/autoshun_shunlist_spec.rb +42 -0
- data/spec/feeds/blocklist_de_apache-ip_reputation_spec.rb +50 -0
- data/spec/feeds/blocklist_de_bots-ip_reputation_spec.rb +50 -0
- data/spec/feeds/blocklist_de_ftp-ip_reputation_spec.rb +50 -0
- data/spec/feeds/blocklist_de_imap-ip_reputation_spec.rb +50 -0
- data/spec/feeds/blocklist_de_pop3-ip_reputation_spec.rb +50 -0
- data/spec/feeds/blocklist_de_proftpd-ip_reputation_spec.rb +50 -0
- data/spec/feeds/blocklist_de_sip-ip_reputation_spec.rb +50 -0
- data/spec/feeds/blocklist_de_ssh-ip_reputation_spec.rb +50 -0
- data/spec/feeds/blocklist_de_strongips-ip_reputation_spec.rb +50 -0
- data/spec/feeds/ciarmy-ip_reputation_spec.rb +50 -0
- data/spec/feeds/cruzit-ip_reputation_spec.rb +50 -0
- data/spec/feeds/dan_me_uk_torlist-ip_reputation_spec.rb +50 -0
- data/spec/feeds/data/ET_compromised-ip_reputation.txt +11 -0
- data/spec/feeds/data/alienvault-ip_reputation.txt +18 -0
- data/spec/feeds/data/arbor_domainlist.txt +11 -0
- data/spec/feeds/data/arbor_ssh.txt +16 -0
- data/spec/feeds/data/autoshun_shunlist.csv +20 -0
- data/spec/feeds/data/blocklist_de_apache-ip-reputation.txt +17 -0
- data/spec/feeds/data/blocklist_de_bots-ip-reputation.txt +15 -0
- data/spec/feeds/data/blocklist_de_ftp-ip-reputation.txt +7 -0
- data/spec/feeds/data/blocklist_de_imap-ip-reputation.txt +8 -0
- data/spec/feeds/data/blocklist_de_pop3-ip-reputation.txt +11 -0
- data/spec/feeds/data/blocklist_de_proftpd-ip-reputation.txt +12 -0
- data/spec/feeds/data/blocklist_de_sip-ip-reputation.txt +9 -0
- data/spec/feeds/data/blocklist_de_ssh-ip-reputation.txt +10 -0
- data/spec/feeds/data/blocklist_de_strongips-ip-reputation.txt +11 -0
- data/spec/feeds/data/ciarmy-ip-reputation.txt +11 -0
- data/spec/feeds/data/cruzit-ip-reputation.txt +14 -0
- data/spec/feeds/data/dan_me_uk_torlist-ip-reputation.txt +11 -0
- data/spec/feeds/data/dshield_topattackers.xml +4 -0
- data/spec/feeds/data/feodo_domainlist.txt +18 -0
- data/spec/feeds/data/feodo_iplist.txt +20 -0
- data/spec/feeds/data/infiltrated_iplist.txt +16 -0
- data/spec/feeds/data/malc0de_domainlist.txt +18 -0
- data/spec/feeds/data/malc0de_iplist.txt +14 -0
- data/spec/feeds/data/mirc_domainlist.txt +31 -0
- data/spec/feeds/data/nothink_irc_iplist.txt +14 -0
- data/spec/feeds/data/nothink_ssh_iplist.txt +10 -0
- data/spec/feeds/data/openbl_iplist.txt +12 -0
- data/spec/feeds/data/palevo_domainlist.txt +25 -0
- data/spec/feeds/data/palevo_iplist.txt +24 -0
- data/spec/feeds/data/phishtank-sample.json.gz +0 -0
- data/spec/feeds/data/spyeye_domainlist.txt +16 -0
- data/spec/feeds/data/spyeye_iplist.txt +19 -0
- data/spec/feeds/data/t-arend-de_ssh_iplist.txt +17 -0
- data/spec/feeds/data/the_haleys_ssh_iplist.txt +12 -0
- data/spec/feeds/data/yourcmc_ssh-ip_reputation.txt +27 -0
- data/spec/feeds/data/zeus-ip_reputation.txt +285 -0
- data/spec/feeds/data/zeus_domainlist.txt +27 -0
- data/spec/feeds/dshield_attackers-top1000_spec.rb +43 -0
- data/spec/feeds/feodo-domain_reputation_spec.rb +50 -0
- data/spec/feeds/feodo-ip_reputation_spec.rb +50 -0
- data/spec/feeds/infiltrated-ip_reputation_spec.rb +50 -0
- data/spec/feeds/malc0de-domain_reputation_spec.rb +50 -0
- data/spec/feeds/malc0de-ip_reputation_spec.rb +50 -0
- data/spec/feeds/mirc-domain_reputation_spec.rb +50 -0
- data/spec/feeds/nothink_irc-ip_reputation_spec.rb +50 -0
- data/spec/feeds/nothink_ssh-ip_reputation_spec.rb +50 -0
- data/spec/feeds/openbl-ip_reputation_spec.rb +50 -0
- data/spec/feeds/palevo-domain_reputation_spec.rb +50 -0
- data/spec/feeds/palevo-ip_reputation_spec.rb +50 -0
- data/spec/feeds/phishtank_spec.rb +45 -0
- data/spec/feeds/spyeye-domain_reputation_spec.rb +50 -0
- data/spec/feeds/spyeye-ip_reputation_spec.rb +50 -0
- data/spec/feeds/t-arend-de_ssh-ip_reputation_spec.rb +50 -0
- data/spec/feeds/the_haleys_ssh-ip_reputation_spec.rb +50 -0
- data/spec/feeds/yourcmc_ssh-ip_reputation_spec.rb +50 -0
- data/spec/feeds/zeus-domain_reputation_spec.rb +50 -0
- data/spec/feeds/zeus-ip_reputation_spec.rb +50 -0
- data/spec/fixtures/feed/provider1/feed1.feed +6 -0
- data/spec/fixtures/parsers/test.xml +13 -0
- data/spec/fixtures/parsers/test_self_closing.xml +20 -0
- data/spec/fixtures/plugins/bad/threatinator/plugins/test_error1/plugin.rb +1 -0
- data/spec/fixtures/plugins/bad/threatinator/plugins/test_missing1/plugin.rb +0 -0
- data/spec/fixtures/plugins/fake.rb +19 -0
- data/spec/fixtures/plugins/good/threatinator/plugins/test_type1/plugin_a.rb +8 -0
- data/spec/fixtures/plugins/good/threatinator/plugins/test_type1/plugin_b.rb +8 -0
- data/spec/fixtures/plugins/good/threatinator/plugins/test_type2/plugin_c.rb +8 -0
- data/spec/fixtures/plugins/good/threatinator/plugins/test_type2/plugin_d.rb +8 -0
- data/spec/fixtures/plugins/good/threatinator/plugins/test_type3/plugin_e.rb +8 -0
- data/spec/fixtures/plugins/good/threatinator/plugins/test_type3/plugin_f.rb +8 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/support/bad_feeds/missing_fetcher.feed +7 -0
- data/spec/support/bad_feeds/missing_name.feed +6 -0
- data/spec/support/bad_feeds/missing_parser.feed +3 -0
- data/spec/support/bad_feeds/missing_provider.feed +5 -0
- data/spec/support/factories/event.rb +27 -0
- data/spec/support/factories/feed.rb +32 -0
- data/spec/support/factories/feed_builder.rb +65 -0
- data/spec/support/factories/feed_registry.rb +8 -0
- data/spec/support/factories/output.rb +11 -0
- data/spec/support/factories/record.rb +17 -0
- data/spec/support/factories/xml_node.rb +33 -0
- data/spec/support/helpers/io.rb +11 -0
- data/spec/support/helpers/models.rb +13 -0
- data/spec/support/shared/action_builder.rb +47 -0
- data/spec/support/shared/decoder.rb +70 -0
- data/spec/support/shared/feeds.rb +218 -0
- data/spec/support/shared/fetcher.rb +48 -0
- data/spec/support/shared/filter.rb +14 -0
- data/spec/support/shared/io-like.rb +7 -0
- data/spec/support/shared/output.rb +120 -0
- data/spec/support/shared/parsers.rb +51 -0
- data/spec/support/shared/record.rb +111 -0
- data/spec/threatinator/actions/list/action_spec.rb +93 -0
- data/spec/threatinator/actions/run/action_spec.rb +89 -0
- data/spec/threatinator/actions/run/config_spec.rb +39 -0
- data/spec/threatinator/actions/run/coverage_observer_spec.rb +116 -0
- data/spec/threatinator/actions/run/output_config_spec.rb +89 -0
- data/spec/threatinator/cli/list_action_builder_spec.rb +57 -0
- data/spec/threatinator/cli/run_action_builder_spec.rb +133 -0
- data/spec/threatinator/cli_spec.rb +175 -0
- data/spec/threatinator/config/base_spec.rb +39 -0
- data/spec/threatinator/config/feed_search_spec.rb +76 -0
- data/spec/threatinator/decoders/gzip_spec.rb +75 -0
- data/spec/threatinator/event_builder_spec.rb +33 -0
- data/spec/threatinator/event_spec.rb +30 -0
- data/spec/threatinator/feed_builder_spec.rb +636 -0
- data/spec/threatinator/feed_registry_spec.rb +198 -0
- data/spec/threatinator/feed_runner_spec.rb +155 -0
- data/spec/threatinator/feed_spec.rb +169 -0
- data/spec/threatinator/fetcher_spec.rb +12 -0
- data/spec/threatinator/fetchers/http_spec.rb +32 -0
- data/spec/threatinator/filter_spec.rb +13 -0
- data/spec/threatinator/filters/block_spec.rb +16 -0
- data/spec/threatinator/filters/comments_spec.rb +13 -0
- data/spec/threatinator/filters/whitespace_spec.rb +12 -0
- data/spec/threatinator/parser_spec.rb +13 -0
- data/spec/threatinator/parsers/csv/parser_spec.rb +202 -0
- data/spec/threatinator/parsers/getline/parser_spec.rb +83 -0
- data/spec/threatinator/parsers/json/parser_spec.rb +106 -0
- data/spec/threatinator/parsers/json/record_spec.rb +30 -0
- data/spec/threatinator/parsers/xml/node_spec.rb +335 -0
- data/spec/threatinator/parsers/xml/parser_spec.rb +263 -0
- data/spec/threatinator/parsers/xml/path_spec.rb +209 -0
- data/spec/threatinator/parsers/xml/pattern_spec.rb +72 -0
- data/spec/threatinator/parsers/xml/record_spec.rb +27 -0
- data/spec/threatinator/plugin_loader_spec.rb +238 -0
- data/spec/threatinator/plugins/output/csv_spec.rb +46 -0
- data/spec/threatinator/plugins/output/null_spec.rb +17 -0
- data/spec/threatinator/plugins/output/rubydebug_spec.rb +37 -0
- data/spec/threatinator/property_definer_spec.rb +155 -0
- data/spec/threatinator/record_spec.rb +19 -0
- data/spec/threatinator/registry_spec.rb +97 -0
- data/spec/threatinator/runner_spec.rb +273 -0
- metadata +376 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'threatinator/plugins/output/csv'
|
|
3
|
+
require 'stringio'
|
|
4
|
+
|
|
5
|
+
describe Threatinator::Plugins::Output::Csv do
|
|
6
|
+
let(:config) { Threatinator::Plugins::Output::Csv::Config.new }
|
|
7
|
+
it_should_behave_like "a file-based output plugin", :csv
|
|
8
|
+
|
|
9
|
+
describe "the output" do
|
|
10
|
+
let(:io) { StringIO.new }
|
|
11
|
+
let(:output) { described_class.new(config) }
|
|
12
|
+
|
|
13
|
+
before :each do
|
|
14
|
+
config.io = io
|
|
15
|
+
events.each do |e|
|
|
16
|
+
output.handle_event(e)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:lines) { io.string.lines.to_a }
|
|
21
|
+
let(:events) {
|
|
22
|
+
ret = []
|
|
23
|
+
1.upto(10) do |i|
|
|
24
|
+
ret << build(:event, feed_provider: "my_prov#{i}",
|
|
25
|
+
feed_name: "my_name#{i}", type: :scanning,
|
|
26
|
+
ipv4s: ["#{i}.1.1.1","#{i}.1.1.2","#{i}.1.1.3","#{i}.1.1.4","#{i}.1.1.5"],
|
|
27
|
+
fqdns: ["a#{i}.com","b#{i}.com","c#{i}.com","d#{i}.com","e#{i}.com"]
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
ret
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
describe "the header" do
|
|
35
|
+
subject { lines.first }
|
|
36
|
+
it { is_expected.to eq("provider,feed_name,type,ipv4_1,ipv4_2,ipv4_3,ipv4_4,fqdn_1,fqdn_2,fqdn_3,fqdn_4\n") }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "outputs each event, limited to the first four IPs and four fqdns" do
|
|
40
|
+
line2 = lines[1]
|
|
41
|
+
1.upto(10) do |i|
|
|
42
|
+
expect(lines[i]).to eq("my_prov#{i},my_name#{i},scanning,#{i}.1.1.1,#{i}.1.1.2,#{i}.1.1.3,#{i}.1.1.4,a#{i}.com,b#{i}.com,c#{i}.com,d#{i}.com\n")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'threatinator/plugins/output/null'
|
|
3
|
+
require 'stringio'
|
|
4
|
+
|
|
5
|
+
describe Threatinator::Plugins::Output::Null do
|
|
6
|
+
let(:config) { Threatinator::Plugins::Output::Null::Config.new }
|
|
7
|
+
it_should_behave_like "an output plugin", :null
|
|
8
|
+
|
|
9
|
+
describe "#handle_event" do
|
|
10
|
+
let(:output) { described_class.new(config) }
|
|
11
|
+
it "does not call any methods on the event" do
|
|
12
|
+
event = double("event")
|
|
13
|
+
output.handle_event(event)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'threatinator/plugins/output/rubydebug'
|
|
3
|
+
require 'stringio'
|
|
4
|
+
|
|
5
|
+
describe Threatinator::Plugins::Output::Rubydebug do
|
|
6
|
+
let(:config) { Threatinator::Plugins::Output::Rubydebug::Config.new }
|
|
7
|
+
|
|
8
|
+
it_should_behave_like "a file-based output plugin", :rubydebug
|
|
9
|
+
|
|
10
|
+
describe "the output" do
|
|
11
|
+
let(:output) { described_class.new(config) }
|
|
12
|
+
let(:io) { StringIO.new }
|
|
13
|
+
before :each do
|
|
14
|
+
config.io = io
|
|
15
|
+
events.each do |e|
|
|
16
|
+
output.handle_event(e)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:events) {
|
|
21
|
+
ret = []
|
|
22
|
+
1.upto(10) do |i|
|
|
23
|
+
ret << build(:event, feed_provider: "my_prov#{i}",
|
|
24
|
+
feed_name: "my_name#{i}", type: :scanning,
|
|
25
|
+
ipv4s: ["#{i}.1.1.1","#{i}.1.1.2","#{i}.1.1.3","#{i}.1.1.4","#{i}.1.1.5"],
|
|
26
|
+
fqdns: ["a#{i}.com","b#{i}.com","c#{i}.com","d#{i}.com","e#{i}.com"]
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
ret
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
it "outputs a bunch of stuff" do
|
|
33
|
+
expect(io.string.length).to be > 0
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'threatinator/property_definer'
|
|
3
|
+
|
|
4
|
+
describe Threatinator::PropertyDefiner do
|
|
5
|
+
describe "defining a property" do
|
|
6
|
+
let(:klass) {
|
|
7
|
+
Class.new do
|
|
8
|
+
include Threatinator::PropertyDefiner
|
|
9
|
+
property :my_prop
|
|
10
|
+
end
|
|
11
|
+
}
|
|
12
|
+
it "should add a setter for the property you define" do
|
|
13
|
+
klass = Class.new do
|
|
14
|
+
include Threatinator::PropertyDefiner
|
|
15
|
+
property :some_prop
|
|
16
|
+
end
|
|
17
|
+
expect(klass.new).to respond_to(:some_prop=)
|
|
18
|
+
end
|
|
19
|
+
it "should add a getter for the property you define" do
|
|
20
|
+
klass = Class.new do
|
|
21
|
+
include Threatinator::PropertyDefiner
|
|
22
|
+
property :another_prop
|
|
23
|
+
end
|
|
24
|
+
expect(klass.new).to respond_to(:another_prop)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "getting and setting properties" do
|
|
29
|
+
let(:klass) {
|
|
30
|
+
Class.new do
|
|
31
|
+
include Threatinator::PropertyDefiner
|
|
32
|
+
property :my_prop
|
|
33
|
+
end
|
|
34
|
+
}
|
|
35
|
+
it "should let me set the value of a property and retrieve it" do
|
|
36
|
+
instance = klass.new
|
|
37
|
+
instance.my_prop = 1234
|
|
38
|
+
expect(instance.my_prop).to eq(1234)
|
|
39
|
+
end
|
|
40
|
+
it "the getter should respond with nil by default" do
|
|
41
|
+
instance = klass.new
|
|
42
|
+
expect(instance.my_prop).to be_nil
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
describe ":type (type validation)" do
|
|
46
|
+
context "when :type is set to a class" do
|
|
47
|
+
let(:klass) {
|
|
48
|
+
Class.new do
|
|
49
|
+
include Threatinator::PropertyDefiner
|
|
50
|
+
property :my_prop, type: Integer
|
|
51
|
+
end
|
|
52
|
+
}
|
|
53
|
+
let(:instance) { klass.new }
|
|
54
|
+
|
|
55
|
+
it "should not raise an error if the property is set to a instance of the specified class" do
|
|
56
|
+
expect{instance.my_prop = 1234}.not_to raise_error
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should raise an InvalidAttributeError if the property being set is not of its defined type" do
|
|
60
|
+
expect{instance.my_prop = "asdf"}.to raise_error do |e|
|
|
61
|
+
expect(e).to be_a(Threatinator::Exceptions::InvalidAttributeError)
|
|
62
|
+
expect(e.attribute).to eq(:my_prop)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe ":validate" do
|
|
69
|
+
it "should raise an ArgumentError if :validate is not a proc" do
|
|
70
|
+
expect {
|
|
71
|
+
Class.new do
|
|
72
|
+
include Threatinator::PropertyDefiner
|
|
73
|
+
property :my_prop, validate: 1234
|
|
74
|
+
end
|
|
75
|
+
}.to raise_error(ArgumentError)
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should call the validate block whenever the associated attribute is set" do
|
|
80
|
+
expect { |b|
|
|
81
|
+
klass = Class.new do
|
|
82
|
+
include Threatinator::PropertyDefiner
|
|
83
|
+
property :my_prop, validate: lambda { |obj, val| b.to_proc.call(obj, val); true }
|
|
84
|
+
end
|
|
85
|
+
instance = klass.new
|
|
86
|
+
instance.my_prop = "value1"
|
|
87
|
+
instance.my_prop = "value2"
|
|
88
|
+
}.to yield_successive_args(
|
|
89
|
+
[kind_of(Threatinator::PropertyDefiner), "value1"],
|
|
90
|
+
[kind_of(Threatinator::PropertyDefiner), "value2"])
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should raise an InvalidAttributeError if the validation block returns false" do
|
|
94
|
+
klass = Class.new do
|
|
95
|
+
include Threatinator::PropertyDefiner
|
|
96
|
+
property :my_prop, validate: lambda { |obj, val| false }
|
|
97
|
+
end
|
|
98
|
+
instance = klass.new
|
|
99
|
+
expect { |b|
|
|
100
|
+
instance.my_prop = "value1"
|
|
101
|
+
}.to raise_error do |e|
|
|
102
|
+
expect(e).to be_a(Threatinator::Exceptions::InvalidAttributeError)
|
|
103
|
+
expect(e.attribute).to eq(:my_prop)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
it "should not raise an error if the validation block returns true" do
|
|
107
|
+
klass = Class.new do
|
|
108
|
+
include Threatinator::PropertyDefiner
|
|
109
|
+
property :my_prop, validate: lambda { |obj, val| true }
|
|
110
|
+
end
|
|
111
|
+
instance = klass.new
|
|
112
|
+
expect { |b|
|
|
113
|
+
instance.my_prop = "value1"
|
|
114
|
+
}.not_to raise_error
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
describe ":default" do
|
|
119
|
+
context "when :default is set to a value" do
|
|
120
|
+
it "should return the object when accessed via a getter" do
|
|
121
|
+
expected_object = "my_val"
|
|
122
|
+
klass = Class.new do
|
|
123
|
+
include Threatinator::PropertyDefiner
|
|
124
|
+
property :my_prop, default: expected_object
|
|
125
|
+
end
|
|
126
|
+
instance = klass.new
|
|
127
|
+
expect(instance.my_prop).to be(expected_object)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
context "when :default is set to a proc" do
|
|
131
|
+
it "should not call the proc if a value is provided" do
|
|
132
|
+
expect { |b|
|
|
133
|
+
klass = Class.new do
|
|
134
|
+
include Threatinator::PropertyDefiner
|
|
135
|
+
property :my_prop, default: b.to_proc
|
|
136
|
+
end
|
|
137
|
+
instance = klass.new
|
|
138
|
+
instance.my_prop = 1234
|
|
139
|
+
}.not_to yield_control
|
|
140
|
+
end
|
|
141
|
+
it "should only call the proc once, and only when it is accessed" do
|
|
142
|
+
expect { |b|
|
|
143
|
+
klass = Class.new do
|
|
144
|
+
include Threatinator::PropertyDefiner
|
|
145
|
+
property :my_prop, default: lambda { b.to_proc.call(); }
|
|
146
|
+
end
|
|
147
|
+
instance = klass.new
|
|
148
|
+
val1 = instance.my_prop
|
|
149
|
+
val2 = instance.my_prop
|
|
150
|
+
val3 = instance.my_prop
|
|
151
|
+
}.to yield_control.exactly(1).times
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'threatinator/record'
|
|
3
|
+
|
|
4
|
+
describe Threatinator::Record do
|
|
5
|
+
it_should_behave_like 'a record' do
|
|
6
|
+
let(:data) { "asdf" }
|
|
7
|
+
let(:opts) { { } }
|
|
8
|
+
end
|
|
9
|
+
context "two instances with different data" do
|
|
10
|
+
it_should_behave_like 'a record when compared to a differently configured record' do
|
|
11
|
+
let(:data) { "foo" }
|
|
12
|
+
let(:opts) { { } }
|
|
13
|
+
|
|
14
|
+
let(:data2) { "bar" }
|
|
15
|
+
let(:opts2) { {} }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'threatinator/registry'
|
|
3
|
+
|
|
4
|
+
describe Threatinator::Registry do
|
|
5
|
+
let(:registry) { described_class.new }
|
|
6
|
+
let(:ten_things) { {
|
|
7
|
+
a: Object.new,
|
|
8
|
+
b: Object.new,
|
|
9
|
+
c: Object.new,
|
|
10
|
+
d: Object.new,
|
|
11
|
+
e: Object.new,
|
|
12
|
+
f: Object.new,
|
|
13
|
+
g: Object.new,
|
|
14
|
+
h: Object.new,
|
|
15
|
+
i: Object.new,
|
|
16
|
+
j: Object.new
|
|
17
|
+
} }
|
|
18
|
+
|
|
19
|
+
describe "#clear" do
|
|
20
|
+
it "should remove all existing registrations" do
|
|
21
|
+
expect(registry.count).to eq(0)
|
|
22
|
+
registry.register(:foo, 123)
|
|
23
|
+
registry.register(:bar, 456)
|
|
24
|
+
expect(registry.count).to eq(2)
|
|
25
|
+
registry.clear
|
|
26
|
+
expect(registry.count).to eq(0)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "#keys" do
|
|
31
|
+
it "returns an array containing all of the keys" do
|
|
32
|
+
expect(registry.keys).to eq([])
|
|
33
|
+
registry.register(:foo, Object.new)
|
|
34
|
+
registry.register(:bar, Object.new)
|
|
35
|
+
registry.register(:woof, Object.new)
|
|
36
|
+
expect(registry.keys).to contain_exactly(:foo, :bar, :woof)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe "#register" do
|
|
41
|
+
it "should register the provided object to the given key" do
|
|
42
|
+
obj = Object.new
|
|
43
|
+
registry.register(:foo, obj)
|
|
44
|
+
expect(registry.get(:foo)).to be(obj)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should return the object that was registered" do
|
|
48
|
+
obj = Object.new
|
|
49
|
+
expect(registry.register(:foo, obj)).to be(obj)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should raise a AlreadyRegisteredError if something is already registered with the the given key" do
|
|
53
|
+
obj = Object.new
|
|
54
|
+
registry.register(:foo, obj)
|
|
55
|
+
expect {
|
|
56
|
+
registry.register(:foo, obj)
|
|
57
|
+
}.to raise_error(Threatinator::Exceptions::AlreadyRegisteredError)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "#each" do
|
|
62
|
+
it "should enumerate through each key and registered object" do
|
|
63
|
+
ten_things.each_pair do |i, thing|
|
|
64
|
+
registry.register(i, thing)
|
|
65
|
+
end
|
|
66
|
+
found_objects = []
|
|
67
|
+
registry.each do |key, obj|
|
|
68
|
+
found_objects << [ key, obj ]
|
|
69
|
+
end
|
|
70
|
+
expect(found_objects).to match_array(ten_things.to_a)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe "#count" do
|
|
75
|
+
it "should return the number of objects contained within the registry" do
|
|
76
|
+
expect(registry.count).to eq(0)
|
|
77
|
+
ten_things.each_pair do |i, thing|
|
|
78
|
+
registry.register(i, thing)
|
|
79
|
+
end
|
|
80
|
+
expect(registry.count).to eq(10)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe "#get" do
|
|
85
|
+
it "should return nil if key isn't registered" do
|
|
86
|
+
expect(registry.get(:foo)).to be_nil
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "should return the correct feed for the key" do
|
|
90
|
+
ten_things.each_pair { |i, o| registry.register(i, o) }
|
|
91
|
+
obj = Object.new
|
|
92
|
+
registry.register(:foo, obj)
|
|
93
|
+
expect(registry.get(:foo)).to be(obj)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
#require 'spec_helper'
|
|
2
|
+
#require 'threatinator/runner'
|
|
3
|
+
#
|
|
4
|
+
#describe Threatinator::Runner do
|
|
5
|
+
# let(:runner) { Threatinator::Runner.new }
|
|
6
|
+
#
|
|
7
|
+
# def generate_feedfile(filename, provider, name, url = "https://foobar/#{provider}/#{name}.data")
|
|
8
|
+
# File.open(filename, "w") do |fio|
|
|
9
|
+
# fio.write <<EOS
|
|
10
|
+
#provider "#{provider}"
|
|
11
|
+
#name "#{name}"
|
|
12
|
+
#fetch_http('#{url}')
|
|
13
|
+
#
|
|
14
|
+
#parse_eachline(:separator => "\n") do |builder, line|
|
|
15
|
+
#end
|
|
16
|
+
#EOS
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# describe "#add_feed_path" do
|
|
21
|
+
# it "add the paths to #feed_paths" do
|
|
22
|
+
# expect(runner.feed_paths).to eq([])
|
|
23
|
+
# runner.add_feed_path("/foo/bar1")
|
|
24
|
+
# expect(runner.feed_paths).to eq(["/foo/bar1"])
|
|
25
|
+
# runner.add_feed_path("/foo/bar2")
|
|
26
|
+
# expect(runner.feed_paths).to eq(["/foo/bar1", "/foo/bar2"])
|
|
27
|
+
# end
|
|
28
|
+
# end
|
|
29
|
+
#
|
|
30
|
+
# describe "#_load_feeds" do
|
|
31
|
+
# before :each do
|
|
32
|
+
# @feed_path1 = Dir.mktmpdir
|
|
33
|
+
# @feed_path2 = Dir.mktmpdir
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# after :each do
|
|
37
|
+
# FileUtils.remove_entry_secure @feed_path1
|
|
38
|
+
# FileUtils.remove_entry_secure @feed_path2
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
# context "with no feed paths" do
|
|
42
|
+
# it "should not have loaded any feeds" do
|
|
43
|
+
# runner._load_feeds
|
|
44
|
+
# expect(runner.registry.count).to eq(0)
|
|
45
|
+
# end
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# context "with paths added to the runner" do
|
|
49
|
+
# before :each do
|
|
50
|
+
# runner.add_feed_path(@feed_path1)
|
|
51
|
+
# runner.add_feed_path(@feed_path2)
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
# it "should load feeds from all of the configured paths" do
|
|
55
|
+
# 5.times do |i|
|
|
56
|
+
# generate_feedfile(File.join(@feed_path1, "feed#{i}.feed"), "provider1", "feed#{i}")
|
|
57
|
+
# generate_feedfile(File.join(@feed_path2, "feed#{i}.feed"), "provider2", "feed#{i}")
|
|
58
|
+
# end
|
|
59
|
+
# runner._load_feeds
|
|
60
|
+
# expect(runner.registry.count).to eq(10)
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
# it "should ignore files that don't end with .feed" do
|
|
64
|
+
# generate_feedfile(File.join(@feed_path1, "feed1.fee"), "provider1", "feed1")
|
|
65
|
+
# generate_feedfile(File.join(@feed_path1, "feed1.fed"), "provider1", "feed2")
|
|
66
|
+
# generate_feedfile(File.join(@feed_path1, "feed1.rb"), "provider1", "feed3")
|
|
67
|
+
# generate_feedfile(File.join(@feed_path1, "feed1.feed"), "real_provider", "my_feed")
|
|
68
|
+
# runner._load_feeds
|
|
69
|
+
# expect(runner.registry.count).to eq(1)
|
|
70
|
+
# expect(runner.registry.get("real_provider", "my_feed")).to be_a(Threatinator::Feed)
|
|
71
|
+
# expect(runner.registry.get("provider1", "feed1")).to be_nil
|
|
72
|
+
# expect(runner.registry.get("provider1", "feed2")).to be_nil
|
|
73
|
+
# expect(runner.registry.get("provider1", "feed3")).to be_nil
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
# it "should recurse subdirectories, loading feeds from there" do
|
|
77
|
+
# level1 = File.join(@feed_path1, "level1")
|
|
78
|
+
# level2 = File.join(@feed_path1, "level1", "level2")
|
|
79
|
+
# level3 = File.join(@feed_path1, "level1", "level2", "level3")
|
|
80
|
+
# FileUtils.mkdir_p level1
|
|
81
|
+
# FileUtils.mkdir_p level2
|
|
82
|
+
# FileUtils.mkdir_p level3
|
|
83
|
+
# generate_feedfile(File.join(level1, "feed1.feed"), "provider1", "feed1")
|
|
84
|
+
# generate_feedfile(File.join(level2, "feed2.feed"), "provider1", "feed2")
|
|
85
|
+
# generate_feedfile(File.join(level3, "feed3.feed"), "provider1", "feed3")
|
|
86
|
+
# runner._load_feeds
|
|
87
|
+
# expect(runner.registry.count).to eq(3)
|
|
88
|
+
# end
|
|
89
|
+
#
|
|
90
|
+
# it "should raise an exception if the same feed provider/name combination appears in multiple files" do
|
|
91
|
+
# generate_feedfile(File.join(@feed_path1, "feed1.feed"), "provider1", "feed1")
|
|
92
|
+
# generate_feedfile(File.join(@feed_path1, "feed2.feed"), "provider1", "feed1")
|
|
93
|
+
# expect {
|
|
94
|
+
# runner._load_feeds
|
|
95
|
+
# }.to raise_error(Threatinator::Exceptions::AlreadyRegisteredError)
|
|
96
|
+
# end
|
|
97
|
+
#
|
|
98
|
+
# end
|
|
99
|
+
# end
|
|
100
|
+
#
|
|
101
|
+
# describe "#_register_feed_from_file" do
|
|
102
|
+
# let(:feedfile) {FEED_FIXTURES.join("provider1", "feed1.feed").to_s}
|
|
103
|
+
#
|
|
104
|
+
# it "should return the feed after parsing the file" do
|
|
105
|
+
# ret = runner._register_feed_from_file(feedfile)
|
|
106
|
+
# expect(ret).to be_a(Threatinator::Feed)
|
|
107
|
+
# expect(ret.provider).to eq("provider1")
|
|
108
|
+
# expect(ret.name).to eq("feed1")
|
|
109
|
+
# end
|
|
110
|
+
#
|
|
111
|
+
# it "should have registered the feed" do
|
|
112
|
+
# expect(runner.registry.count).to eq(0)
|
|
113
|
+
# feed = runner._register_feed_from_file(feedfile)
|
|
114
|
+
# expect(runner.registry.count).to eq(1)
|
|
115
|
+
# expect(runner.registry.get(feed.provider, feed.name)).to be(feed)
|
|
116
|
+
# end
|
|
117
|
+
# end
|
|
118
|
+
#
|
|
119
|
+
# describe "#list" do
|
|
120
|
+
# let(:io_out) { StringIO.new }
|
|
121
|
+
#
|
|
122
|
+
# before :each do
|
|
123
|
+
# @feed_path = Dir.mktmpdir
|
|
124
|
+
# runner.add_feed_path(@feed_path)
|
|
125
|
+
# end
|
|
126
|
+
#
|
|
127
|
+
# after :each do
|
|
128
|
+
# FileUtils.remove_entry_secure @feed_path
|
|
129
|
+
# end
|
|
130
|
+
#
|
|
131
|
+
# context "with no feed paths" do
|
|
132
|
+
# it "should output the header" do
|
|
133
|
+
# runner.list(io_out: io_out);
|
|
134
|
+
# lines = io_out.string.lines.to_a
|
|
135
|
+
# expect(lines[0]).to eq("provider name type link/path\n")
|
|
136
|
+
# expect(lines[1]).to eq("-------- ---- ---- ---------\n")
|
|
137
|
+
# end
|
|
138
|
+
#
|
|
139
|
+
# it "should output the footer with a total of 0" do
|
|
140
|
+
# runner.list(io_out: io_out);
|
|
141
|
+
# lines = io_out.string.lines.to_a
|
|
142
|
+
# expect(lines[-2]).to eq("-------- ---- ---- ---------\n")
|
|
143
|
+
# expect(lines[-1]).to eq("Total: 0\n")
|
|
144
|
+
# end
|
|
145
|
+
# end
|
|
146
|
+
#
|
|
147
|
+
# context "with paths added to the runner" do
|
|
148
|
+
# before :each do
|
|
149
|
+
# end
|
|
150
|
+
# describe "the header row, header separator, and footer separator" do
|
|
151
|
+
# it "should vary the width of 'provider' based on the longest provider name" do
|
|
152
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), "A" * 10, "x", "http://x")
|
|
153
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), "A" * 20, "x", "http://x")
|
|
154
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), "A" * 30, "x", "http://x")
|
|
155
|
+
#
|
|
156
|
+
# runner.list(io_out: io_out);
|
|
157
|
+
# lines = io_out.string.lines.to_a
|
|
158
|
+
# expect(lines[0]).to eq("provider name type link/path\n")
|
|
159
|
+
# expect(lines[1]).to eq("------------------------------ ---- ---- ---------\n")
|
|
160
|
+
# expect(lines[-2]).to eq("------------------------------ ---- ---- ---------\n")
|
|
161
|
+
# end
|
|
162
|
+
#
|
|
163
|
+
# it "should vary the width of 'name' based on the longest feed name" do
|
|
164
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), 'a', "A" * 10, "http://x")
|
|
165
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), 'a', "A" * 20, "http://x")
|
|
166
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), 'a', "A" * 30, "http://x")
|
|
167
|
+
#
|
|
168
|
+
# runner.list(io_out: io_out);
|
|
169
|
+
# lines = io_out.string.lines.to_a
|
|
170
|
+
# expect(lines[0]).to eq("provider name type link/path\n")
|
|
171
|
+
# expect(lines[1]).to eq("-------- ------------------------------ ---- ---------\n")
|
|
172
|
+
# expect(lines[-2]).to eq("-------- ------------------------------ ---- ---------\n")
|
|
173
|
+
# end
|
|
174
|
+
#
|
|
175
|
+
# it "should vary the width of 'link/path' based on the longest link name" do
|
|
176
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), 'a', 'b', "http://" + ("A" * 10))
|
|
177
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), 'a', 'b', "http://" + ("A" * 20))
|
|
178
|
+
# generate_feedfile(File.join(@feed_path, "feed.feed"), 'a', 'b', "http://" + ("A" * 30))
|
|
179
|
+
#
|
|
180
|
+
# runner.list(io_out: io_out);
|
|
181
|
+
# lines = io_out.string.lines.to_a
|
|
182
|
+
# expect(lines[0]).to eq("provider name type link/path \n")
|
|
183
|
+
# expect(lines[1]).to eq("-------- ---- ---- -------------------------------------\n")
|
|
184
|
+
# expect(lines[-2]).to eq("-------- ---- ---- -------------------------------------\n")
|
|
185
|
+
# end
|
|
186
|
+
# end
|
|
187
|
+
#
|
|
188
|
+
# describe "the list of feeds" do
|
|
189
|
+
# it "should be sorted by provider name and then feed name" do
|
|
190
|
+
# generate_feedfile(File.join(@feed_path, "feed1.feed"), 'provider_b', 'feed_c')
|
|
191
|
+
# generate_feedfile(File.join(@feed_path, "feed2.feed"), 'provider_a', 'feed_d')
|
|
192
|
+
# generate_feedfile(File.join(@feed_path, "feed3.feed"), 'provider_a', 'feed_a')
|
|
193
|
+
# generate_feedfile(File.join(@feed_path, "feed4.feed"), 'provider_b', 'feed_d')
|
|
194
|
+
# generate_feedfile(File.join(@feed_path, "feed5.feed"), 'provider_a', 'feed_c')
|
|
195
|
+
# generate_feedfile(File.join(@feed_path, "feed6.feed"), 'provider_b', 'feed_a')
|
|
196
|
+
# generate_feedfile(File.join(@feed_path, "feed7.feed"), 'provider_b', 'feed_b')
|
|
197
|
+
# generate_feedfile(File.join(@feed_path, "feed8.feed"), 'provider_a', 'feed_b')
|
|
198
|
+
#
|
|
199
|
+
# runner.list(io_out: io_out);
|
|
200
|
+
# lines = io_out.string.lines.to_a
|
|
201
|
+
# expect(lines[2]).to eq("provider_a feed_a http https://foobar/provider_a/feed_a.data\n")
|
|
202
|
+
# expect(lines[3]).to eq("provider_a feed_b http https://foobar/provider_a/feed_b.data\n")
|
|
203
|
+
# expect(lines[4]).to eq("provider_a feed_c http https://foobar/provider_a/feed_c.data\n")
|
|
204
|
+
# expect(lines[5]).to eq("provider_a feed_d http https://foobar/provider_a/feed_d.data\n")
|
|
205
|
+
#
|
|
206
|
+
# expect(lines[6]).to eq("provider_b feed_a http https://foobar/provider_b/feed_a.data\n")
|
|
207
|
+
# expect(lines[7]).to eq("provider_b feed_b http https://foobar/provider_b/feed_b.data\n")
|
|
208
|
+
# expect(lines[8]).to eq("provider_b feed_c http https://foobar/provider_b/feed_c.data\n")
|
|
209
|
+
# expect(lines[9]).to eq("provider_b feed_d http https://foobar/provider_b/feed_d.data\n")
|
|
210
|
+
# end
|
|
211
|
+
# end
|
|
212
|
+
#
|
|
213
|
+
# describe "the footer" do
|
|
214
|
+
# it "should indicate the number of feeds" do
|
|
215
|
+
# 20.times do |i|
|
|
216
|
+
# generate_feedfile(File.join(@feed_path, "feed#{i}.feed"), "a#{i}", 'b', "http://" + ("A" * 10))
|
|
217
|
+
# end
|
|
218
|
+
# runner.list(io_out: io_out);
|
|
219
|
+
# lines = io_out.string.lines.to_a
|
|
220
|
+
# expect(lines[-1]).to eq("Total: 20\n")
|
|
221
|
+
# end
|
|
222
|
+
# end
|
|
223
|
+
# end
|
|
224
|
+
# end
|
|
225
|
+
#
|
|
226
|
+
# describe "#run" do
|
|
227
|
+
# before :each do
|
|
228
|
+
# @feed_path = Dir.mktmpdir
|
|
229
|
+
# generate_feedfile(File.join(@feed_path, "feed1.feed"), "provider1", "feed1")
|
|
230
|
+
# runner.add_feed_path(@feed_path)
|
|
231
|
+
# allow(Threatinator::FeedRunner).to receive(:run)
|
|
232
|
+
# end
|
|
233
|
+
#
|
|
234
|
+
# after :each do
|
|
235
|
+
# FileUtils.remove_entry_secure @feed_path
|
|
236
|
+
# end
|
|
237
|
+
#
|
|
238
|
+
# let(:loader) {
|
|
239
|
+
# x = Threatinator::PluginLoader.new
|
|
240
|
+
# x.load_plugins(:output)
|
|
241
|
+
# x }
|
|
242
|
+
#
|
|
243
|
+
#
|
|
244
|
+
# let(:output) { loader[:output][:null] }
|
|
245
|
+
#
|
|
246
|
+
# it "parses all the feeds" do
|
|
247
|
+
# expect(runner).to receive(:_load_feeds).and_call_original
|
|
248
|
+
# runner.run("provider1", "feed1", output)
|
|
249
|
+
# end
|
|
250
|
+
#
|
|
251
|
+
# context "when called with a provider and feed name that does not match a feed" do
|
|
252
|
+
# it "raises Threatinator::Exceptions::UnknownFeed" do
|
|
253
|
+
# expect {
|
|
254
|
+
# runner.run("foobar", "bla", output)
|
|
255
|
+
# }.to raise_error(Threatinator::Exceptions::UnknownFeed)
|
|
256
|
+
# end
|
|
257
|
+
# end
|
|
258
|
+
#
|
|
259
|
+
# context "when called with a provider and feed name that matches a feed" do
|
|
260
|
+
# it "loads the feed by the given provider and name" do
|
|
261
|
+
# expect(runner.registry).to receive(:get).with("provider1", "feed1").and_call_original
|
|
262
|
+
# runner.run("provider1", "feed1", output)
|
|
263
|
+
# end
|
|
264
|
+
#
|
|
265
|
+
# it "runs the feed" do
|
|
266
|
+
# opts_hash = {foo: 123}
|
|
267
|
+
# expect(Threatinator::FeedRunner).to receive(:run).with(kind_of(Threatinator::Feed), output, opts_hash)
|
|
268
|
+
# runner.run("provider1", "feed1", output, opts_hash)
|
|
269
|
+
# end
|
|
270
|
+
# end
|
|
271
|
+
# end
|
|
272
|
+
#
|
|
273
|
+
#end
|