fluent-plugin-gcloud-pubsub-custom-compress-batches 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,308 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+
5
+ require_relative "../test_helper"
6
+ require "fluent/test/driver/output"
7
+ require "fluent/test/helpers"
8
+
9
+ class GcloudPubSubOutputTest < Test::Unit::TestCase
10
+ include Fluent::Test::Helpers
11
+
12
+ CONFIG = %(
13
+ project project-test
14
+ topic topic-test
15
+ key key-test
16
+ )
17
+
18
+ ReRaisedError = Class.new(RuntimeError)
19
+
20
+ def create_driver(conf = CONFIG)
21
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::GcloudPubSubOutput).configure(conf)
22
+ end
23
+
24
+ setup do
25
+ Fluent::Test.setup
26
+ end
27
+
28
+ setup do
29
+ @time = event_time("2016-07-09 11:12:13 UTC")
30
+ end
31
+
32
+ sub_test_case "configure" do
33
+ test "default values are configured" do
34
+ d = create_driver(%(
35
+ project project-test
36
+ topic topic-test
37
+ key key-test
38
+ ))
39
+
40
+ assert_equal("project-test", d.instance.project)
41
+ assert_equal("topic-test", d.instance.topic)
42
+ assert_equal("key-test", d.instance.key)
43
+ assert_equal(false, d.instance.autocreate_topic)
44
+ assert_equal(1000, d.instance.max_messages)
45
+ assert_equal(9_800_000, d.instance.max_total_size)
46
+ assert_equal(4_000_000, d.instance.max_message_size)
47
+ end
48
+
49
+ test '"topic" must be specified' do
50
+ assert_raises Fluent::ConfigError do
51
+ create_driver(%(
52
+ project project-test
53
+ key key-test
54
+ ))
55
+ end
56
+ end
57
+
58
+ test '"autocreate_topic" can be specified' do
59
+ d = create_driver(%(
60
+ project project-test
61
+ topic topic-test
62
+ key key-test
63
+ autocreate_topic true
64
+ ))
65
+
66
+ assert_equal(true, d.instance.autocreate_topic)
67
+ end
68
+
69
+ test "'attribute_keys' cannot be used with 'compress_batches'" do
70
+ assert_raise(Fluent::ConfigError.new(":attribute_keys cannot be used when compression is enabled")) do
71
+ create_driver(%(
72
+ project project-test
73
+ topic topic-test
74
+ attribute_keys attr-test
75
+ compress_batches true
76
+ ))
77
+ end
78
+ end
79
+ end
80
+
81
+ sub_test_case "topic" do
82
+ setup do
83
+ @publisher = mock!
84
+ @pubsub_mock = mock!
85
+ stub(Google::Cloud::Pubsub).new { @pubsub_mock }
86
+ end
87
+
88
+ test '"autocreate_topic" is enabled' do
89
+ d = create_driver(%(
90
+ project project-test
91
+ topic topic-test
92
+ key key-test
93
+ autocreate_topic true
94
+ ))
95
+
96
+ @publisher.publish.once
97
+ @pubsub_mock.topic("topic-test").once { nil }
98
+ @pubsub_mock.create_topic("topic-test").once { @publisher }
99
+ d.run(default_tag: "test") do
100
+ d.feed(@time, { "a" => "b" })
101
+ end
102
+ end
103
+
104
+ test "40x error occurred on connecting to Pub/Sub" do
105
+ d = create_driver
106
+
107
+ @pubsub_mock.topic("topic-test").once do
108
+ raise Google::Cloud::NotFoundError, "TEST"
109
+ end
110
+
111
+ assert_raise Google::Cloud::NotFoundError do
112
+ d.run(default_tag: "test") do
113
+ d.feed(@time, { "a" => "b" })
114
+ end
115
+ end
116
+ end
117
+
118
+ test "50x error occurred on connecting to Pub/Sub" do
119
+ d = create_driver
120
+
121
+ @pubsub_mock.topic("topic-test").once do
122
+ raise Google::Cloud::UnavailableError, "TEST"
123
+ end
124
+
125
+ assert_raise Fluent::GcloudPubSub::RetryableError do
126
+ d.run(default_tag: "test") do
127
+ d.feed(@time, { "a" => "b" })
128
+ end
129
+ end
130
+ end
131
+
132
+ test "topic is nil" do
133
+ d = create_driver
134
+
135
+ @pubsub_mock.topic("topic-test").once { nil }
136
+
137
+ assert_raise Fluent::GcloudPubSub::Error do
138
+ d.run(default_tag: "test") do
139
+ d.feed(@time, { "a" => "b" })
140
+ end
141
+ end
142
+ end
143
+
144
+ test 'messages exceeding "max_message_size" are not published' do
145
+ d = create_driver(%(
146
+ project project-test
147
+ topic topic-test
148
+ key key-test
149
+ max_message_size 1000
150
+ ))
151
+
152
+ @publisher.publish.times(0)
153
+ d.run(default_tag: "test") do
154
+ d.feed(@time, { "a" => "a" * 1000 })
155
+ end
156
+ end
157
+ end
158
+
159
+ # Rubocop will erroneously correct the MessagePack.unpack call, for which there's no `unpack1` equivalent method.
160
+ # rubocop:disable Style/UnpackFirst
161
+ sub_test_case "publish" do
162
+ setup do
163
+ @publisher = mock!
164
+ @pubsub_mock = mock!.topic(anything) { @publisher }
165
+ stub(Google::Cloud::Pubsub).new { @pubsub_mock }
166
+ end
167
+
168
+ test 'messages are divided into "max_messages"' do
169
+ d = create_driver
170
+ @publisher.publish.times(2)
171
+ d.run(default_tag: "test") do
172
+ # max_messages is default 1000
173
+ 1001.times do |i|
174
+ d.feed(@time, { "a" => i })
175
+ end
176
+ end
177
+ end
178
+
179
+ test 'messages are divided into "max_total_size"' do
180
+ d = create_driver(%(
181
+ project project-test
182
+ topic topic-test
183
+ key key-test
184
+ max_messages 100000
185
+ max_total_size 1000
186
+ ))
187
+
188
+ @publisher.publish.times(2)
189
+ d.run(default_tag: "test") do
190
+ # 400 * 4 / max_total_size = twice
191
+ 4.times do
192
+ d.feed(@time, { "a" => "a" * 400 })
193
+ end
194
+ end
195
+ end
196
+
197
+ test 'accept "ASCII-8BIT" encoded multibyte strings' do
198
+ # on fluentd v0.14, all strings treated as "ASCII-8BIT" except specified encoding.
199
+ d = create_driver
200
+ @publisher.publish.once
201
+ d.run(default_tag: "test") do
202
+ d.feed(@time, { "a" => "あああ".dup.force_encoding("ASCII-8BIT") })
203
+ end
204
+ end
205
+
206
+ test "reraise unexpected errors" do
207
+ d = create_driver
208
+ @publisher.publish.once { raise ReRaisedError }
209
+ assert_raises ReRaisedError do
210
+ d.run(default_tag: "test") do
211
+ d.feed([{ "a" => 1, "b" => 2 }])
212
+ end
213
+ end
214
+ end
215
+
216
+ test "reraise RetryableError" do
217
+ d = create_driver
218
+ @publisher.publish.once { raise Google::Cloud::UnavailableError, "TEST" }
219
+ assert_raises Fluent::GcloudPubSub::RetryableError do
220
+ d.run(default_tag: "test") do
221
+ d.feed([{ "a" => 1, "b" => 2 }])
222
+ end
223
+ end
224
+ end
225
+
226
+ test "inject section" do
227
+ d = create_driver(%(
228
+ project project-test
229
+ topic topic-test
230
+ key key-test
231
+ <inject>
232
+ tag_key tag
233
+ </inject>
234
+ ))
235
+ @publisher.publish.once
236
+ d.run(default_tag: "test") do
237
+ d.feed({ "foo" => "bar" })
238
+ end
239
+ assert_equal({ "tag" => "test", "foo" => "bar" }, JSON.parse(MessagePack.unpack(d.formatted.first)[0]))
240
+ end
241
+
242
+ test "compressed batch" do
243
+ d = create_driver(%(
244
+ project project-test
245
+ topic topic-test
246
+ key key-test
247
+ compress_batches true
248
+ max_messages 2
249
+ ))
250
+
251
+ # This is a little hacky: we're doing assertions via matchers.
252
+ # The RR library doesn't seem to provide an easy alternative to this. The
253
+ # downside of this approach is that you will not receive a nice diff if
254
+ # the expectation fails.
255
+ first_batch = [
256
+ '{"foo":"bar"}' + "\n",
257
+ '{"foo":123}' + "\n",
258
+ ]
259
+ @publisher.publish(ZlibCompressedBatch.new(first_batch), { compression_algorithm: "zlib" }).once
260
+
261
+ second_batch = [
262
+ '{"msg":"last"}' + "\n",
263
+ ]
264
+ @publisher.publish(ZlibCompressedBatch.new(second_batch), { compression_algorithm: "zlib" }).once
265
+
266
+ d.run(default_tag: "test") do
267
+ d.feed({ "foo" => "bar" })
268
+ d.feed({ "foo" => 123 })
269
+ d.feed({ "msg" => "last" })
270
+ end
271
+ end
272
+ end
273
+ # rubocop:enable Style/UnpackFirst
274
+ end
275
+
276
+ private
277
+
278
+ # A matcher for a compressed batch of messages
279
+ # https://www.rubydoc.info/gems/rr/1.2.1/RR/WildcardMatchers
280
+ class ZlibCompressedBatch
281
+ attr_reader :expected_messages
282
+
283
+ def initialize(expected_messages)
284
+ @expected_messages = expected_messages
285
+ end
286
+
287
+ def wildcard_match?(other)
288
+ return true if self == other
289
+
290
+ return false unless other.is_a?(String)
291
+
292
+ decompressed = Zlib::Inflate.inflate(other)
293
+ other_messages = decompressed.split(30.chr)
294
+
295
+ other_messages == expected_messages
296
+ end
297
+
298
+ def ==(other)
299
+ other.is_a?(self.class) &&
300
+ other.expected_messages == expected_messages
301
+ end
302
+
303
+ alias eql? ==
304
+
305
+ def inspect
306
+ "contains compressed messages: #{expected_messages}"
307
+ end
308
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubygems"
4
+ require "bundler"
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ warn e.message
9
+ warn "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require "test/unit"
13
+ require "test/unit/rr"
14
+
15
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
16
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
17
+
18
+ require "fluent/test"
19
+ unless ENV.key?("VERBOSE")
20
+ nulllogger = Object.new
21
+ nulllogger.instance_eval do |_obj|
22
+ def method_missing(method, *args)
23
+ # pass
24
+ end
25
+ end
26
+ $log = nulllogger
27
+ end
28
+
29
+ require "fluent/plugin/in_gcloud_pubsub"
30
+ require "fluent/plugin/out_gcloud_pubsub"
31
+
32
+ class Test::Unit::TestCase
33
+ end
metadata ADDED
@@ -0,0 +1,208 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-gcloud-pubsub-custom-compress-batches
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.4
5
+ platform: ruby
6
+ authors:
7
+ - Calvin Aditya
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.15
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.14.15
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: google-cloud-pubsub
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.30.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.30.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: prometheus-client
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.10'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.10'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: pry
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: pry-byebug
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rake
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rubocop
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.83'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.83'
131
+ - !ruby/object:Gem::Dependency
132
+ name: test-unit
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: test-unit-rr
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ description: Google Cloud Pub/Sub input/output plugin for Fluentd event collector
160
+ - with payload compression. Forked from https://github.com/gocardless/fluent-plugin-gcloud-pubsub-custom
161
+ email: calvin.aditya95@gmail.com
162
+ executables: []
163
+ extensions: []
164
+ extra_rdoc_files: []
165
+ files:
166
+ - ".gitignore"
167
+ - ".rubocop.yml"
168
+ - ".rubocop_todo.yml"
169
+ - ".ruby-version"
170
+ - ".travis.yml"
171
+ - CHANGELOG.md
172
+ - Gemfile
173
+ - LICENSE
174
+ - README.md
175
+ - Rakefile
176
+ - fluent-plugin-gcloud-pubsub-custom.gemspec
177
+ - lib/fluent/plugin/gcloud_pubsub/client.rb
178
+ - lib/fluent/plugin/gcloud_pubsub/metrics.rb
179
+ - lib/fluent/plugin/in_gcloud_pubsub.rb
180
+ - lib/fluent/plugin/out_gcloud_pubsub.rb
181
+ - test/plugin/test_in_gcloud_pubsub.rb
182
+ - test/plugin/test_out_gcloud_pubsub.rb
183
+ - test/test_helper.rb
184
+ homepage: https://github.com/calvinaditya95/fluent-plugin-gcloud-pubsub-custom
185
+ licenses:
186
+ - MIT
187
+ metadata: {}
188
+ post_install_message:
189
+ rdoc_options: []
190
+ require_paths:
191
+ - lib
192
+ required_ruby_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ required_rubygems_version: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ requirements: []
203
+ rubygems_version: 3.1.2
204
+ signing_key:
205
+ specification_version: 4
206
+ summary: Google Cloud Pub/Sub input/output plugin for Fluentd event collector - with
207
+ payload compression
208
+ test_files: []