logstash-core 2.2.4.snapshot1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of logstash-core might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/lib/logstash-core.rb +1 -0
- data/lib/logstash-core/logstash-core.rb +3 -0
- data/lib/logstash-core/version.rb +8 -0
- data/lib/logstash/agent.rb +391 -0
- data/lib/logstash/codecs/base.rb +50 -0
- data/lib/logstash/config/config_ast.rb +550 -0
- data/lib/logstash/config/cpu_core_strategy.rb +32 -0
- data/lib/logstash/config/defaults.rb +12 -0
- data/lib/logstash/config/file.rb +39 -0
- data/lib/logstash/config/grammar.rb +3503 -0
- data/lib/logstash/config/mixin.rb +518 -0
- data/lib/logstash/config/registry.rb +13 -0
- data/lib/logstash/environment.rb +98 -0
- data/lib/logstash/errors.rb +12 -0
- data/lib/logstash/filters/base.rb +205 -0
- data/lib/logstash/inputs/base.rb +116 -0
- data/lib/logstash/inputs/threadable.rb +18 -0
- data/lib/logstash/java_integration.rb +116 -0
- data/lib/logstash/json.rb +61 -0
- data/lib/logstash/logging.rb +91 -0
- data/lib/logstash/namespace.rb +13 -0
- data/lib/logstash/output_delegator.rb +172 -0
- data/lib/logstash/outputs/base.rb +91 -0
- data/lib/logstash/patches.rb +5 -0
- data/lib/logstash/patches/bugfix_jruby_2558.rb +51 -0
- data/lib/logstash/patches/cabin.rb +35 -0
- data/lib/logstash/patches/profile_require_calls.rb +47 -0
- data/lib/logstash/patches/rubygems.rb +38 -0
- data/lib/logstash/patches/stronger_openssl_defaults.rb +68 -0
- data/lib/logstash/pipeline.rb +499 -0
- data/lib/logstash/pipeline_reporter.rb +114 -0
- data/lib/logstash/plugin.rb +120 -0
- data/lib/logstash/program.rb +14 -0
- data/lib/logstash/runner.rb +124 -0
- data/lib/logstash/shutdown_watcher.rb +100 -0
- data/lib/logstash/util.rb +203 -0
- data/lib/logstash/util/buftok.rb +139 -0
- data/lib/logstash/util/charset.rb +35 -0
- data/lib/logstash/util/decorators.rb +52 -0
- data/lib/logstash/util/defaults_printer.rb +31 -0
- data/lib/logstash/util/filetools.rb +186 -0
- data/lib/logstash/util/java_version.rb +66 -0
- data/lib/logstash/util/password.rb +25 -0
- data/lib/logstash/util/plugin_version.rb +56 -0
- data/lib/logstash/util/prctl.rb +10 -0
- data/lib/logstash/util/retryable.rb +40 -0
- data/lib/logstash/util/socket_peer.rb +7 -0
- data/lib/logstash/util/unicode_trimmer.rb +81 -0
- data/lib/logstash/util/worker_threads_default_printer.rb +29 -0
- data/lib/logstash/util/wrapped_synchronous_queue.rb +41 -0
- data/lib/logstash/version.rb +14 -0
- data/locales/en.yml +204 -0
- data/logstash-core.gemspec +58 -0
- data/spec/conditionals_spec.rb +429 -0
- data/spec/logstash/agent_spec.rb +85 -0
- data/spec/logstash/config/config_ast_spec.rb +146 -0
- data/spec/logstash/config/cpu_core_strategy_spec.rb +123 -0
- data/spec/logstash/config/defaults_spec.rb +10 -0
- data/spec/logstash/config/mixin_spec.rb +158 -0
- data/spec/logstash/environment_spec.rb +56 -0
- data/spec/logstash/filters/base_spec.rb +251 -0
- data/spec/logstash/inputs/base_spec.rb +74 -0
- data/spec/logstash/java_integration_spec.rb +304 -0
- data/spec/logstash/json_spec.rb +96 -0
- data/spec/logstash/output_delegator_spec.rb +144 -0
- data/spec/logstash/outputs/base_spec.rb +40 -0
- data/spec/logstash/patches_spec.rb +90 -0
- data/spec/logstash/pipeline_reporter_spec.rb +85 -0
- data/spec/logstash/pipeline_spec.rb +455 -0
- data/spec/logstash/plugin_spec.rb +169 -0
- data/spec/logstash/runner_spec.rb +68 -0
- data/spec/logstash/shutdown_watcher_spec.rb +113 -0
- data/spec/logstash/util/buftok_spec.rb +31 -0
- data/spec/logstash/util/charset_spec.rb +74 -0
- data/spec/logstash/util/defaults_printer_spec.rb +50 -0
- data/spec/logstash/util/java_version_spec.rb +79 -0
- data/spec/logstash/util/plugin_version_spec.rb +64 -0
- data/spec/logstash/util/unicode_trimmer_spec.rb +55 -0
- data/spec/logstash/util/worker_threads_default_printer_spec.rb +45 -0
- data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +28 -0
- data/spec/logstash/util_spec.rb +35 -0
- metadata +364 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
require "logstash/plugin"
|
4
|
+
|
5
|
+
describe LogStash::Plugin do
|
6
|
+
it "should fail lookup on inexisting type" do
|
7
|
+
expect_any_instance_of(Cabin::Channel).to receive(:debug).once
|
8
|
+
expect { LogStash::Plugin.lookup("badbadtype", "badname") }.to raise_error(LogStash::PluginLoadingError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should fail lookup on inexisting name" do
|
12
|
+
expect_any_instance_of(Cabin::Channel).to receive(:debug).once
|
13
|
+
expect { LogStash::Plugin.lookup("filter", "badname") }.to raise_error(LogStash::PluginLoadingError)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should fail on bad plugin class" do
|
17
|
+
LogStash::Filters::BadSuperClass = Class.new
|
18
|
+
expect { LogStash::Plugin.lookup("filter", "bad_super_class") }.to raise_error(LogStash::PluginLoadingError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should fail on missing config_name method" do
|
22
|
+
LogStash::Filters::MissingConfigName = Class.new(LogStash::Filters::Base)
|
23
|
+
expect { LogStash::Plugin.lookup("filter", "missing_config_name") }.to raise_error(LogStash::PluginLoadingError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should lookup an already defined plugin class" do
|
27
|
+
class LogStash::Filters::LadyGaga < LogStash::Filters::Base
|
28
|
+
config_name "lady_gaga"
|
29
|
+
end
|
30
|
+
expect(LogStash::Plugin.lookup("filter", "lady_gaga")).to eq(LogStash::Filters::LadyGaga)
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#inspect" do
|
34
|
+
class LogStash::Filters::MyTestFilter < LogStash::Filters::Base
|
35
|
+
config_name "param1"
|
36
|
+
config :num, :validate => :number, :default => 20
|
37
|
+
config :str, :validate => :string, :default => "test"
|
38
|
+
end
|
39
|
+
subject { LogStash::Filters::MyTestFilter.new("num" => 1, "str" => "hello") }
|
40
|
+
|
41
|
+
it "should print the class of the filter" do
|
42
|
+
expect(subject.inspect).to match(/^<LogStash::Filters::MyTestFilter/)
|
43
|
+
end
|
44
|
+
it "should list config options and values" do
|
45
|
+
expect(subject.inspect).to match(/num=>1, str=>"hello"/)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when validating the plugin version" do
|
50
|
+
let(:plugin_name) { 'logstash-filter-stromae' }
|
51
|
+
subject do
|
52
|
+
Class.new(LogStash::Filters::Base) do
|
53
|
+
config_name 'stromae'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "doesn't warn the user if the version is superior or equal to 1.0.0" do
|
58
|
+
allow(Gem::Specification).to receive(:find_by_name)
|
59
|
+
.with(plugin_name)
|
60
|
+
.and_return(double(:version => Gem::Version.new('1.0.0')))
|
61
|
+
|
62
|
+
expect_any_instance_of(Cabin::Channel).not_to receive(:info)
|
63
|
+
subject.validate({})
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'warns the user if the plugin version is between 0.9.x and 1.0.0' do
|
67
|
+
allow(Gem::Specification).to receive(:find_by_name)
|
68
|
+
.with(plugin_name)
|
69
|
+
.and_return(double(:version => Gem::Version.new('0.9.1')))
|
70
|
+
|
71
|
+
expect_any_instance_of(Cabin::Channel).to receive(:info)
|
72
|
+
.with(/Using version 0.9.x/)
|
73
|
+
|
74
|
+
subject.validate({})
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'warns the user if the plugin version is inferior to 0.9.x' do
|
78
|
+
allow(Gem::Specification).to receive(:find_by_name)
|
79
|
+
.with(plugin_name)
|
80
|
+
.and_return(double(:version => Gem::Version.new('0.1.1')))
|
81
|
+
|
82
|
+
expect_any_instance_of(Cabin::Channel).to receive(:info)
|
83
|
+
.with(/Using version 0.1.x/)
|
84
|
+
subject.validate({})
|
85
|
+
end
|
86
|
+
|
87
|
+
it "doesnt show the version notice more than once" do
|
88
|
+
one_notice = Class.new(LogStash::Filters::Base) do
|
89
|
+
config_name "stromae"
|
90
|
+
end
|
91
|
+
|
92
|
+
allow(Gem::Specification).to receive(:find_by_name)
|
93
|
+
.with(plugin_name)
|
94
|
+
.and_return(double(:version => Gem::Version.new('0.1.1')))
|
95
|
+
|
96
|
+
expect_any_instance_of(Cabin::Channel).to receive(:info)
|
97
|
+
.once
|
98
|
+
.with(/Using version 0.1.x/)
|
99
|
+
|
100
|
+
one_notice.validate({})
|
101
|
+
one_notice.validate({})
|
102
|
+
end
|
103
|
+
|
104
|
+
it "warns the user if we can't find a defined version" do
|
105
|
+
expect_any_instance_of(Cabin::Channel).to receive(:warn)
|
106
|
+
.once
|
107
|
+
.with(/plugin doesn't have a version/)
|
108
|
+
|
109
|
+
subject.validate({})
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
it 'logs a warning if the plugin use the milestone option' do
|
114
|
+
expect_any_instance_of(Cabin::Channel).to receive(:warn)
|
115
|
+
.with(/stromae plugin is using the 'milestone' method/)
|
116
|
+
|
117
|
+
class LogStash::Filters::Stromae < LogStash::Filters::Base
|
118
|
+
config_name "stromae"
|
119
|
+
milestone 2
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "subclass initialize" do
|
125
|
+
let(:args) { Hash.new }
|
126
|
+
|
127
|
+
[
|
128
|
+
StromaeCodec = Class.new(LogStash::Codecs::Base) do
|
129
|
+
config_name "stromae"
|
130
|
+
config :foo_tag, :validate => :string, :default => "bar"
|
131
|
+
end,
|
132
|
+
StromaeFilter = Class.new(LogStash::Filters::Base) do
|
133
|
+
config_name "stromae"
|
134
|
+
config :foo_tag, :validate => :string, :default => "bar"
|
135
|
+
end,
|
136
|
+
StromaeInput = Class.new(LogStash::Inputs::Base) do
|
137
|
+
config_name "stromae"
|
138
|
+
config :foo_tag, :validate => :string, :default => "bar"
|
139
|
+
end,
|
140
|
+
StromaeOutput = Class.new(LogStash::Outputs::Base) do
|
141
|
+
config_name "stromae"
|
142
|
+
config :foo_tag, :validate => :string, :default => "bar"
|
143
|
+
end
|
144
|
+
].each do |klass|
|
145
|
+
|
146
|
+
it "subclass #{klass.name} does not modify params" do
|
147
|
+
klass.new(args)
|
148
|
+
expect(args).to be_empty
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "codec initialization" do
|
153
|
+
|
154
|
+
class LogStash::Codecs::Noop < LogStash::Codecs::Base
|
155
|
+
config_name "noop"
|
156
|
+
|
157
|
+
config :format, :validate => :string
|
158
|
+
def register; end
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should only register once" do
|
162
|
+
args = { "codec" => LogStash::Codecs::Noop.new("format" => ".") }
|
163
|
+
expect_any_instance_of(LogStash::Codecs::Noop).to receive(:register).once
|
164
|
+
LogStash::Plugin.new(args)
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
require "logstash/runner"
|
4
|
+
require "stud/task"
|
5
|
+
require "stud/trap"
|
6
|
+
|
7
|
+
class NullRunner
|
8
|
+
def run(args); end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe LogStash::Runner do
|
12
|
+
|
13
|
+
context "argument parsing" do
|
14
|
+
it "should run agent" do
|
15
|
+
expect(Stud::Task).to receive(:new).once.and_return(nil)
|
16
|
+
args = ["agent", "-e", ""]
|
17
|
+
expect(subject.run(args)).to eq(nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should run agent help" do
|
21
|
+
expect(subject).to receive(:show_help).once.and_return(nil)
|
22
|
+
args = ["agent", "-h"]
|
23
|
+
expect(subject.run(args).wait).to eq(0)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should show help with no arguments" do
|
27
|
+
expect($stderr).to receive(:puts).once.and_return("No command given")
|
28
|
+
expect($stderr).to receive(:puts).once
|
29
|
+
args = []
|
30
|
+
expect(subject.run(args).wait).to eq(1)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should show help for unknown commands" do
|
34
|
+
expect($stderr).to receive(:puts).once.and_return("No such command welp")
|
35
|
+
expect($stderr).to receive(:puts).once
|
36
|
+
args = ["welp"]
|
37
|
+
expect(subject.run(args).wait).to eq(1)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "pipeline settings" do
|
42
|
+
let(:pipeline_string) { "input { stdin {} } output { stdout {} }" }
|
43
|
+
let(:base_pipeline_settings) { { :pipeline_id => "base", :debug_config => false } }
|
44
|
+
let(:pipeline) { double("pipeline") }
|
45
|
+
|
46
|
+
before(:each) do
|
47
|
+
task = Stud::Task.new { 1 }
|
48
|
+
allow(pipeline).to receive(:run).and_return(task)
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when pipeline workers is not defined by the user" do
|
52
|
+
it "should not pass the value to the pipeline" do
|
53
|
+
expect(LogStash::Pipeline).to receive(:new).with(pipeline_string, base_pipeline_settings).and_return(pipeline)
|
54
|
+
args = ["agent", "-e", pipeline_string]
|
55
|
+
subject.run(args).wait
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when pipeline workers is defined by the user" do
|
60
|
+
it "should pass the value to the pipeline" do
|
61
|
+
base_pipeline_settings[:pipeline_workers] = 2
|
62
|
+
expect(LogStash::Pipeline).to receive(:new).with(pipeline_string, base_pipeline_settings).and_return(pipeline)
|
63
|
+
args = ["agent", "-w", "2", "-e", pipeline_string]
|
64
|
+
subject.run(args).wait
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
require "logstash/shutdown_watcher"
|
4
|
+
|
5
|
+
describe LogStash::ShutdownWatcher do
|
6
|
+
|
7
|
+
let(:check_every) { 0.01 }
|
8
|
+
let(:check_threshold) { 100 }
|
9
|
+
subject { LogStash::ShutdownWatcher.new(pipeline, check_every) }
|
10
|
+
let(:pipeline) { double("pipeline") }
|
11
|
+
let(:reporter) { double("reporter") }
|
12
|
+
let(:reporter_snapshot) { double("reporter snapshot") }
|
13
|
+
report_count = 0
|
14
|
+
|
15
|
+
before :each do
|
16
|
+
allow(pipeline).to receive(:reporter).and_return(reporter)
|
17
|
+
allow(reporter).to receive(:snapshot).and_return(reporter_snapshot)
|
18
|
+
allow(reporter_snapshot).to receive(:o_simple_hash).and_return({})
|
19
|
+
|
20
|
+
allow(subject).to receive(:pipeline_report_snapshot).and_wrap_original do |m, *args|
|
21
|
+
report_count += 1
|
22
|
+
m.call(*args)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
after :each do
|
27
|
+
report_count = 0
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when pipeline is stalled" do
|
31
|
+
let(:increasing_count) { (1..5000).to_a }
|
32
|
+
before :each do
|
33
|
+
allow(reporter_snapshot).to receive(:inflight_count).and_return(*increasing_count)
|
34
|
+
allow(reporter_snapshot).to receive(:stalling_threads) { { } }
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".unsafe_shutdown = true" do
|
38
|
+
let(:abort_threshold) { subject.abort_threshold }
|
39
|
+
let(:report_every) { subject.report_every }
|
40
|
+
|
41
|
+
before :each do
|
42
|
+
subject.class.unsafe_shutdown = true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should force the shutdown" do
|
46
|
+
expect(subject).to receive(:force_exit).once
|
47
|
+
subject.start
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should do exactly \"abort_threshold\" stall checks" do
|
51
|
+
allow(subject).to receive(:force_exit)
|
52
|
+
expect(subject).to receive(:shutdown_stalled?).exactly(abort_threshold).times.and_call_original
|
53
|
+
subject.start
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should do exactly \"abort_threshold\"*\"report_every\" stall checks" do
|
57
|
+
allow(subject).to receive(:force_exit)
|
58
|
+
expect(subject).to receive(:pipeline_report_snapshot).exactly(abort_threshold*report_every).times.and_call_original
|
59
|
+
subject.start
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe ".unsafe_shutdown = false" do
|
64
|
+
|
65
|
+
before :each do
|
66
|
+
subject.class.unsafe_shutdown = false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "shouldn't force the shutdown" do
|
70
|
+
expect(subject).to_not receive(:force_exit)
|
71
|
+
thread = Thread.new(subject) {|subject| subject.start }
|
72
|
+
sleep 0.1 until report_count > check_threshold
|
73
|
+
thread.kill
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "when pipeline is not stalled" do
|
79
|
+
let(:decreasing_count) { (1..5000).to_a.reverse }
|
80
|
+
before :each do
|
81
|
+
allow(reporter_snapshot).to receive(:inflight_count).and_return(*decreasing_count)
|
82
|
+
allow(reporter_snapshot).to receive(:stalling_threads) { { } }
|
83
|
+
end
|
84
|
+
|
85
|
+
describe ".unsafe_shutdown = true" do
|
86
|
+
|
87
|
+
before :each do
|
88
|
+
subject.class.unsafe_shutdown = true
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should force the shutdown" do
|
92
|
+
expect(subject).to_not receive(:force_exit)
|
93
|
+
thread = Thread.new(subject) {|subject| subject.start }
|
94
|
+
sleep 0.1 until report_count > check_threshold
|
95
|
+
thread.kill
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe ".unsafe_shutdown = false" do
|
100
|
+
|
101
|
+
before :each do
|
102
|
+
subject.class.unsafe_shutdown = false
|
103
|
+
end
|
104
|
+
|
105
|
+
it "shouldn't force the shutdown" do
|
106
|
+
expect(subject).to_not receive(:force_exit)
|
107
|
+
thread = Thread.new(subject) {|subject| subject.start }
|
108
|
+
sleep 0.1 until report_count > check_threshold
|
109
|
+
thread.kill
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
require "logstash/util/buftok"
|
4
|
+
|
5
|
+
describe FileWatch::BufferedTokenizer do
|
6
|
+
|
7
|
+
subject { FileWatch::BufferedTokenizer.new }
|
8
|
+
|
9
|
+
it "should tokenize a single token" do
|
10
|
+
expect(subject.extract("foo\n")).to eq(["foo"])
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should merge multiple token" do
|
14
|
+
expect(subject.extract("foo")).to eq([])
|
15
|
+
expect(subject.extract("bar\n")).to eq(["foobar"])
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should tokenize multiple token" do
|
19
|
+
expect(subject.extract("foo\nbar\n")).to eq(["foo", "bar"])
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should ignore empty payload" do
|
23
|
+
expect(subject.extract("")).to eq([])
|
24
|
+
expect(subject.extract("foo\nbar")).to eq(["foo"])
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should tokenize empty payload with newline" do
|
28
|
+
expect(subject.extract("\n")).to eq([""])
|
29
|
+
expect(subject.extract("\n\n\n")).to eq(["", "", ""])
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
require "logstash/util/charset"
|
4
|
+
|
5
|
+
describe LogStash::Util::Charset do
|
6
|
+
let(:logger) { double("logger") }
|
7
|
+
|
8
|
+
context "with valid UTF-8 source encoding" do
|
9
|
+
subject {LogStash::Util::Charset.new("UTF-8")}
|
10
|
+
|
11
|
+
it "should return untouched data" do
|
12
|
+
["foobar", "κόσμε"].each do |data|
|
13
|
+
expect(data.encoding.name).to eq("UTF-8")
|
14
|
+
expect(subject.convert(data)).to eq(data)
|
15
|
+
expect(subject.convert(data).encoding.name).to eq("UTF-8")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "with invalid UTF-8 source encoding" do
|
21
|
+
subject do
|
22
|
+
LogStash::Util::Charset.new("UTF-8").tap do |charset|
|
23
|
+
charset.logger = logger
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should escape invalid sequences" do
|
28
|
+
["foo \xED\xB9\x81\xC3", "bar \xAD"].each do |data|
|
29
|
+
expect(data.encoding.name).to eq("UTF-8")
|
30
|
+
expect(data.valid_encoding?).to eq(false)
|
31
|
+
expect(logger).to receive(:warn).exactly(2).times
|
32
|
+
#logger.should_receive(:warn).twice
|
33
|
+
expect(subject.convert(data)).to eq(data.inspect[1..-2])
|
34
|
+
expect(subject.convert(data).encoding.name).to eq("UTF-8")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with valid non UTF-8 source encoding" do
|
41
|
+
subject {LogStash::Util::Charset.new("ISO-8859-1")}
|
42
|
+
|
43
|
+
it "should encode to UTF-8" do
|
44
|
+
samples = [
|
45
|
+
["foobar", "foobar"],
|
46
|
+
["\xE0 Montr\xE9al", "à Montréal"],
|
47
|
+
]
|
48
|
+
samples.map{|(a, b)| [a.force_encoding("ISO-8859-1"), b]}.each do |(a, b)|
|
49
|
+
expect(a.encoding.name).to eq("ISO-8859-1")
|
50
|
+
expect(b.encoding.name).to eq("UTF-8")
|
51
|
+
expect(a.valid_encoding?).to eq(true)
|
52
|
+
expect(subject.convert(a).encoding.name).to eq("UTF-8")
|
53
|
+
expect(subject.convert(a)).to eq(b)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with invalid non UTF-8 source encoding" do
|
59
|
+
subject {LogStash::Util::Charset.new("ASCII-8BIT")}
|
60
|
+
|
61
|
+
it "should encode to UTF-8 and replace invalid chars" do
|
62
|
+
samples = [
|
63
|
+
["\xE0 Montr\xE9al", "� Montr�al"],
|
64
|
+
["\xCE\xBA\xCF\x8C\xCF\x83\xCE\xBC\xCE\xB5", "����������"],
|
65
|
+
]
|
66
|
+
samples.map{|(a, b)| [a.force_encoding("ASCII-8BIT"), b]}.each do |(a, b)|
|
67
|
+
expect(a.encoding.name).to eq("ASCII-8BIT")
|
68
|
+
expect(b.encoding.name).to eq("UTF-8")
|
69
|
+
expect(subject.convert(a).encoding.name).to eq("UTF-8")
|
70
|
+
expect(subject.convert(a)).to eq(b)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|