diff --git a/test/models/fluentd/agent_test.rb b/test/models/fluentd/agent_test.rb
new file mode 100644
index 0000000..6804883
--- /dev/null
+++ b/test/models/fluentd/agent_test.rb
@@ -0,0 +1,279 @@
+require "test_helper"
+
+class Fluentd
+ class AgentTest < ActiveSupport::TestCase
+ module CommonBehavior
+ extend ActiveSupport::Concern
+ included do
+ sub_test_case "#extra_options" do
+ test "blank" do
+ @agent = @klass.new({})
+ assert_equal({}, @agent.extra_options)
+ extra_options = {
+ config_file: @agent.config_file,
+ log_file: @agent.log_file,
+ pid_file: @agent.pid_file
+ }
+ assert_equal(extra_options, @klass.default_options)
+ end
+
+ test "given" do
+ options = {
+ config_file: "pid",
+ log_file: "log",
+ pid_file: "config"
+ }
+ @agent = @klass.new(options)
+ extra_options = {
+ config_file: @agent.config_file,
+ log_file: @agent.log_file,
+ pid_file: @agent.pid_file
+ }
+ assert_equal(extra_options, options)
+ end
+ end
+
+ sub_test_case "#errors_since" do
+ setup do
+ @logged_time = Time.parse('2014-05-27')
+ @now = Time.parse("2014-05-29")
+ Timecop.freeze(@now)
+ end
+
+ teardown do
+ Timecop.return
+ end
+
+ test "have no errors" do
+ stub(@agent).log_file { fixture_path("error0.log") }
+ assert do
+ @agent.log.errors_since(100.days.ago).empty?
+ end
+ end
+
+ sub_test_case "have errors" do
+ test "unreachable since 0 days ago" do
+ stub(@agent).log_file { fixture_path("error2.log") }
+ assert_equal([], @agent.log.errors_since(0.days.ago))
+ end
+
+ test "reachable since 100 days ago" do
+ stub(@agent).log_file { fixture_path("error2.log") }
+ logs = @agent.log.errors_since(100.days.ago)
+ assert do
+ logs[0][:subject].include?("Address already in use - bind(2)")
+ end
+ one = Time.parse(logs[0][:subject])
+ two = Time.parse(logs[1][:subject])
+ assert do
+ one >= two
+ end
+ end
+ end
+ end
+
+ sub_test_case "#recent_errors" do
+ test "have 0 error log" do
+ stub(@agent).log_file { fixture_path("error0.log") }
+ assert do
+ @agent.log.recent_errors(2).empty?
+ end
+ end
+
+ sub_test_case "have 2 error log" do
+ setup do
+ stub(@agent).log_file { fixture_path("error2.log") }
+ end
+
+ data("limit 1" => 1,
+ "limit 2" => 2)
+ test "limit" do |limit|
+ assert do
+ limit == @agent.log.recent_errors(limit).size
+ end
+ end
+
+ test "contains stack trace" do
+ logs = @agent.log.recent_errors(2)
+ assert do
+ logs[0][:subject].include?("Address already in use - bind(2)")
+ end
+ end
+
+ test "newer(bottom) is first" do
+ logs = @agent.log.recent_errors(2)
+ one = Time.parse(logs[0][:subject])
+ two = Time.parse(logs[1][:subject])
+ assert do
+ one >= two
+ end
+ end
+ end
+
+ sub_test_case "have 3 errors log including sequential 2 error log" do
+ setup do
+ stub(@agent).log_file { fixture_path("error3.log") }
+ end
+
+ test "count 3 errors" do
+ logs = @agent.log.recent_errors(3)
+ assert_equal(logs[0][:subject].slice(/::EADDRINUSE: (\d) Address already in use/, 1), "3")
+ assert_equal(logs[0][:notes].size, 1)
+ assert_equal(logs[1][:subject].slice(/::EADDRINUSE: (\d) Address already in use/, 1), "2")
+ assert_equal(logs[1][:notes].size, 2)
+ assert_equal(logs[2][:subject].slice(/::EADDRINUSE: (\d) Address already in use/, 1), "1")
+ assert_equal(logs[2][:notes].size, 0)
+ end
+ end
+ end
+
+ sub_test_case "#dryrun" do
+ setup do
+ pend("/usr/sbin/td-agent does not exist") unless File.exist?("/usr/sbin/td-agent")
+ @root = FluentdUI.data_dir + "/tmp/agent-test/"
+ @dummy_log_file = @root + "dummy.log"
+ @dummy_pid_file = @root + "dummy.pid"
+
+ FileUtils.mkdir_p(@root)
+ stub(@agent).log_file { @dummy_log_file }
+ stub(@agent).pid_file { @dummy_pid_file }
+ end
+
+ sub_test_case "valid/invalid" do
+ setup do
+ @config_path = Rails.root.join("tmp", "fluent-test.conf").to_s
+ end
+
+ teardown do
+ File.unlink(@config_path) if @config_path && File.exist?(@config_path)
+ end
+
+ test "valid config" do
+ config = <<-CONF.strip_heredoc
+
+ @type forward
+
+ CONF
+ File.write(@config_path, config)
+ assert_nothing_raised do
+ @agent.dryrun!(@config_path)
+ end
+ assert_true(@agent.dryrun(@config_path))
+ end
+
+ test "invalid config" do
+ config = <<-CONF.strip_heredoc
+
+ @type forward
+ CONF
+ File.write(@config_path, config)
+ assert_raise(Fluentd::Agent::ConfigError) do
+ @agent.dryrun!(@config_path)
+ end
+ assert_false(@agent.dryrun(@config_path))
+ end
+ end
+ end
+ end
+ end
+
+ sub_test_case "FluentdGem" do
+ setup do
+ options = {
+ config_file: Rails.root.join("tmp", "fluentd-test", "fluentd.conf").to_s
+ }
+ @klass = Fluentd::Agent::FluentdGem
+ @agent = @klass.new(options)
+ end
+
+ include CommonBehavior
+
+ test "#options_to_argv" do
+ expected_argv = " -c #{@agent.config_file} -d #{@agent.pid_file} -o #{@agent.log_file}"
+ assert_equal(expected_argv, @agent.__send__(:options_to_argv))
+ end
+
+ sub_test_case "#start" do
+ setup do
+ # ensure valid config
+ @agent.config_write("")
+ end
+
+ teardown do
+ FileUtils.rm_rf(@agent.running_config_backup_dir)
+ end
+
+ test "running" do
+ stub(@agent).running? { true }
+ assert_true(@agent.start)
+ end
+
+ test "succeeded to actual_start" do
+ stub(@agent).running? { false }
+ stub(@agent).actual_start { true }
+ assert_true(@agent.start)
+ backup_file = @agent.running_config_backup_file
+ assert do
+ File.exist?(backup_file)
+ end
+ assert_equal(File.read(@agent.config_file), File.read(backup_file))
+ end
+
+ test "failed to actual_start" do
+ stub(@agent).running? { false }
+ stub(@agent).actual_start { false }
+ assert_nil(@agent.start)
+ end
+ end
+
+ sub_test_case "#stop" do
+ data("succeeded to actual_stop" => true,
+ "failed to actual_stop" => false)
+ test "running" do |stop_result|
+ stub(@agent).running? { true }
+ stub(@agent).actual_stop { stop_result }
+ assert_equal(stop_result, @agent.stop)
+ end
+
+ test "not running" do
+ stub(@agent).running? { false }
+ assert do
+ @agent.stop
+ end
+ end
+ end
+ end
+
+ sub_test_case "TdAgent" do
+ setup do
+ options = {
+ config_file: Rails.root.join("tmp", "fluentd-test", "fluentd.conf").to_s
+ }
+ @klass = Fluentd::Agent::TdAgent
+ @agent = @klass.new(options)
+ end
+
+ include CommonBehavior
+
+ sub_test_case "#backup_running_config" do
+ setup do
+ stub(@agent).detached_command { true }
+ stub(@agent).pid_from_launchctl { true }
+ @agent.config_write("") # ensure valid config
+ end
+
+ teardown do
+ FileUtils.rm_rf(@agent.running_config_backup_dir)
+ end
+
+
+ test "backup running conf" do
+ @agent.start
+ backup_file = @agent.running_config_backup_file
+ assert_true(File.exist?(backup_file))
+ assert_equal(File.read(@agent.config_file), File.read(backup_file))
+ end
+ end
+ end
+ end
+end