Skip to content

Commit f1dfb81

Browse files
nilskuhnarichiardi
authored andcommitted
✅ Added tests
1 parent b69a38f commit f1dfb81

File tree

7 files changed

+364
-14
lines changed

7 files changed

+364
-14
lines changed

lib/logstash/outputs/mongodb.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def validate_config
9191
if @action != "insert" && @action != "update" && @action != "replace"
9292
raise LogStash::ConfigurationError, "Only insert, update and replace are valid for 'action' setting."
9393
end
94-
if (@action == "update" || @action == "replace") && @query_value.blank?
94+
if (@action == "update" || @action == "replace") && (@query_value.nil? || @query_value.empty?)
9595
raise LogStash::ConfigurationError, "If action is update or replace, query_value must be set."
9696
end
9797
end
@@ -160,6 +160,7 @@ def get_write_ops(documents)
160160
ops = []
161161
documents.each do |doc|
162162
replaced_query_value = doc["metadata_mongodb_output_query_value"]
163+
doc.delete("metadata_mongodb_output_query_value")
163164
if @action == "insert"
164165
ops << {:insert_one => doc}
165166
elsif @action == "update"

spec/integration/mongodb_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
let(:database) { 'logstash' }
88
let(:collection) { 'logs' }
99
let(:uuid) { SecureRandom.uuid }
10+
let(:action) { 'insert' }
1011

1112
let(:config) do
1213
{ "uri" => uri, "database" => database,
13-
"collection" => collection, "isodate" => true }
14+
"collection" => collection, "isodate" => true, "action" => action }
1415
end
1516

1617
describe "#send" do
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# encoding: utf-8
2+
require_relative "../spec_helper"
3+
require "logstash/plugin"
4+
5+
describe LogStash::Outputs::Mongodb do
6+
7+
let(:uri) { 'mongodb://localhost:27017' }
8+
let(:database) { 'logstash' }
9+
let(:collection) { 'logs' }
10+
11+
describe "validate_config method" do
12+
13+
subject! { LogStash::Outputs::Mongodb.new(config) }
14+
15+
[
16+
{:action => "not-supported", :query_key => "qk", :query_value => "qv", :upsert => false,
17+
:expected_reason => "Only insert, update and replace are valid for 'action' setting."},
18+
{:action => "update", :query_key => "qk", :query_value => nil, :upsert => false,
19+
:expected_reason => "If action is update or replace, query_value must be set."},
20+
{:action => "update", :query_key => "qk", :query_value => "", :upsert => false,
21+
:expected_reason => "If action is update or replace, query_value must be set."},
22+
{:action => "replace", :query_key => "qk", :query_value => nil, :upsert => false,
23+
:expected_reason => "If action is update or replace, query_value must be set."},
24+
{:action => "replace", :query_key => "qk", :query_value => "", :upsert => false,
25+
:expected_reason => "If action is update or replace, query_value must be set."},
26+
{:action => "insert", :bulk_size => 1001,
27+
:expected_reason => "Bulk size must be lower than '1000', currently '1001'"},
28+
].each do |test|
29+
30+
describe "when validating config with action '#{test[:action]}' query_key '#{test[:query_key]}', query_value '#{test[:query_value]}' and upsert '#{test[:upsert]}'" do
31+
32+
let(:config) {
33+
configuration = {
34+
"uri" => uri,
35+
"database" => database,
36+
"collection" => collection
37+
}
38+
unless test[:action].nil?
39+
configuration["action"] = test[:action]
40+
end
41+
unless test[:query_key].nil?
42+
configuration["query_key"] = test[:query_key]
43+
end
44+
unless test[:query_value].nil?
45+
configuration["query_value"] = test[:query_value]
46+
end
47+
unless test[:upsert].nil?
48+
configuration["upsert"] = test[:upsert]
49+
end
50+
unless test[:bulk_size].nil?
51+
configuration["bulk_size"] = test[:bulk_size]
52+
end
53+
return configuration
54+
}
55+
56+
it "should raise error: #{test[:expected_reason]}" do
57+
expect { subject.validate_config }.to raise_error(LogStash::ConfigurationError, test[:expected_reason])
58+
end
59+
end
60+
61+
end
62+
63+
end
64+
end

spec/outputs/mongodb_spec.rb renamed to spec/outputs/mongodb_insert_spec.rb

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
let(:uri) { 'mongodb://localhost:27017' }
88
let(:database) { 'logstash' }
99
let(:collection) { 'logs' }
10+
let(:action) { 'insert' }
1011

1112
let(:config) {{
1213
"uri" => uri,
1314
"database" => database,
14-
"collection" => collection
15+
"collection" => collection,
16+
"action" => action
1517
}}
1618

