require_relative 'helper'
require 'fluent/config'
require 'fluent/config/parser'
require 'fluent/supervisor'
require 'fluent/load'
require 'fileutils'
class ConfigTest < Test::Unit::TestCase
include Fluent
TMP_DIR = File.dirname(__FILE__) + "/tmp/config#{ENV['TEST_ENV_NUMBER']}"
def read_config(path, use_yaml: false)
path = File.expand_path(path)
if use_yaml
context = Kernel.binding
s = Fluent::Config::YamlParser::Loader.new(context).load(Pathname.new(path))
Fluent::Config::YamlParser::Parser.new(s).build.to_element
else
File.open(path) { |io|
Fluent::Config::Parser.parse(io, File.basename(path), File.dirname(path))
}
end
end
def prepare_config
write_config "#{TMP_DIR}/config_test_1.conf", %[
k1 root_config
include dir/config_test_2.conf #
include #{TMP_DIR}/config_test_4.conf
include file://#{TMP_DIR}/config_test_5.conf
]
write_config "#{TMP_DIR}/dir/config_test_2.conf", %[
k2 relative_path_include
include ../config_test_3.conf
]
write_config "#{TMP_DIR}/config_test_3.conf", %[
k3 relative_include_in_included_file
]
write_config "#{TMP_DIR}/config_test_4.conf", %[
k4 absolute_path_include
]
write_config "#{TMP_DIR}/config_test_5.conf", %[
k5 uri_include
]
write_config "#{TMP_DIR}/config.d/config_test_6.conf", %[
k6 wildcard_include_1
include normal_parameter
]
write_config "#{TMP_DIR}/config.d/config_test_7.conf", %[
k7 wildcard_include_2
]
write_config "#{TMP_DIR}/config.d/config_test_8.conf", %[
]
write_config "#{TMP_DIR}/dir/config_test_9.conf", %[
k9 embedded
nested nested_value
include hoge
]
write_config "#{TMP_DIR}/config.d/00_config_test_8.conf", %[
k8 wildcard_include_3
include normal_parameter
]
end
def test_include
prepare_config
c = read_config("#{TMP_DIR}/config_test_1.conf")
assert_equal 'root_config', c['k1']
assert_equal 'relative_path_include', c['k2']
assert_equal 'relative_include_in_included_file', c['k3']
assert_equal 'absolute_path_include', c['k4']
assert_equal 'uri_include', c['k5']
assert_equal 'wildcard_include_1', c['k6']
assert_equal 'wildcard_include_2', c['k7']
assert_equal 'wildcard_include_3', c['k8']
assert_equal [
'k1',
'k2',
'k3',
'k4',
'k5',
'k8', # Because of the file name this comes first.
'k6',
'k7',
], c.keys
elem1 = c.elements.find { |e| e.name == 'elem1' }
assert_not_nil elem1
assert_equal 'name', elem1.arg
assert_equal 'normal_parameter', elem1['include']
elem2 = c.elements.find { |e| e.name == 'elem2' }
assert_not_nil elem2
assert_equal 'name', elem2.arg
assert_equal 'embedded', elem2['k9']
assert !elem2.has_key?('include')
elem3 = elem2.elements.find { |e| e.name == 'elem3' }
assert_not_nil elem3
assert_equal 'nested_value', elem3['nested']
assert_equal 'hoge', elem3['include']
end
def test_check_not_fetchd
write_config "#{TMP_DIR}/config_test_not_fetched.conf", %[
type rewrite
add_prefix filtered
key path
pattern ^[A-Z]+
replace
]
root_conf = read_config("#{TMP_DIR}/config_test_not_fetched.conf")
match_conf = root_conf.elements.first
rule_conf = match_conf.elements.first
not_fetched = []; root_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[type add_prefix key pattern replace], not_fetched
not_fetched = []; match_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[type add_prefix key pattern replace], not_fetched
not_fetched = []; rule_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[key pattern replace], not_fetched
# accessing should delete
match_conf['type']
rule_conf['key']
not_fetched = []; root_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[add_prefix pattern replace], not_fetched
not_fetched = []; match_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[add_prefix pattern replace], not_fetched
not_fetched = []; rule_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[pattern replace], not_fetched
# repeatedly accessing should not grow memory usage
before_size = match_conf.unused.size
10.times { match_conf['type'] }
assert_equal before_size, match_conf.unused.size
end
sub_test_case "yaml config" do
def test_included
write_config "#{TMP_DIR}/config_test_not_fetched.yaml", <<-EOS
config:
- source:
$type: dummy
tag: tag.dummy
- source:
$type: tcp
tag: tag.tcp
parse:
$arg:
- why.parse.section.doesnot.have.arg
- huh
$type: none
- match:
$tag: tag.*
$type: stdout
buffer:
$type: memory
flush_interval: 1s
- !include fluent-included.yaml
EOS
write_config "#{TMP_DIR}/fluent-included.yaml", <<-EOS
- label:
$name: '@FLUENT_LOG'
config:
- match:
$type: "null"
$tag: "**"
buffer:
$type: memory
flush_mode: interval
flush_interval: 1s
EOS
root_conf = read_config("#{TMP_DIR}/config_test_not_fetched.yaml", use_yaml: true)
dummy_source_conf = root_conf.elements.first
tcp_source_conf = root_conf.elements[1]
parse_tcp_conf = tcp_source_conf.elements.first
match_conf = root_conf.elements[2]
label_conf = root_conf.elements[3]
fluent_log_conf = label_conf.elements.first
fluent_log_buffer_conf = fluent_log_conf.elements.first
assert_equal(
[
'dummy',
'tag.dummy',
'tcp',
'tag.tcp',
'none',
'why.parse.section.doesnot.have.arg,huh',
'stdout',
'tag.*',
'null',
'**',
'@FLUENT_LOG',
'memory',
'interval',
'1s',
],
[
dummy_source_conf['@type'],
dummy_source_conf['tag'],
tcp_source_conf['@type'],
tcp_source_conf['tag'],
parse_tcp_conf['@type'],
parse_tcp_conf.arg,
match_conf['@type'],
match_conf.arg,
fluent_log_conf['@type'],
fluent_log_conf.arg,
label_conf.arg,
fluent_log_buffer_conf['@type'],
fluent_log_buffer_conf['flush_mode'],
fluent_log_buffer_conf['flush_interval'],
])
end
def test_included_glob
write_config "#{TMP_DIR}/config.yaml", <<-EOS
config:
- !include "include/*.yaml"
EOS
write_config "#{TMP_DIR}/include/02_source2.yaml", <<-EOS
- source:
$type: dummy
tag: tag.dummy
EOS
write_config "#{TMP_DIR}/include/01_source1.yaml", <<-EOS
- source:
$type: tcp
tag: tag.tcp
parse:
$arg:
- why.parse.section.doesnot.have.arg
- huh
$type: none
EOS
write_config "#{TMP_DIR}/include/03_match1.yaml", <<-EOS
- match:
$tag: tag.*
$type: stdout
buffer:
$type: memory
flush_interval: 1s
EOS
root_conf = read_config("#{TMP_DIR}/config.yaml", use_yaml: true)
tcp_source_conf = root_conf.elements.first
dummy_source_conf = root_conf.elements[1]
parse_tcp_conf = tcp_source_conf.elements.first
match_conf = root_conf.elements[2]
assert_equal(
[
'tcp',
'tag.tcp',
'none',
'why.parse.section.doesnot.have.arg,huh',
'dummy',
'tag.dummy',
'stdout',
'tag.*',
],
[
tcp_source_conf['@type'],
tcp_source_conf['tag'],
parse_tcp_conf['@type'],
parse_tcp_conf.arg,
dummy_source_conf['@type'],
dummy_source_conf['tag'],
match_conf['@type'],
match_conf.arg,
])
end
def test_check_not_fetchd
write_config "#{TMP_DIR}/config_test_not_fetched.yaml", <<-EOS
config:
- match:
$arg: dummy
$type: rewrite
add_prefix: filtered
rule:
key: path
pattern: "^[A-Z]+"
replace: true
EOS
root_conf = read_config("#{TMP_DIR}/config_test_not_fetched.yaml", use_yaml: true)
match_conf = root_conf.elements.first
rule_conf = match_conf.elements.first
not_fetched = []; root_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[@type $arg add_prefix key pattern replace], not_fetched
not_fetched = []; match_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[@type $arg add_prefix key pattern replace], not_fetched
not_fetched = []; rule_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[key pattern replace], not_fetched
# accessing should delete
match_conf['type']
rule_conf['key']
not_fetched = []; root_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[@type $arg add_prefix pattern replace], not_fetched
not_fetched = []; match_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[@type $arg add_prefix pattern replace], not_fetched
not_fetched = []; rule_conf.check_not_fetched {|key, e| not_fetched << key }
assert_equal %w[pattern replace], not_fetched
# repeatedly accessing should not grow memory usage
before_size = match_conf.unused.size
10.times { match_conf['type'] }
assert_equal before_size, match_conf.unused.size
end
end
def write_config(path, data, encoding: 'utf-8')
FileUtils.mkdir_p(File.dirname(path))
File.open(path, "w:#{encoding}:utf-8") {|f| f.write data }
end
def test_inline
prepare_config
opts = {
:config_path => "#{TMP_DIR}/config_test_1.conf",
:inline_config => "",
:use_v1_config => false
}
assert_nothing_raised do
Fluent::Supervisor.new(opts)
end
create_warn_dummy_logger
end
def create_warn_dummy_logger
dl_opts = {}
dl_opts[:log_level] = ServerEngine::DaemonLogger::WARN
logdev = Fluent::Test::DummyLogDevice.new
logger = ServerEngine::DaemonLogger.new(logdev, dl_opts)
$log = Fluent::Log.new(logger)
end
sub_test_case '.build' do
test 'read config' do
write_config("#{TMP_DIR}/build/config_build.conf", 'key value')
c = Fluent::Config.build(config_path: "#{TMP_DIR}/build/config_build.conf")
assert_equal('value', c['key'])
end
test 'read config with encoding' do
write_config("#{TMP_DIR}/build/config_build2.conf", "#てすと\nkey value", encoding: 'shift_jis')
c = Fluent::Config.build(config_path: "#{TMP_DIR}/build/config_build2.conf", encoding: 'shift_jis')
assert_equal('value', c['key'])
end
test 'read config with additional_config' do
write_config("#{TMP_DIR}/build/config_build2.conf", "key value")
c = Fluent::Config.build(config_path: "#{TMP_DIR}/build/config_build2.conf", additional_config: 'key2 value2')
assert_equal('value', c['key'])
assert_equal('value2', c['key2'])
end
end
end