Testing Plugin Configuration Formatter Implementation in Fluentd
This test suite validates the functionality of Fluentd’s plugin configuration formatter, ensuring proper handling of various plugin types and output formats. It tests the formatting capabilities for input, output, filter, parser, and formatter plugins across different output styles including JSON, text, and markdown.
Test Coverage Overview
Implementation Analysis
Technical Details
Best Practices Demonstrated
fluent/fluentd
test/command/test_plugin_config_formatter.rb
require_relative '../helper'
require 'pathname'
require 'fluent/command/plugin_config_formatter'
require 'fluent/plugin/input'
require 'fluent/plugin/output'
require 'fluent/plugin/filter'
require 'fluent/plugin/parser'
require 'fluent/plugin/formatter'
class TestFluentPluginConfigFormatter < Test::Unit::TestCase
class FakeInput < ::Fluent::Plugin::Input
::Fluent::Plugin.register_input("fake", self)
desc "path to something"
config_param :path, :string
end
class FakeOutput < ::Fluent::Plugin::Output
::Fluent::Plugin.register_output("fake", self)
desc "path to something"
config_param :path, :string
def process(tag, es)
end
end
class FakeFilter < ::Fluent::Plugin::Filter
::Fluent::Plugin.register_filter("fake", self)
desc "path to something"
config_param :path, :string
def filter(tag, time, record)
end
end
class FakeParser < ::Fluent::Plugin::Parser
::Fluent::Plugin.register_parser("fake", self)
desc "path to something"
config_param :path, :string
def parse(text)
end
end
class FakeFormatter < ::Fluent::Plugin::Formatter
::Fluent::Plugin.register_formatter("fake", self)
desc "path to something"
config_param :path, :string
def format(tag, time, record)
end
end
class FakeStorage < ::Fluent::Plugin::Storage
::Fluent::Plugin.register_storage('fake', self)
def get(key)
end
def fetch(key, defval)
end
def put(key, value)
end
def delete(key)
end
def update(key, &block)
end
end
class FakeServiceDiscovery < ::Fluent::Plugin::ServiceDiscovery
::Fluent::Plugin.register_sd('fake', self)
desc "hostname"
config_param :hostname, :string
end
class SimpleInput < ::Fluent::Plugin::Input
::Fluent::Plugin.register_input("simple", self)
helpers :inject, :compat_parameters
desc "path to something"
config_param :path, :string
end
class ComplexOutput < ::Fluent::Plugin::Output
::Fluent::Plugin.register_output("complex", self)
helpers :inject, :compat_parameters
config_section :authentication, required: true, multi: false do
desc "username"
config_param :username, :string
desc "password"
config_param :password, :string, secret: true
end
config_section :parent do
config_section :child do
desc "names"
config_param :names, :array
desc "difficulty"
config_param :difficulty, :enum, list: [:easy, :normal, :hard], default: :normal
end
end
def process(tag, es)
end
end
class SimpleServiceDiscovery < ::Fluent::Plugin::ServiceDiscovery
::Fluent::Plugin.register_sd('simple', self)
desc "servers"
config_param :servers, :array
end
sub_test_case "json" do
data(input: [FakeInput, "input"],
output: [FakeOutput, "output"],
filter: [FakeFilter, "filter"],
parser: [FakeParser, "parser"],
formatter: [FakeFormatter, "formatter"])
test "dumped config should be valid JSON" do |(klass, type)|
dumped_config = capture_stdout do
FluentPluginConfigFormatter.new(["--format=json", type, "fake"]).call
end
expected = {
path: {
desc: "path to something",
type: "string",
required: true
}
}
assert_equal(expected, JSON.parse(dumped_config, symbolize_names: true)[klass.name.to_sym])
end
end
sub_test_case "text" do
test "input simple" do
dumped_config = capture_stdout do
FluentPluginConfigFormatter.new(["--format=txt", "input", "simple"]).call
end
expected = <<TEXT
helpers: inject,compat_parameters
@log_level: string: (nil)
path: string: (nil)
TEXT
assert_equal(expected, dumped_config)
end
test "output complex" do
dumped_config = capture_stdout do
FluentPluginConfigFormatter.new(["--format=txt", "output", "complex"]).call
end
expected = <<TEXT
helpers: inject,compat_parameters
@log_level: string: (nil)
time_as_integer: bool: (false)
slow_flush_log_threshold: float: (20.0)
<buffer>: optional, single
chunk_keys: array: ([])
@type: string: ("memory")
timekey: time: (nil)
timekey_wait: time: (600)
timekey_use_utc: bool: (false)
timekey_zone: string: ("#{Time.now.strftime('%z')}")
flush_at_shutdown: bool: (nil)
flush_mode: enum: (:default)
flush_interval: time: (60)
flush_thread_count: integer: (1)
flush_thread_interval: float: (1.0)
flush_thread_burst_interval: float: (1.0)
delayed_commit_timeout: time: (60)
overflow_action: enum: (:throw_exception)
retry_forever: bool: (false)
retry_timeout: time: (259200)
retry_max_times: integer: (nil)
retry_secondary_threshold: float: (0.8)
retry_type: enum: (:exponential_backoff)
retry_wait: time: (1)
retry_exponential_backoff_base: float: (2)
retry_max_interval: time: (nil)
retry_randomize: bool: (true)
<secondary>: optional, single
@type: string: (nil)
<buffer>: optional, single
<secondary>: optional, single
<authentication>: required, single
username: string: (nil)
password: string: (nil)
<parent>: optional, multiple
<child>: optional, multiple
names: array: (nil)
difficulty: enum: (:normal)
TEXT
assert_equal(expected, dumped_config)
end
end
sub_test_case "markdown" do
test "input simple" do
dumped_config = capture_stdout do
FluentPluginConfigFormatter.new(["--format=markdown", "input", "simple"]).call
end
expected = <<TEXT
## Plugin helpers
* [inject](https://docs.fluentd.org/v/1.0/plugin-helper-overview/api-plugin-helper-inject)
* [compat_parameters](https://docs.fluentd.org/v/1.0/plugin-helper-overview/api-plugin-helper-compat_parameters)
* See also: [Input Plugin Overview](https://docs.fluentd.org/v/1.0/input#overview)
## TestFluentPluginConfigFormatter::SimpleInput
### path (string) (required)
path to something
TEXT
assert_equal(expected, dumped_config)
end
test "input simple (table)" do
dumped_config = capture_stdout do
FluentPluginConfigFormatter.new(["--format=markdown", "--table", "input", "simple"]).call
end
expected = <<TEXT
## Plugin helpers
* [inject](https://docs.fluentd.org/v/1.0/plugin-helper-overview/api-plugin-helper-inject)
* [compat_parameters](https://docs.fluentd.org/v/1.0/plugin-helper-overview/api-plugin-helper-compat_parameters)
* See also: [Input Plugin Overview](https://docs.fluentd.org/v/1.0/input#overview)
## TestFluentPluginConfigFormatter::SimpleInput
### Configuration
|parameter|type|description|default|
|---|---|---|---|
|path|string (required)|path to something||
TEXT
assert_equal(expected, dumped_config)
end
data("abbrev" => "sd",
"normal" => "service_discovery")
test "service_discovery simple" do |data|
plugin_type = data
dumped_config = capture_stdout do
FluentPluginConfigFormatter.new(["--format=markdown", plugin_type, "simple"]).call
end
expected = <<TEXT
* See also: [ServiceDiscovery Plugin Overview](https://docs.fluentd.org/v/1.0/servicediscovery#overview)
## TestFluentPluginConfigFormatter::SimpleServiceDiscovery
### servers (array) (required)
servers
TEXT
assert_equal(expected, dumped_config)
end
test "output complex" do
dumped_config = capture_stdout do
FluentPluginConfigFormatter.new(["--format=markdown", "output", "complex"]).call
end
expected = <<TEXT
## Plugin helpers
* [inject](https://docs.fluentd.org/v/1.0/plugin-helper-overview/api-plugin-helper-inject)
* [compat_parameters](https://docs.fluentd.org/v/1.0/plugin-helper-overview/api-plugin-helper-compat_parameters)
* See also: [Output Plugin Overview](https://docs.fluentd.org/v/1.0/output#overview)
## TestFluentPluginConfigFormatter::ComplexOutput
### \\<authentication\\> section (required) (single)
#### username (string) (required)
username
#### password (string) (required)
password
### \\<parent\\> section (optional) (multiple)
#### \\<child\\> section (optional) (multiple)
##### names (array) (required)
names
##### difficulty (enum) (optional)
difficulty
Available values: easy, normal, hard
Default value: `normal`.
TEXT
assert_equal(expected, dumped_config)
end
test "output complex (table)" do
dumped_config = capture_stdout do
FluentPluginConfigFormatter.new(["--format=markdown", "--table", "output", "complex"]).call
end
expected = <<TEXT
## Plugin helpers
* [inject](https://docs.fluentd.org/v/1.0/plugin-helper-overview/api-plugin-helper-inject)
* [compat_parameters](https://docs.fluentd.org/v/1.0/plugin-helper-overview/api-plugin-helper-compat_parameters)
* See also: [Output Plugin Overview](https://docs.fluentd.org/v/1.0/output#overview)
## TestFluentPluginConfigFormatter::ComplexOutput
### \\<authentication\\> section (required) (single)
### Configuration
|parameter|type|description|default|
|---|---|---|---|
|username|string (required)|username||
|password|string (required)|password||
### \\<parent\\> section (optional) (multiple)
#### \\<child\\> section (optional) (multiple)
### Configuration
|parameter|type|description|default|
|---|---|---|---|
|names|array (required)|names||
|difficulty|enum (optional)|difficulty (`easy`, `normal`, `hard`)|`normal`|
TEXT
assert_equal(expected, dumped_config)
end
end
sub_test_case "arguments" do
data do
hash = {}
["input", "output", "filter", "parser", "formatter", "storage", "service_discovery"].each do |type|
["txt", "json", "markdown"].each do |format|
argv = ["--format=#{format}"]
[
["--verbose", "--compact"],
["--verbose"],
["--compact"]
].each do |options|
hash["[#{type}] " + (argv + options).join(" ")] = argv + options + [type, "fake"]
end
end
end
hash
end
test "dump txt" do |argv|
capture_stdout do
assert_nothing_raised do
FluentPluginConfigFormatter.new(argv).call
end
end
end
end
end