1719
it "should register and close" do
@@ -20,7 +22,7 @@
2022
plugin.close
2123
end
2224

23-
describe "receive" do
25+
describe "receive method while action is 'insert'" do
2426
subject! { LogStash::Outputs::Mongodb.new(config) }
2527

2628
let(:event) { LogStash::Event.new(properties) }
@@ -32,15 +34,15 @@
3234
allow(Mongo::Client).to receive(:new).and_return(connection)
3335
allow(connection).to receive(:use).and_return(client)
3436
allow(client).to receive(:[]).and_return(collection)
35-
allow(collection).to receive(:insert_one)
37+
allow(collection).to receive(:bulk_write)
3638
subject.register
3739
end
3840

3941
after(:each) do
4042
subject.close
4143
end
4244

43-
describe "#send" do
45+
describe "when processing an event" do
4446
let(:properties) {{
4547
"message" => "This is a message!",
4648
"uuid" => SecureRandom.uuid,
@@ -49,36 +51,41 @@
4951
}}
5052

5153
it "should send the event to the database" do
52-
expect(collection).to receive(:insert_one)
54+
expect(collection).to receive(:bulk_write)
5355
subject.receive(event)
5456
end
5557
end
5658

57-
describe "no event @timestamp" do
59+
describe "when processing an event without @timestamp set" do
5860
let(:properties) { { "message" => "foo" } }
5961

60-
it "should not contain a @timestamp field in the mongo document" do
62+
it "should send a document without @timestamp field to mongodb" do
6163
expect(event).to receive(:timestamp).and_return(nil)
6264
expect(event).to receive(:to_hash).and_return(properties)
63-
expect(collection).to receive(:insert_one).with(properties)
65+
expect(collection).to receive(:bulk_write).with(
66+
[ {:insert_one => properties} ]
67+
)
6468
subject.receive(event)
6569
end
6670
end
6771

68-
describe "generateId" do
72+
describe "when generateId is set" do
6973
let(:properties) { { "message" => "foo" } }
7074
let(:config) {{
7175
"uri" => uri,
7276
"database" => database,
7377
"collection" => collection,
74-
"generateId" => true
78+
"generateId" => true,
79+
"action" => "insert"
7580
}}
7681

77-
it "should contain a BSON::ObjectId as _id" do
82+
it "should send a document containing a BSON::ObjectId as _id to mongodb" do
7883
expect(BSON::ObjectId).to receive(:new).and_return("BSON::ObjectId")
7984
expect(event).to receive(:timestamp).and_return(nil)
8085
expect(event).to receive(:to_hash).and_return(properties)
81-
expect(collection).to receive(:insert_one).with(properties.merge("_id" => "BSON::ObjectId"))
86+
expect(collection).to receive(:bulk_write).with(
87+
[ {:insert_one => properties.merge("_id" => "BSON::ObjectId")} ]
88+
)
8289
subject.receive(event)
8390
end
8491
end

spec/outputs/mongodb_replace_spec.rb

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# encoding: utf-8
2+
require_relative "../spec_helper"
3+
require "logstash/plugin"
4+
5+
describe LogStash::Outputs::Mongodb do
6+
7+
let(:uri) { 'mongodb://localhost:27017' }
8+
let(:database) { 'logstash' }
9+
let(:collection) { 'logs' }
10+
let(:action) { 'replace' }
11+
12+
let(:config) { {
13+
"uri" => uri,
14+
"database" => database,
15+
"collection" => collection,
16+
"action" => action
17+
} }
18+
19+
describe "receive method while action is 'replace'" do
20+
subject! { LogStash::Outputs::Mongodb.new(config) }
21+
22+
let(:properties) { {
23+
"message" => "This is a message!",
24+
"uuid" => SecureRandom.uuid,
25+
"number" => BigDecimal.new("4321.1234"),
26+
"utf8" => "żółć"
27+
} }
28+
let(:event) { LogStash::Event.new(properties) }
29+
let(:connection) { double("connection") }
30+
let(:client) { double("client") }
31+
let(:collection) { double("collection") }
32+
33+
before(:each) do
34+
allow(Mongo::Client).to receive(:new).and_return(connection)
35+
allow(connection).to receive(:use).and_return(client)
36+
allow(client).to receive(:[]).and_return(collection)
37+
allow(collection).to receive(:bulk_write)
38+
subject.register
39+
end
40+
41+
after(:each) do
42+
subject.close
43+
end
44+
45+
[
46+
{:query_key => nil, :query_value => "qv", :upsert => false,
47+
:expected => {:query_key => "_id", :query_value => "qv", :upsert => false}
48+
},
49+
{:query_key => "qk", :query_value => "qv", :upsert => false,
50+
:expected => {:query_key => "qk", :query_value => "qv", :upsert => false}
51+
},
52+
{:query_key => "qk", :query_value => "qv", :upsert => nil,
53+
:expected => {:query_key => "qk", :query_value => "qv", :upsert => false}
54+
},
55+
{:query_key => nil, :query_value => "qv", :upsert => true,
56+
:expected => {:query_key => "_id", :query_value => "qv", :upsert => true}
57+
},
58+
{:query_key => "qk", :query_value => "qv", :upsert => true,
59+
:expected => {:query_key => "qk", :query_value => "qv", :upsert => true}
60+
},
61+
].each do |test|
62+
63+
describe "when processing an event with query_key set to '#{test[:query_key]}', query_value set to '#{test[:query_value]}' and upsert set to '#{test[:upsert]}'" do
64+
65+
let(:config) {
66+
configuration = {
67+
"uri" => uri,
68+
"database" => database,
69+
"collection" => collection,
70+
"action" => action
71+
}
72+
unless test[:query_key].nil?
73+
configuration["query_key"] = test[:query_key]
74+
end
75+
unless test[:query_value].nil?
76+
configuration["query_value"] = test[:query_value]
77+
end
78+
unless test[:upsert].nil?
79+
configuration["upsert"] = test[:upsert]
80+
end
81+
return configuration
82+
}
83+
84+
expected = test[:expected]
85+
it "should send that document as a replace to mongodb with query_key '#{expected[:query_key]}', query_value '#{expected[:query_value]}' and upsert '#{expected[:upsert]}'" do
86+
expect(event).to receive(:timestamp).and_return(nil)
87+
expect(event).to receive(:to_hash).and_return(properties)
88+
expect(collection).to receive(:bulk_write).with(
89+
[{:replace_one => {:filter => {expected[:query_key] => expected[:query_value]}, :replacement => properties, :upsert => expected[:upsert]}}]
90+
)
91+
subject.receive(event)
92+
end
93+
end
94+
95+
end
96+
97+
end
98+
end
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# encoding: utf-8
2+
require_relative "../spec_helper"
3+
require "logstash/plugin"
4+
5+
describe LogStash::Outputs::Mongodb do
6+
7+
let(:uri) { 'mongodb://localhost:27017' }
8+
let(:database) { 'logstash' }
9+
let(:collection) { 'logs' }
10+
let(:action) { 'update' }
11+
let(:query_value) { 'qv' }
12+
13+
let(:config) { {
14+
"uri" => uri,
15+
"database" => database,
16+
"collection" => collection,
17+
"action" => action,
18+
"query_value" => query_value
19+
} }
20+
21+
describe "receive method while action is 'update'" do
22+
subject! { LogStash::Outputs::Mongodb.new(config) }
23+
24+
let(:properties) { {
25+
"message" => "This is a message!",
26+
"hashField" => {
27+
"numField" => 1,
28+
"hashField" => {
29+
"numField": 2
30+
},
31+
"arrayField" => ["one", "two", "three"]
32+
},
33+
"arrayField": [
34+
{"strField" => "four"},
35+
{"strField" => "five"},
36+
{"strField" => "six"},
37+
"numField" => 3
38+
]
39+
} }
40+
let(:event) { LogStash::Event.new(properties) }
41+
let(:connection) { double("connection") }
42+
let(:client) { double("client") }
43+
let(:collection) { double("collection") }
44+
45+
before(:each) do
46+
allow(Mongo::Client).to receive(:new).and_return(connection)
47+
allow(connection).to receive(:use).and_return(client)
48+
allow(client).to receive(:[]).and_return(collection)
49+
allow(collection).to receive(:bulk_write)
50+
subject.register
51+
end
52+
53+
after(:each) do
54+
subject.close
55+
end
56+
57+
describe "when processing an event with nested hash" do
58+
59+
it "should send a document update to mongodb with dotted notation" do
60+
expect(event).to receive(:timestamp).and_return(nil)
61+
expect(event).to receive(:to_hash).and_return(properties)
62+
expect(collection).to receive(:bulk_write).with(
63+
[{:update_one => {:filter => {"_id" => query_value}, :update => {"$set" => {
64+
"message" => "This is a message!",
65+
"hashField.numField" => 1,
66+
"hashField.hashField.numField" => 2,
67+
"hashField.arrayField.0" => "one",
68+
"hashField.arrayField.1" => "two",
69+
"hashField.arrayField.2" => "three",
70+
"arrayField.0.strField" => "four",
71+
"arrayField.1.strField" => "five",
72+
"arrayField.2.strField" => "six",
73+
"arrayField.3.numField" => 3,
74+
}}, :upsert => false}}]
75+
)
76+
subject.receive(event)
77+
end
78+
end
79+
80+
end
81+
end

0 commit comments

Comments
 (0)