fluentd 1.14.4-x86-mingw32 → 1.15.0-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/config.yml +2 -2
- data/.github/workflows/linux-test.yaml +1 -1
- data/.github/workflows/macos-test.yaml +5 -1
- data/.github/workflows/windows-test.yaml +9 -6
- data/CHANGELOG.md +115 -19
- data/CONTRIBUTING.md +1 -1
- data/MAINTAINERS.md +2 -2
- data/README.md +2 -23
- data/Rakefile +1 -1
- data/fluentd.gemspec +3 -1
- data/lib/fluent/command/ctl.rb +4 -1
- data/lib/fluent/command/fluentd.rb +14 -0
- data/lib/fluent/config/error.rb +12 -0
- data/lib/fluent/config/literal_parser.rb +2 -2
- data/lib/fluent/config/yaml_parser/fluent_value.rb +47 -0
- data/lib/fluent/config/yaml_parser/loader.rb +91 -0
- data/lib/fluent/config/yaml_parser/parser.rb +166 -0
- data/lib/fluent/config/yaml_parser/section_builder.rb +107 -0
- data/lib/fluent/config/yaml_parser.rb +56 -0
- data/lib/fluent/config.rb +14 -1
- data/lib/fluent/event_router.rb +19 -1
- data/lib/fluent/plugin/bare_output.rb +1 -1
- data/lib/fluent/plugin/base.rb +1 -1
- data/lib/fluent/plugin/file_wrapper.rb +52 -107
- data/lib/fluent/plugin/in_forward.rb +1 -1
- data/lib/fluent/plugin/in_http.rb +11 -1
- data/lib/fluent/plugin/in_tail/group_watch.rb +204 -0
- data/lib/fluent/plugin/in_tail/position_file.rb +1 -15
- data/lib/fluent/plugin/in_tail.rb +66 -47
- data/lib/fluent/plugin/out_forward/socket_cache.rb +2 -0
- data/lib/fluent/plugin/output.rb +43 -33
- data/lib/fluent/plugin/parser.rb +3 -4
- data/lib/fluent/plugin/parser_syslog.rb +1 -1
- data/lib/fluent/plugin_helper/retry_state.rb +14 -4
- data/lib/fluent/plugin_helper/server.rb +23 -4
- data/lib/fluent/plugin_helper/service_discovery.rb +2 -2
- data/lib/fluent/plugin_helper/socket.rb +13 -2
- data/lib/fluent/registry.rb +2 -1
- data/lib/fluent/rpc.rb +4 -3
- data/lib/fluent/supervisor.rb +114 -27
- data/lib/fluent/system_config.rb +2 -1
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +2 -0
- data/test/command/test_ctl.rb +0 -1
- data/test/command/test_fluentd.rb +33 -0
- data/test/compat/test_parser.rb +1 -1
- data/test/config/test_system_config.rb +3 -1
- data/test/config/test_types.rb +1 -1
- data/test/plugin/in_tail/test_io_handler.rb +14 -4
- data/test/plugin/in_tail/test_position_file.rb +0 -63
- data/test/plugin/out_forward/test_socket_cache.rb +26 -1
- data/test/plugin/test_file_wrapper.rb +0 -68
- data/test/plugin/test_filter_parser.rb +1 -1
- data/test/plugin/test_filter_stdout.rb +2 -2
- data/test/plugin/test_in_forward.rb +0 -2
- data/test/plugin/test_in_http.rb +23 -0
- data/test/plugin/test_in_object_space.rb +9 -3
- data/test/plugin/test_in_syslog.rb +1 -1
- data/test/plugin/test_in_tail.rb +629 -353
- data/test/plugin/test_out_forward.rb +30 -20
- data/test/plugin/test_out_stdout.rb +2 -2
- data/test/plugin/test_output_as_buffered_retries.rb +53 -6
- data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
- data/test/plugin/test_parser_syslog.rb +1 -1
- data/test/plugin_helper/test_cert_option.rb +1 -1
- data/test/plugin_helper/test_child_process.rb +16 -4
- data/test/plugin_helper/test_retry_state.rb +602 -38
- data/test/plugin_helper/test_server.rb +18 -0
- data/test/test_config.rb +135 -4
- data/test/test_event_router.rb +17 -0
- data/test/test_formatter.rb +1 -1
- data/test/test_supervisor.rb +196 -6
- metadata +39 -5
    
        data/test/plugin/test_in_tail.rb
    CHANGED
    
    | @@ -12,15 +12,21 @@ require 'securerandom' | |
| 12 12 | 
             
            class TailInputTest < Test::Unit::TestCase
         | 
| 13 13 | 
             
              include FlexMock::TestCase
         | 
| 14 14 |  | 
| 15 | 
            +
              def tmp_dir
         | 
| 16 | 
            +
                File.join(File.dirname(__FILE__), "..", "tmp", "tail#{ENV['TEST_ENV_NUMBER']}", SecureRandom.hex(10))
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 15 19 | 
             
              def setup
         | 
| 16 20 | 
             
                Fluent::Test.setup
         | 
| 17 | 
            -
                 | 
| 21 | 
            +
                @tmp_dir = tmp_dir
         | 
| 22 | 
            +
                cleanup_directory(@tmp_dir)
         | 
| 18 23 | 
             
              end
         | 
| 19 24 |  | 
| 20 25 | 
             
              def teardown
         | 
| 21 26 | 
             
                super
         | 
| 22 | 
            -
                cleanup_directory( | 
| 27 | 
            +
                cleanup_directory(@tmp_dir)
         | 
| 23 28 | 
             
                Fluent::Engine.stop
         | 
| 29 | 
            +
                Timecop.return
         | 
| 24 30 | 
             
              end
         | 
| 25 31 |  | 
| 26 32 | 
             
              def cleanup_directory(path)
         | 
| @@ -29,89 +35,48 @@ class TailInputTest < Test::Unit::TestCase | |
| 29 35 | 
             
                  return
         | 
| 30 36 | 
             
                end
         | 
| 31 37 |  | 
| 32 | 
            -
                 | 
| 33 | 
            -
                  Dir.glob("*", base: path).each do |name|
         | 
| 34 | 
            -
                    begin
         | 
| 35 | 
            -
                      cleanup_file(File.join(path, name))
         | 
| 36 | 
            -
                    rescue
         | 
| 37 | 
            -
                      # expect test driver block release already owned file handle.
         | 
| 38 | 
            -
                    end
         | 
| 39 | 
            -
                  end
         | 
| 40 | 
            -
                else
         | 
| 41 | 
            -
                  begin
         | 
| 42 | 
            -
                    FileUtils.rm_f(path, secure:true)
         | 
| 43 | 
            -
                  rescue ArgumentError
         | 
| 44 | 
            -
                    FileUtils.rm_f(path) # For Ruby 2.6 or before.
         | 
| 45 | 
            -
                  end
         | 
| 46 | 
            -
                  if File.exist?(path)
         | 
| 47 | 
            -
                    FileUtils.remove_entry_secure(path, true)
         | 
| 48 | 
            -
                  end
         | 
| 49 | 
            -
                end
         | 
| 50 | 
            -
                FileUtils.mkdir_p(path)
         | 
| 38 | 
            +
                FileUtils.remove_entry_secure(path, true)
         | 
| 51 39 | 
             
              end
         | 
| 52 40 |  | 
| 53 41 | 
             
              def cleanup_file(path)
         | 
| 54 | 
            -
                 | 
| 55 | 
            -
                  # On Windows, when the file or directory is removed and created
         | 
| 56 | 
            -
                  # frequently, there is a case that creating file or directory will
         | 
| 57 | 
            -
                  # fail. This situation is caused by pending file or directory
         | 
| 58 | 
            -
                  # deletion which is mentioned on win32 API document [1]
         | 
| 59 | 
            -
                  # As a workaround, execute rename and remove method.
         | 
| 60 | 
            -
                  #
         | 
| 61 | 
            -
                  # [1] https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#files
         | 
| 62 | 
            -
                  #
         | 
| 63 | 
            -
                  file = File.join(Dir.tmpdir, SecureRandom.hex(10))
         | 
| 64 | 
            -
                  begin
         | 
| 65 | 
            -
                    FileUtils.mv(path, file)
         | 
| 66 | 
            -
                    FileUtils.rm_rf(file, secure: true)
         | 
| 67 | 
            -
                  rescue ArgumentError
         | 
| 68 | 
            -
                    FileUtils.rm_rf(file) # For Ruby 2.6 or before.
         | 
| 69 | 
            -
                  end
         | 
| 70 | 
            -
                  if File.exist?(file)
         | 
| 71 | 
            -
                    # ensure files are closed for Windows, on which deleted files
         | 
| 72 | 
            -
                    # are still visible from filesystem
         | 
| 73 | 
            -
                    GC.start(full_mark: true, immediate_mark: true, immediate_sweep: true)
         | 
| 74 | 
            -
                    FileUtils.remove_entry_secure(file, true)
         | 
| 75 | 
            -
                  end
         | 
| 76 | 
            -
                else
         | 
| 77 | 
            -
                  begin
         | 
| 78 | 
            -
                    FileUtils.rm_f(path, secure: true)
         | 
| 79 | 
            -
                  rescue ArgumentError
         | 
| 80 | 
            -
                    FileUtils.rm_f(path) # For Ruby 2.6 or before.
         | 
| 81 | 
            -
                  end
         | 
| 82 | 
            -
                  if File.exist?(path)
         | 
| 83 | 
            -
                    FileUtils.remove_entry_secure(path, true)
         | 
| 84 | 
            -
                  end
         | 
| 85 | 
            -
                end
         | 
| 42 | 
            +
                FileUtils.remove_entry_secure(path, true)
         | 
| 86 43 | 
             
              end
         | 
| 87 44 |  | 
| 88 45 | 
             
              def create_target_info(path)
         | 
| 89 46 | 
             
                Fluent::Plugin::TailInput::TargetInfo.new(path, Fluent::FileWrapper.stat(path).ino)
         | 
| 90 47 | 
             
              end
         | 
| 91 48 |  | 
| 92 | 
            -
               | 
| 93 | 
            -
             | 
| 94 | 
            -
              CONFIG = config_element("ROOT", "", {
         | 
| 95 | 
            -
                                        "path" => "#{TMP_DIR}/tail.txt",
         | 
| 49 | 
            +
              ROOT_CONFIG = config_element("ROOT", "", {
         | 
| 96 50 | 
             
                                        "tag" => "t1",
         | 
| 97 51 | 
             
                                        "rotate_wait" => "2s",
         | 
| 98 52 | 
             
                                        "refresh_interval" => "1s"
         | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 53 | 
            +
                                           })
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              def base_config
         | 
| 56 | 
            +
                ROOT_CONFIG + config_element("", "", { "path" => "#{@tmp_dir}/tail.txt" })
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              def common_config
         | 
| 60 | 
            +
                base_config + config_element("", "", { "pos_file" => "#{@tmp_dir}/tail.pos" })
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              def common_follow_inode_config
         | 
| 64 | 
            +
                config_element("ROOT", "", {
         | 
| 65 | 
            +
                                 "path" => "#{@tmp_dir}/tail.txt*",
         | 
| 66 | 
            +
                                 "pos_file" => "#{@tmp_dir}/tail.pos",
         | 
| 67 | 
            +
                                 "tag" => "t1",
         | 
| 68 | 
            +
                                 "refresh_interval" => "1s",
         | 
| 69 | 
            +
                                 "read_from_head" => "true",
         | 
| 70 | 
            +
                                 "format" => "none",
         | 
| 71 | 
            +
                                 "rotate_wait" => "1s",
         | 
| 72 | 
            +
                                 "follow_inodes" => "true"
         | 
| 73 | 
            +
                               })
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 101 76 | 
             
              CONFIG_READ_FROM_HEAD = config_element("", "", { "read_from_head" => true })
         | 
| 102 77 | 
             
              CONFIG_DISABLE_WATCH_TIMER = config_element("", "", { "enable_watch_timer" => false })
         | 
| 103 78 | 
             
              CONFIG_DISABLE_STAT_WATCHER = config_element("", "", { "enable_stat_watcher" => false })
         | 
| 104 79 | 
             
              CONFIG_OPEN_ON_EVERY_UPDATE = config_element("", "", { "open_on_every_update" => true })
         | 
| 105 | 
            -
              COMMON_FOLLOW_INODE_CONFIG = config_element("ROOT", "", {
         | 
| 106 | 
            -
                                                            "path" => "#{TMP_DIR}/tail.txt*",
         | 
| 107 | 
            -
                                                            "pos_file" => "#{TMP_DIR}/tail.pos",
         | 
| 108 | 
            -
                                                            "tag" => "t1",
         | 
| 109 | 
            -
                                                            "refresh_interval" => "1s",
         | 
| 110 | 
            -
                                                            "read_from_head" => "true",
         | 
| 111 | 
            -
                                                            "format" => "none",
         | 
| 112 | 
            -
                                                            "rotate_wait" => "1s",
         | 
| 113 | 
            -
                                                            "follow_inodes" => "true"
         | 
| 114 | 
            -
                                                          })
         | 
| 115 80 | 
             
              SINGLE_LINE_CONFIG = config_element("", "", { "format" => "/(?<message>.*)/" })
         | 
| 116 81 | 
             
              PARSE_SINGLE_LINE_CONFIG = config_element("", "", {}, [config_element("parse", "", { "@type" => "/(?<message>.*)/" })])
         | 
| 117 82 | 
             
              MULTILINE_CONFIG = config_element(
         | 
| @@ -144,21 +109,67 @@ class TailInputTest < Test::Unit::TestCase | |
| 144 109 | 
             
                                })
         | 
| 145 110 | 
             
                ])
         | 
| 146 111 |  | 
| 112 | 
            +
              EX_ROTATE_WAIT = 0
         | 
| 113 | 
            +
              EX_FOLLOW_INODES = false
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              def ex_config
         | 
| 116 | 
            +
                config_element("", "", {
         | 
| 117 | 
            +
                                 "tag" => "tail",
         | 
| 118 | 
            +
                                 "path" => "test/plugin/*/%Y/%m/%Y%m%d-%H%M%S.log,test/plugin/data/log/**/*.log",
         | 
| 119 | 
            +
                                 "format" => "none",
         | 
| 120 | 
            +
                                 "pos_file" => "#{@tmp_dir}/tail.pos",
         | 
| 121 | 
            +
                                 "read_from_head" => true,
         | 
| 122 | 
            +
                                 "refresh_interval" => 30,
         | 
| 123 | 
            +
                                 "rotate_wait" => "#{EX_ROTATE_WAIT}s",
         | 
| 124 | 
            +
                                 "follow_inodes" => "#{EX_FOLLOW_INODES}",
         | 
| 125 | 
            +
                               })
         | 
| 126 | 
            +
              end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
              def tailing_group_pattern
         | 
| 129 | 
            +
                "/#{@tmp_dir}\/(?<podname>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\/[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace>[^_]+)_(?<container>.+)-(?<docker_id>[a-z0-9]{6})\.log$/"
         | 
| 130 | 
            +
              end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
              DEBUG_LOG_LEVEL = config_element("", "", {
         | 
| 133 | 
            +
                "@log_level" => "debug"
         | 
| 134 | 
            +
              })
         | 
| 135 | 
            +
             | 
| 136 | 
            +
              def create_group_directive(pattern, rate_period, *rules)
         | 
| 137 | 
            +
                config_element("", "", {}, [
         | 
| 138 | 
            +
                  config_element("group", "", {
         | 
| 139 | 
            +
                    "pattern" => pattern,
         | 
| 140 | 
            +
                    "rate_period" => rate_period
         | 
| 141 | 
            +
                  }, rules)
         | 
| 142 | 
            +
                ])
         | 
| 143 | 
            +
              end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
              def create_rule_directive(match_named_captures, limit)
         | 
| 146 | 
            +
                params = {
         | 
| 147 | 
            +
                  "limit" => limit,
         | 
| 148 | 
            +
                  "match" => match_named_captures,
         | 
| 149 | 
            +
                }
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                config_element("rule", "", params)
         | 
| 152 | 
            +
              end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
              def create_path_element(path)
         | 
| 155 | 
            +
                config_element("source", "", { "path" => "#{@tmp_dir}/#{path}" })
         | 
| 156 | 
            +
              end
         | 
| 157 | 
            +
             | 
| 147 158 | 
             
              def create_driver(conf = SINGLE_LINE_CONFIG, use_common_conf = true)
         | 
| 148 | 
            -
                config = use_common_conf ?  | 
| 159 | 
            +
                config = use_common_conf ? common_config + conf : conf
         | 
| 149 160 | 
             
                Fluent::Test::Driver::Input.new(Fluent::Plugin::TailInput).configure(config)
         | 
| 150 161 | 
             
              end
         | 
| 151 162 |  | 
| 152 163 | 
             
              sub_test_case "configure" do
         | 
| 153 164 | 
             
                test "plain single line" do
         | 
| 154 165 | 
             
                  d = create_driver
         | 
| 155 | 
            -
                  assert_equal | 
| 156 | 
            -
                  assert_equal | 
| 157 | 
            -
                  assert_equal | 
| 158 | 
            -
                  assert_equal | 
| 159 | 
            -
                  assert_equal | 
| 160 | 
            -
                  assert_equal | 
| 161 | 
            -
                  assert_equal | 
| 166 | 
            +
                  assert_equal(["#{@tmp_dir}/tail.txt"], d.instance.paths)
         | 
| 167 | 
            +
                  assert_equal("t1", d.instance.tag)
         | 
| 168 | 
            +
                  assert_equal(2, d.instance.rotate_wait)
         | 
| 169 | 
            +
                  assert_equal("#{@tmp_dir}/tail.pos", d.instance.pos_file)
         | 
| 170 | 
            +
                  assert_equal(1000, d.instance.read_lines_limit)
         | 
| 171 | 
            +
                  assert_equal(-1, d.instance.read_bytes_limit_per_second)
         | 
| 172 | 
            +
                  assert_equal(false, d.instance.ignore_repeated_permission_error)
         | 
| 162 173 | 
             
                  assert_nothing_raised do
         | 
| 163 174 | 
             
                    d.instance.have_read_capability?
         | 
| 164 175 | 
             
                  end
         | 
| @@ -175,13 +186,13 @@ class TailInputTest < Test::Unit::TestCase | |
| 175 186 | 
             
                test "multi paths with path_delimiter" do
         | 
| 176 187 | 
             
                  c = config_element("ROOT", "", { "path" => "tail.txt|test2|tmp,dev", "tag" => "t1", "path_delimiter" => "|" })
         | 
| 177 188 | 
             
                  d = create_driver(c + PARSE_SINGLE_LINE_CONFIG, false)
         | 
| 178 | 
            -
                  assert_equal | 
| 189 | 
            +
                  assert_equal(["tail.txt", "test2", "tmp,dev"], d.instance.paths)
         | 
| 179 190 | 
             
                end
         | 
| 180 191 |  | 
| 181 192 | 
             
                test "multi paths with same path configured twice" do
         | 
| 182 193 | 
             
                  c = config_element("ROOT", "", { "path" => "test1.txt,test2.txt,test1.txt", "tag" => "t1", "path_delimiter" => "," })
         | 
| 183 194 | 
             
                  d = create_driver(c + PARSE_SINGLE_LINE_CONFIG, false)
         | 
| 184 | 
            -
                  assert_equal | 
| 195 | 
            +
                  assert_equal(["test2.txt","test1.txt"].sort, d.instance.paths.sort)
         | 
| 185 196 | 
             
                end
         | 
| 186 197 |  | 
| 187 198 | 
             
                test "multi paths with invaid path_delimiter" do
         | 
| @@ -193,7 +204,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 193 204 |  | 
| 194 205 | 
             
                test "follow_inodes w/o pos file" do
         | 
| 195 206 | 
             
                  assert_raise(Fluent::ConfigError) do
         | 
| 196 | 
            -
                    create_driver( | 
| 207 | 
            +
                    create_driver(base_config + config_element('', '', {'follow_inodes' => 'true'}))
         | 
| 197 208 | 
             
                  end
         | 
| 198 209 | 
             
                end
         | 
| 199 210 |  | 
| @@ -223,7 +234,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 223 234 | 
             
                  test "valid" do
         | 
| 224 235 | 
             
                    conf = SINGLE_LINE_CONFIG + config_element("", "", { "encoding" => "utf-8" })
         | 
| 225 236 | 
             
                    d = create_driver(conf)
         | 
| 226 | 
            -
                    assert_equal | 
| 237 | 
            +
                    assert_equal(Encoding::UTF_8, d.instance.encoding)
         | 
| 227 238 | 
             
                  end
         | 
| 228 239 |  | 
| 229 240 | 
             
                  test "invalid" do
         | 
| @@ -263,12 +274,171 @@ class TailInputTest < Test::Unit::TestCase | |
| 263 274 | 
             
                end
         | 
| 264 275 | 
             
              end
         | 
| 265 276 |  | 
| 277 | 
            +
              sub_test_case "configure group" do
         | 
| 278 | 
            +
                test "<rule> required" do
         | 
| 279 | 
            +
                  conf = create_group_directive('.', '1m') + SINGLE_LINE_CONFIG
         | 
| 280 | 
            +
                  assert_raise(Fluent::ConfigError) do
         | 
| 281 | 
            +
                    create_driver(conf)
         | 
| 282 | 
            +
                  end
         | 
| 283 | 
            +
                end
         | 
| 284 | 
            +
             | 
| 285 | 
            +
                test "valid configuration" do
         | 
| 286 | 
            +
                  rule1 = create_rule_directive({
         | 
| 287 | 
            +
                    "namespace"=> "/namespace-a/",
         | 
| 288 | 
            +
                    "podname"=> "/podname-[b|c]/"
         | 
| 289 | 
            +
                  }, 100)
         | 
| 290 | 
            +
                  rule2 = create_rule_directive({
         | 
| 291 | 
            +
                    "namespace"=> "/namespace-[d|e]/",
         | 
| 292 | 
            +
                    "podname"=> "/podname-f/",
         | 
| 293 | 
            +
                  }, 50)
         | 
| 294 | 
            +
                  rule3 = create_rule_directive({
         | 
| 295 | 
            +
                    "podname"=> "/podname-g/",
         | 
| 296 | 
            +
                  }, -1)
         | 
| 297 | 
            +
                  rule4 = create_rule_directive({
         | 
| 298 | 
            +
                    "namespace"=> "/namespace-h/",
         | 
| 299 | 
            +
                  }, 0)
         | 
| 300 | 
            +
             | 
| 301 | 
            +
                  conf = create_group_directive(tailing_group_pattern, '1m', rule1, rule2, rule3, rule4) + SINGLE_LINE_CONFIG
         | 
| 302 | 
            +
                  assert_nothing_raised do
         | 
| 303 | 
            +
                    create_driver(conf)
         | 
| 304 | 
            +
                  end
         | 
| 305 | 
            +
                end
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                test "limit should be greater than DEFAULT_LIMIT (-1)" do
         | 
| 308 | 
            +
                  rule1 = create_rule_directive({
         | 
| 309 | 
            +
                    "namespace"=> "/namespace-a/",
         | 
| 310 | 
            +
                    "podname"=> "/podname-[b|c]/",
         | 
| 311 | 
            +
                  }, -100)
         | 
| 312 | 
            +
                  rule2 = create_rule_directive({
         | 
| 313 | 
            +
                    "namespace"=> "/namespace-[d|e]/",
         | 
| 314 | 
            +
                    "podname"=> "/podname-f/",
         | 
| 315 | 
            +
                  }, 50)
         | 
| 316 | 
            +
                  conf = create_group_directive(tailing_group_pattern, '1m', rule1, rule2) + SINGLE_LINE_CONFIG
         | 
| 317 | 
            +
                  assert_raise(RuntimeError) do
         | 
| 318 | 
            +
                    create_driver(conf)
         | 
| 319 | 
            +
                  end
         | 
| 320 | 
            +
                end
         | 
| 321 | 
            +
              end
         | 
| 322 | 
            +
             | 
| 323 | 
            +
              sub_test_case "group rules line limit resolution" do
         | 
| 324 | 
            +
                test "valid" do
         | 
| 325 | 
            +
                  rule1 = create_rule_directive({
         | 
| 326 | 
            +
                    "namespace"=> "/namespace-a/",
         | 
| 327 | 
            +
                    "podname"=> "/podname-[b|c]/",
         | 
| 328 | 
            +
                  }, 50)
         | 
| 329 | 
            +
                  rule2 = create_rule_directive({
         | 
| 330 | 
            +
                    "podname"=> "/podname-[b|c]/",
         | 
| 331 | 
            +
                  }, 400)
         | 
| 332 | 
            +
                  rule3 = create_rule_directive({
         | 
| 333 | 
            +
                    "namespace"=> "/namespace-a/",
         | 
| 334 | 
            +
                  }, 100)
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                  conf = create_group_directive(tailing_group_pattern, '1m', rule3, rule1, rule2) + SINGLE_LINE_CONFIG
         | 
| 337 | 
            +
                  assert_nothing_raised do
         | 
| 338 | 
            +
                    d = create_driver(conf)
         | 
| 339 | 
            +
                    instance = d.instance
         | 
| 340 | 
            +
             | 
| 341 | 
            +
                    metadata = {
         | 
| 342 | 
            +
                      "namespace"=> "namespace-a",
         | 
| 343 | 
            +
                      "podname"=> "podname-b",
         | 
| 344 | 
            +
                    }
         | 
| 345 | 
            +
                    assert_equal(50, instance.find_group(metadata).limit)
         | 
| 346 | 
            +
             | 
| 347 | 
            +
                    metadata = {
         | 
| 348 | 
            +
                      "namespace" => "namespace-a",
         | 
| 349 | 
            +
                      "podname" => "podname-c",
         | 
| 350 | 
            +
                    }
         | 
| 351 | 
            +
                    assert_equal(50, instance.find_group(metadata).limit)
         | 
| 352 | 
            +
             | 
| 353 | 
            +
                    metadata = {
         | 
| 354 | 
            +
                      "namespace" => "namespace-a",
         | 
| 355 | 
            +
                      "podname" => "podname-d",
         | 
| 356 | 
            +
                    }
         | 
| 357 | 
            +
                    assert_equal(100, instance.find_group(metadata).limit)
         | 
| 358 | 
            +
             | 
| 359 | 
            +
                    metadata = {
         | 
| 360 | 
            +
                      "namespace" => "namespace-f",
         | 
| 361 | 
            +
                      "podname" => "podname-b",
         | 
| 362 | 
            +
                    }
         | 
| 363 | 
            +
                    assert_equal(400, instance.find_group(metadata).limit)
         | 
| 364 | 
            +
             | 
| 365 | 
            +
                    metadata = {
         | 
| 366 | 
            +
                      "podname" => "podname-c",
         | 
| 367 | 
            +
                    }
         | 
| 368 | 
            +
                    assert_equal(400, instance.find_group(metadata).limit)
         | 
| 369 | 
            +
             | 
| 370 | 
            +
                    assert_equal(-1, instance.find_group({}).limit)
         | 
| 371 | 
            +
                  end
         | 
| 372 | 
            +
                end
         | 
| 373 | 
            +
              end
         | 
| 374 | 
            +
             | 
| 375 | 
            +
              sub_test_case "files should be placed in groups" do
         | 
| 376 | 
            +
                test "invalid regex pattern places files in default group" do
         | 
| 377 | 
            +
                  rule1 = create_rule_directive({}, 100) ## limits default groups
         | 
| 378 | 
            +
                  conf = ROOT_CONFIG + DEBUG_LOG_LEVEL + create_group_directive(tailing_group_pattern, '1m', rule1) + create_path_element("test*.txt") + SINGLE_LINE_CONFIG
         | 
| 379 | 
            +
             | 
| 380 | 
            +
                  d = create_driver(conf, false)
         | 
| 381 | 
            +
                  File.open("#{@tmp_dir}/test1.txt", 'w')
         | 
| 382 | 
            +
                  File.open("#{@tmp_dir}/test2.txt", 'w')
         | 
| 383 | 
            +
                  File.open("#{@tmp_dir}/test3.txt", 'w')
         | 
| 384 | 
            +
             | 
| 385 | 
            +
                  d.run do
         | 
| 386 | 
            +
                    ## checking default group_watcher's paths
         | 
| 387 | 
            +
                    instance = d.instance
         | 
| 388 | 
            +
                    key = instance.default_group_key
         | 
| 389 | 
            +
             | 
| 390 | 
            +
                    assert_equal(3, instance.log.logs.count{|a| a.match?("Cannot find group from metadata, Adding file in the default group\n")})
         | 
| 391 | 
            +
                    assert_equal(3, instance.group_watchers[key].size)
         | 
| 392 | 
            +
                    assert_true(instance.group_watchers[key].include? File.join(@tmp_dir, 'test1.txt'))
         | 
| 393 | 
            +
                    assert_true(instance.group_watchers[key].include? File.join(@tmp_dir, 'test2.txt'))
         | 
| 394 | 
            +
                    assert_true(instance.group_watchers[key].include? File.join(@tmp_dir, 'test3.txt'))
         | 
| 395 | 
            +
                  end
         | 
| 396 | 
            +
                end
         | 
| 397 | 
            +
             | 
| 398 | 
            +
                test "valid regex pattern places file in their respective groups" do
         | 
| 399 | 
            +
                  rule1 = create_rule_directive({
         | 
| 400 | 
            +
                    "namespace"=> "/test-namespace1/",
         | 
| 401 | 
            +
                    "podname"=> "/test-podname1/",
         | 
| 402 | 
            +
                  }, 100)
         | 
| 403 | 
            +
                  rule2 = create_rule_directive({
         | 
| 404 | 
            +
                    "namespace"=> "/test-namespace1/",
         | 
| 405 | 
            +
                  }, 200)
         | 
| 406 | 
            +
                  rule3 = create_rule_directive({
         | 
| 407 | 
            +
                    "podname"=> "/test-podname2/",
         | 
| 408 | 
            +
                  }, 300)
         | 
| 409 | 
            +
                  rule4 = create_rule_directive({}, 400)
         | 
| 410 | 
            +
             | 
| 411 | 
            +
                  path_element = create_path_element("test-podname*.log")
         | 
| 412 | 
            +
             | 
| 413 | 
            +
                  conf = ROOT_CONFIG + create_group_directive(tailing_group_pattern, '1m', rule4, rule3, rule2, rule1) + path_element + SINGLE_LINE_CONFIG
         | 
| 414 | 
            +
                  d = create_driver(conf, false)
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                  file1 = File.join(@tmp_dir, "test-podname1_test-namespace1_test-container-15fabq.log")
         | 
| 417 | 
            +
                  file2 = File.join(@tmp_dir, "test-podname3_test-namespace1_test-container-15fabq.log")
         | 
| 418 | 
            +
                  file3 = File.join(@tmp_dir, "test-podname2_test-namespace2_test-container-15fabq.log")
         | 
| 419 | 
            +
                  file4 = File.join(@tmp_dir, "test-podname4_test-namespace3_test-container-15fabq.log")
         | 
| 420 | 
            +
             | 
| 421 | 
            +
                  d.run do
         | 
| 422 | 
            +
                    File.open(file1, 'w')
         | 
| 423 | 
            +
                    File.open(file2, 'w')
         | 
| 424 | 
            +
                    File.open(file3, 'w')
         | 
| 425 | 
            +
                    File.open(file4, 'w')
         | 
| 426 | 
            +
             | 
| 427 | 
            +
                    instance = d.instance
         | 
| 428 | 
            +
                    assert_equal(100, instance.find_group_from_metadata(file1).limit)
         | 
| 429 | 
            +
                    assert_equal(200, instance.find_group_from_metadata(file2).limit)
         | 
| 430 | 
            +
                    assert_equal(300, instance.find_group_from_metadata(file3).limit)
         | 
| 431 | 
            +
                    assert_equal(400, instance.find_group_from_metadata(file4).limit)
         | 
| 432 | 
            +
                  end
         | 
| 433 | 
            +
                end
         | 
| 434 | 
            +
              end
         | 
| 435 | 
            +
             | 
| 266 436 | 
             
              sub_test_case "singleline" do
         | 
| 267 437 | 
             
                data(flat: SINGLE_LINE_CONFIG,
         | 
| 268 438 | 
             
                     parse: PARSE_SINGLE_LINE_CONFIG)
         | 
| 269 439 | 
             
                def test_emit(data)
         | 
| 270 440 | 
             
                  config = data
         | 
| 271 | 
            -
                  File.open("#{ | 
| 441 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 272 442 | 
             
                    f.puts "test1"
         | 
| 273 443 | 
             
                    f.puts "test2"
         | 
| 274 444 | 
             
                  }
         | 
| @@ -276,7 +446,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 276 446 | 
             
                  d = create_driver(config)
         | 
| 277 447 |  | 
| 278 448 | 
             
                  d.run(expect_emits: 1) do
         | 
| 279 | 
            -
                    File.open("#{ | 
| 449 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 280 450 | 
             
                      f.puts "test3\ntest4"
         | 
| 281 451 | 
             
                    }
         | 
| 282 452 | 
             
                  end
         | 
| @@ -292,11 +462,11 @@ class TailInputTest < Test::Unit::TestCase | |
| 292 462 |  | 
| 293 463 | 
             
                def test_emit_with_emit_unmatched_lines_true
         | 
| 294 464 | 
             
                  config = config_element("", "", { "format" => "/^(?<message>test.*)/", "emit_unmatched_lines" => true })
         | 
| 295 | 
            -
                  File.open("#{ | 
| 465 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 296 466 |  | 
| 297 467 | 
             
                  d = create_driver(config)
         | 
| 298 468 | 
             
                  d.run(expect_emits: 1) do
         | 
| 299 | 
            -
                    File.open("#{ | 
| 469 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 300 470 | 
             
                      f.puts "test line 1"
         | 
| 301 471 | 
             
                      f.puts "test line 2"
         | 
| 302 472 | 
             
                      f.puts "bad line 1"
         | 
| @@ -328,7 +498,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 328 498 | 
             
                  msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
         | 
| 329 499 |  | 
| 330 500 | 
             
                  d.run(expect_emits: num_events, timeout: 2) do
         | 
| 331 | 
            -
                    File.open("#{ | 
| 501 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 332 502 | 
             
                      f.puts msg
         | 
| 333 503 | 
             
                      f.puts msg
         | 
| 334 504 | 
             
                    }
         | 
| @@ -343,7 +513,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 343 513 |  | 
| 344 514 | 
             
                sub_test_case "log throttling per file" do
         | 
| 345 515 | 
             
                  teardown do
         | 
| 346 | 
            -
                    cleanup_file("#{ | 
| 516 | 
            +
                    cleanup_file("#{@tmp_dir}/tail.txt")
         | 
| 347 517 | 
             
                  end
         | 
| 348 518 |  | 
| 349 519 | 
             
                  sub_test_case "reads_bytes_per_second w/o throttled" do
         | 
| @@ -374,7 +544,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 374 544 |  | 
| 375 545 | 
             
                      d = create_driver(config)
         | 
| 376 546 | 
             
                      d.run(expect_emits: 2) do
         | 
| 377 | 
            -
                        File.open("#{ | 
| 547 | 
            +
                        File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 378 548 | 
             
                          100.times do
         | 
| 379 549 | 
             
                            f.puts msg
         | 
| 380 550 | 
             
                          end
         | 
| @@ -397,7 +567,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 397 567 | 
             
                      start_time = Fluent::Clock.now
         | 
| 398 568 | 
             
                      d = create_driver(config)
         | 
| 399 569 | 
             
                      d.run(expect_emits: 2) do
         | 
| 400 | 
            -
                        File.open("#{ | 
| 570 | 
            +
                        File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 401 571 | 
             
                          8000.times do
         | 
| 402 572 | 
             
                            f.puts msg
         | 
| 403 573 | 
             
                          end
         | 
| @@ -436,7 +606,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 436 606 | 
             
                        io_handler
         | 
| 437 607 | 
             
                      end
         | 
| 438 608 |  | 
| 439 | 
            -
                      File.open("#{ | 
| 609 | 
            +
                      File.open("#{@tmp_dir}/tail.txt", "ab") do |f|
         | 
| 440 610 | 
             
                        100.times do
         | 
| 441 611 | 
             
                          f.puts msg
         | 
| 442 612 | 
             
                        end
         | 
| @@ -446,7 +616,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 446 616 | 
             
                      d.run do
         | 
| 447 617 | 
             
                        start_time = Fluent::Clock.now
         | 
| 448 618 | 
             
                        while Fluent::Clock.now - start_time < 0.8 do
         | 
| 449 | 
            -
                          File.open("#{ | 
| 619 | 
            +
                          File.open("#{@tmp_dir}/tail.txt", "ab") do |f|
         | 
| 450 620 | 
             
                            f.puts msg
         | 
| 451 621 | 
             
                            f.flush
         | 
| 452 622 | 
             
                          end
         | 
| @@ -464,7 +634,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 464 634 | 
             
                      num_lines = 1024 * 3
         | 
| 465 635 | 
             
                      msg = "08bytes"
         | 
| 466 636 |  | 
| 467 | 
            -
                      File.open("#{ | 
| 637 | 
            +
                      File.open("#{@tmp_dir}/tail.txt", "wb") do |f|
         | 
| 468 638 | 
             
                        f.write("#{msg}\n" * num_lines)
         | 
| 469 639 | 
             
                      end
         | 
| 470 640 |  | 
| @@ -481,8 +651,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 481 651 | 
             
                      d.run(timeout: 10) do
         | 
| 482 652 | 
             
                        while d.events.size < num_lines do
         | 
| 483 653 | 
             
                          if d.events.size > 0 && !rotated
         | 
| 484 | 
            -
                            cleanup_file("#{ | 
| 485 | 
            -
                            FileUtils.touch("#{ | 
| 654 | 
            +
                            cleanup_file("#{@tmp_dir}/tail.txt")
         | 
| 655 | 
            +
                            FileUtils.touch("#{@tmp_dir}/tail.txt")
         | 
| 486 656 | 
             
                            rotated = true
         | 
| 487 657 | 
             
                          end
         | 
| 488 658 | 
             
                          sleep 0.3
         | 
| @@ -500,7 +670,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 500 670 | 
             
                      num_lines = 1024 * 2
         | 
| 501 671 | 
             
                      msg = "08bytes"
         | 
| 502 672 |  | 
| 503 | 
            -
                      File.open("#{ | 
| 673 | 
            +
                      File.open("#{@tmp_dir}/tail.txt", "wb") do |f|
         | 
| 504 674 | 
             
                        f.write("#{msg}\n" * num_lines)
         | 
| 505 675 | 
             
                      end
         | 
| 506 676 |  | 
| @@ -527,8 +697,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 527 697 | 
             
                      d.run(timeout: 10) do
         | 
| 528 698 | 
             
                        until detached do
         | 
| 529 699 | 
             
                          if d.events.size > 0 && !rotated
         | 
| 530 | 
            -
                            cleanup_file("#{ | 
| 531 | 
            -
                            FileUtils.touch("#{ | 
| 700 | 
            +
                            cleanup_file("#{@tmp_dir}/tail.txt")
         | 
| 701 | 
            +
                            FileUtils.touch("#{@tmp_dir}/tail.txt")
         | 
| 532 702 | 
             
                            rotated = true
         | 
| 533 703 | 
             
                          end
         | 
| 534 704 | 
             
                          sleep 0.3
         | 
| @@ -548,7 +718,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 548 718 | 
             
                     parse: CONFIG_READ_FROM_HEAD + PARSE_SINGLE_LINE_CONFIG)
         | 
| 549 719 | 
             
                def test_emit_with_read_from_head(data)
         | 
| 550 720 | 
             
                  config = data
         | 
| 551 | 
            -
                  File.open("#{ | 
| 721 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 552 722 | 
             
                    f.puts "test1"
         | 
| 553 723 | 
             
                    f.puts "test2"
         | 
| 554 724 | 
             
                  }
         | 
| @@ -556,7 +726,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 556 726 | 
             
                  d = create_driver(config)
         | 
| 557 727 |  | 
| 558 728 | 
             
                  d.run(expect_emits: 2) do
         | 
| 559 | 
            -
                    File.open("#{ | 
| 729 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 560 730 | 
             
                      f.puts "test3"
         | 
| 561 731 | 
             
                      f.puts "test4"
         | 
| 562 732 | 
             
                    }
         | 
| @@ -574,7 +744,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 574 744 | 
             
                     parse: CONFIG_DISABLE_WATCH_TIMER + PARSE_SINGLE_LINE_CONFIG)
         | 
| 575 745 | 
             
                def test_emit_without_watch_timer(data)
         | 
| 576 746 | 
             
                  config = data
         | 
| 577 | 
            -
                  File.open("#{ | 
| 747 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 578 748 | 
             
                    f.puts "test1"
         | 
| 579 749 | 
             
                    f.puts "test2"
         | 
| 580 750 | 
             
                  }
         | 
| @@ -582,7 +752,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 582 752 | 
             
                  d = create_driver(config)
         | 
| 583 753 |  | 
| 584 754 | 
             
                  d.run(expect_emits: 1) do
         | 
| 585 | 
            -
                    File.open("#{ | 
| 755 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 586 756 | 
             
                      f.puts "test3"
         | 
| 587 757 | 
             
                      f.puts "test4"
         | 
| 588 758 | 
             
                    }
         | 
| @@ -601,12 +771,12 @@ class TailInputTest < Test::Unit::TestCase | |
| 601 771 | 
             
                  omit "need inotify" unless Fluent.linux?
         | 
| 602 772 |  | 
| 603 773 | 
             
                  config = config_element("ROOT", "", {
         | 
| 604 | 
            -
                                            "path" => "#{ | 
| 774 | 
            +
                                            "path" => "#{@tmp_dir}/tail*.txt",
         | 
| 605 775 | 
             
                                            "tag" => "t1",
         | 
| 606 776 | 
             
                                          })
         | 
| 607 777 | 
             
                  config = config + CONFIG_DISABLE_WATCH_TIMER + SINGLE_LINE_CONFIG
         | 
| 608 778 |  | 
| 609 | 
            -
                  File.open("#{ | 
| 779 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 610 780 | 
             
                    f.puts "test1"
         | 
| 611 781 | 
             
                    f.puts "test2"
         | 
| 612 782 | 
             
                  }
         | 
| @@ -614,7 +784,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 614 784 | 
             
                  d = create_driver(config, false)
         | 
| 615 785 |  | 
| 616 786 | 
             
                  d.run(expect_emits: 1, timeout: 1) do
         | 
| 617 | 
            -
                    File.open("#{ | 
| 787 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 618 788 | 
             
                      f.puts "test3"
         | 
| 619 789 | 
             
                      f.puts "test4"
         | 
| 620 790 | 
             
                    }
         | 
| @@ -632,7 +802,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 632 802 | 
             
                     parse: CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
         | 
| 633 803 | 
             
                def test_emit_with_disable_stat_watcher(data)
         | 
| 634 804 | 
             
                  config = data
         | 
| 635 | 
            -
                  File.open("#{ | 
| 805 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 636 806 | 
             
                    f.puts "test1"
         | 
| 637 807 | 
             
                    f.puts "test2"
         | 
| 638 808 | 
             
                  }
         | 
| @@ -640,7 +810,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 640 810 | 
             
                  d = create_driver(config)
         | 
| 641 811 |  | 
| 642 812 | 
             
                  d.run(expect_emits: 1) do
         | 
| 643 | 
            -
                    File.open("#{ | 
| 813 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 644 814 | 
             
                      f.puts "test3"
         | 
| 645 815 | 
             
                      f.puts "test4"
         | 
| 646 816 | 
             
                    }
         | 
| @@ -656,7 +826,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 656 826 | 
             
                  d = create_driver(SINGLE_LINE_CONFIG)
         | 
| 657 827 |  | 
| 658 828 | 
             
                  d.run(expect_emits: 1, timeout: 3) do
         | 
| 659 | 
            -
                    File.open("#{ | 
| 829 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 660 830 | 
             
                      f.puts "test1\ntest2\n"
         | 
| 661 831 | 
             
                    }
         | 
| 662 832 | 
             
                  end
         | 
| @@ -682,11 +852,14 @@ class TailInputTest < Test::Unit::TestCase | |
| 682 852 |  | 
| 683 853 | 
             
                def setup
         | 
| 684 854 | 
             
                  omit "NTFS doesn't support UNIX like permissions" if Fluent.windows?
         | 
| 855 | 
            +
                  super
         | 
| 685 856 | 
             
                  # Store default permission
         | 
| 686 857 | 
             
                  @default_permission = system_config.instance_variable_get(:@file_permission)
         | 
| 687 858 | 
             
                end
         | 
| 688 859 |  | 
| 689 860 | 
             
                def teardown
         | 
| 861 | 
            +
                  return if Fluent.windows?
         | 
| 862 | 
            +
                  super
         | 
| 690 863 | 
             
                  # Restore default permission
         | 
| 691 864 | 
             
                  system_config.instance_variable_set(:@file_permission, @default_permission)
         | 
| 692 865 | 
             
                end
         | 
| @@ -700,7 +873,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 700 873 | 
             
                  system_conf = parse_system(CONFIG_SYSTEM)
         | 
| 701 874 | 
             
                  sc = Fluent::SystemConfig.new(system_conf)
         | 
| 702 875 | 
             
                  Fluent::Engine.init(sc)
         | 
| 703 | 
            -
                  File.open("#{ | 
| 876 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 704 877 | 
             
                    f.puts "test1"
         | 
| 705 878 | 
             
                    f.puts "test2"
         | 
| 706 879 | 
             
                  }
         | 
| @@ -708,7 +881,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 708 881 | 
             
                  d = create_driver
         | 
| 709 882 |  | 
| 710 883 | 
             
                  d.run(expect_emits: 1) do
         | 
| 711 | 
            -
                    File.open("#{ | 
| 884 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 712 885 | 
             
                      f.puts "test3"
         | 
| 713 886 | 
             
                      f.puts "test4"
         | 
| 714 887 | 
             
                    }
         | 
| @@ -728,16 +901,18 @@ class TailInputTest < Test::Unit::TestCase | |
| 728 901 | 
             
              end
         | 
| 729 902 |  | 
| 730 903 | 
             
              sub_test_case "rotate file" do
         | 
| 904 | 
            +
                def create_driver(conf = SINGLE_LINE_CONFIG)
         | 
| 905 | 
            +
                  config = common_config + conf
         | 
| 906 | 
            +
                  Fluent::Test::Driver::Input.new(Fluent::Plugin::TailInput).configure(config)
         | 
| 907 | 
            +
                end
         | 
| 908 | 
            +
             | 
| 731 909 | 
             
                data(flat: SINGLE_LINE_CONFIG,
         | 
| 732 910 | 
             
                     parse: PARSE_SINGLE_LINE_CONFIG)
         | 
| 733 911 | 
             
                def test_rotate_file(data)
         | 
| 734 912 | 
             
                  config = data
         | 
| 735 913 | 
             
                  events = sub_test_rotate_file(config, expect_emits: 2)
         | 
| 736 | 
            -
                  assert_equal( | 
| 737 | 
            -
             | 
| 738 | 
            -
                  assert_equal({"message" => "test4"}, events[1][2])
         | 
| 739 | 
            -
                  assert_equal({"message" => "test5"}, events[2][2])
         | 
| 740 | 
            -
                  assert_equal({"message" => "test6"}, events[3][2])
         | 
| 914 | 
            +
                  assert_equal(3.upto(6).collect { |i| {"message" => "test#{i}"} },
         | 
| 915 | 
            +
                               events.collect { |event| event[2] })
         | 
| 741 916 | 
             
                end
         | 
| 742 917 |  | 
| 743 918 | 
             
                data(flat: CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG,
         | 
| @@ -745,13 +920,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 745 920 | 
             
                def test_rotate_file_with_read_from_head(data)
         | 
| 746 921 | 
             
                  config = data
         | 
| 747 922 | 
             
                  events = sub_test_rotate_file(config, expect_records: 6)
         | 
| 748 | 
            -
                  assert_equal(6, | 
| 749 | 
            -
             | 
| 750 | 
            -
                  assert_equal({"message" => "test2"}, events[1][2])
         | 
| 751 | 
            -
                  assert_equal({"message" => "test3"}, events[2][2])
         | 
| 752 | 
            -
                  assert_equal({"message" => "test4"}, events[3][2])
         | 
| 753 | 
            -
                  assert_equal({"message" => "test5"}, events[4][2])
         | 
| 754 | 
            -
                  assert_equal({"message" => "test6"}, events[5][2])
         | 
| 923 | 
            +
                  assert_equal(1.upto(6).collect { |i| {"message" => "test#{i}"} },
         | 
| 924 | 
            +
                               events.collect { |event| event[2] })
         | 
| 755 925 | 
             
                end
         | 
| 756 926 |  | 
| 757 927 | 
             
                data(flat: CONFIG_OPEN_ON_EVERY_UPDATE + CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG,
         | 
| @@ -759,13 +929,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 759 929 | 
             
                def test_rotate_file_with_open_on_every_update(data)
         | 
| 760 930 | 
             
                  config = data
         | 
| 761 931 | 
             
                  events = sub_test_rotate_file(config, expect_records: 6)
         | 
| 762 | 
            -
                  assert_equal(6, | 
| 763 | 
            -
             | 
| 764 | 
            -
                  assert_equal({"message" => "test2"}, events[1][2])
         | 
| 765 | 
            -
                  assert_equal({"message" => "test3"}, events[2][2])
         | 
| 766 | 
            -
                  assert_equal({"message" => "test4"}, events[3][2])
         | 
| 767 | 
            -
                  assert_equal({"message" => "test5"}, events[4][2])
         | 
| 768 | 
            -
                  assert_equal({"message" => "test6"}, events[5][2])
         | 
| 932 | 
            +
                  assert_equal(1.upto(6).collect { |i| {"message" => "test#{i}"} },
         | 
| 933 | 
            +
                               events.collect { |event| event[2] })
         | 
| 769 934 | 
             
                end
         | 
| 770 935 |  | 
| 771 936 | 
             
                data(flat: SINGLE_LINE_CONFIG,
         | 
| @@ -773,26 +938,21 @@ class TailInputTest < Test::Unit::TestCase | |
| 773 938 | 
             
                def test_rotate_file_with_write_old(data)
         | 
| 774 939 | 
             
                  config = data
         | 
| 775 940 | 
             
                  events = sub_test_rotate_file(config, expect_emits: 3) { |rotated_file|
         | 
| 776 | 
            -
                    File.open("#{ | 
| 941 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 777 942 | 
             
                    rotated_file.puts "test7"
         | 
| 778 943 | 
             
                    rotated_file.puts "test8"
         | 
| 779 944 | 
             
                    rotated_file.flush
         | 
| 780 945 |  | 
| 781 946 | 
             
                    sleep 1
         | 
| 782 | 
            -
                    File.open("#{ | 
| 947 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 783 948 | 
             
                      f.puts "test5"
         | 
| 784 949 | 
             
                      f.puts "test6"
         | 
| 785 950 | 
             
                    }
         | 
| 786 951 | 
             
                  }
         | 
| 787 952 | 
             
                  # This test sometimes fails and it shows a potential bug of in_tail
         | 
| 788 953 | 
             
                  # https://github.com/fluent/fluentd/issues/1434
         | 
| 789 | 
            -
                  assert_equal( | 
| 790 | 
            -
             | 
| 791 | 
            -
                  assert_equal({"message" => "test4"}, events[1][2])
         | 
| 792 | 
            -
                  assert_equal({"message" => "test7"}, events[2][2])
         | 
| 793 | 
            -
                  assert_equal({"message" => "test8"}, events[3][2])
         | 
| 794 | 
            -
                  assert_equal({"message" => "test5"}, events[4][2])
         | 
| 795 | 
            -
                  assert_equal({"message" => "test6"}, events[5][2])
         | 
| 954 | 
            +
                  assert_equal([3, 4, 7, 8, 5, 6].collect { |i| {"message" => "test#{i}"} },
         | 
| 955 | 
            +
                               events.collect { |event| event[2] })
         | 
| 796 956 | 
             
                end
         | 
| 797 957 |  | 
| 798 958 | 
             
                data(flat: SINGLE_LINE_CONFIG,
         | 
| @@ -804,21 +964,19 @@ class TailInputTest < Test::Unit::TestCase | |
| 804 964 | 
             
                    rotated_file.puts "test8"
         | 
| 805 965 | 
             
                    rotated_file.flush
         | 
| 806 966 | 
             
                  }
         | 
| 807 | 
            -
                  assert_equal(4,  | 
| 808 | 
            -
             | 
| 809 | 
            -
                  assert_equal({"message" => "test4"}, events[1][2])
         | 
| 810 | 
            -
                  assert_equal({"message" => "test7"}, events[2][2])
         | 
| 811 | 
            -
                  assert_equal({"message" => "test8"}, events[3][2])
         | 
| 967 | 
            +
                  assert_equal([3, 4, 7, 8].collect { |i| {"message" => "test#{i}"} },
         | 
| 968 | 
            +
                               events.collect { |event| event[2] })
         | 
| 812 969 | 
             
                end
         | 
| 813 970 |  | 
| 814 | 
            -
                def sub_test_rotate_file(config = nil, expect_emits: nil, expect_records: nil, timeout:  | 
| 815 | 
            -
                  file = Fluent::FileWrapper.open("#{ | 
| 971 | 
            +
                def sub_test_rotate_file(config = nil, expect_emits: nil, expect_records: nil, timeout: 5)
         | 
| 972 | 
            +
                  file = Fluent::FileWrapper.open("#{@tmp_dir}/tail.txt", "wb")
         | 
| 816 973 | 
             
                  file.puts "test1"
         | 
| 817 974 | 
             
                  file.puts "test2"
         | 
| 818 975 | 
             
                  file.flush
         | 
| 819 976 |  | 
| 820 977 | 
             
                  d = create_driver(config)
         | 
| 821 978 | 
             
                  d.run(expect_emits: expect_emits, expect_records: expect_records, timeout: timeout) do
         | 
| 979 | 
            +
                    sleep(0.1) while d.instance.instance_variable_get(:@startup)
         | 
| 822 980 | 
             
                    size = d.emit_count
         | 
| 823 981 | 
             
                    file.puts "test3"
         | 
| 824 982 | 
             
                    file.puts "test4"
         | 
| @@ -828,18 +986,18 @@ class TailInputTest < Test::Unit::TestCase | |
| 828 986 |  | 
| 829 987 | 
             
                    if Fluent.windows?
         | 
| 830 988 | 
             
                      file.close
         | 
| 831 | 
            -
                      FileUtils.mv("#{ | 
| 832 | 
            -
                      file =  | 
| 989 | 
            +
                      FileUtils.mv("#{@tmp_dir}/tail.txt", "#{@tmp_dir}/tail2.txt", force: true)
         | 
| 990 | 
            +
                      file = Fluent::FileWrapper.open("#{@tmp_dir}/tail2.txt", "ab")
         | 
| 833 991 | 
             
                    else
         | 
| 834 | 
            -
                      FileUtils.mv("#{ | 
| 992 | 
            +
                      FileUtils.mv("#{@tmp_dir}/tail.txt", "#{@tmp_dir}/tail2.txt")
         | 
| 835 993 | 
             
                    end
         | 
| 836 994 | 
             
                    if block_given?
         | 
| 837 995 | 
             
                      yield file
         | 
| 838 996 | 
             
                    else
         | 
| 839 | 
            -
                      File.open("#{ | 
| 997 | 
            +
                      File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 840 998 | 
             
                      sleep 1
         | 
| 841 999 |  | 
| 842 | 
            -
                      File.open("#{ | 
| 1000 | 
            +
                      File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 843 1001 | 
             
                        f.puts "test5"
         | 
| 844 1002 | 
             
                        f.puts "test6"
         | 
| 845 1003 | 
             
                      }
         | 
| @@ -853,10 +1011,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 853 1011 | 
             
              end
         | 
| 854 1012 |  | 
| 855 1013 | 
             
              def test_truncate_file
         | 
| 856 | 
            -
                omit "Permission denied error happen on Windows. Need fix" if Fluent.windows?
         | 
| 857 | 
            -
             | 
| 858 1014 | 
             
                config = SINGLE_LINE_CONFIG
         | 
| 859 | 
            -
                File.open("#{ | 
| 1015 | 
            +
                File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 860 1016 | 
             
                  f.puts "test1"
         | 
| 861 1017 | 
             
                  f.puts "test2"
         | 
| 862 1018 | 
             
                  f.flush
         | 
| @@ -865,12 +1021,18 @@ class TailInputTest < Test::Unit::TestCase | |
| 865 1021 | 
             
                d = create_driver(config)
         | 
| 866 1022 |  | 
| 867 1023 | 
             
                d.run(expect_emits: 2) do
         | 
| 868 | 
            -
                  File.open("#{ | 
| 1024 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 869 1025 | 
             
                    f.puts "test3\ntest4"
         | 
| 870 1026 | 
             
                    f.flush
         | 
| 871 1027 | 
             
                  }
         | 
| 872 1028 | 
             
                  waiting(2) { sleep 0.1 until d.events.length == 2 }
         | 
| 873 | 
            -
                   | 
| 1029 | 
            +
                  if Fluent.windows?
         | 
| 1030 | 
            +
                    Fluent::FileWrapper.open("#{@tmp_dir}/tail.txt", "wb") { |f|
         | 
| 1031 | 
            +
                      f.puts("test1");
         | 
| 1032 | 
            +
                    }
         | 
| 1033 | 
            +
                  else
         | 
| 1034 | 
            +
                    File.truncate("#{@tmp_dir}/tail.txt", 6)
         | 
| 1035 | 
            +
                  end
         | 
| 874 1036 | 
             
                end
         | 
| 875 1037 |  | 
| 876 1038 | 
             
                expected = {
         | 
| @@ -889,10 +1051,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 889 1051 | 
             
              end
         | 
| 890 1052 |  | 
| 891 1053 | 
             
              def test_move_truncate_move_back
         | 
| 892 | 
            -
                omit "Permission denied error happen on Windows. Need fix" if Fluent.windows?
         | 
| 893 | 
            -
             | 
| 894 1054 | 
             
                config = SINGLE_LINE_CONFIG
         | 
| 895 | 
            -
                File.open("#{ | 
| 1055 | 
            +
                File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 896 1056 | 
             
                  f.puts "test1"
         | 
| 897 1057 | 
             
                  f.puts "test2"
         | 
| 898 1058 | 
             
                }
         | 
| @@ -901,17 +1061,23 @@ class TailInputTest < Test::Unit::TestCase | |
| 901 1061 |  | 
| 902 1062 | 
             
                d.run(expect_emits: 1) do
         | 
| 903 1063 | 
             
                  if Fluent.windows?
         | 
| 904 | 
            -
                    FileUtils.mv("#{ | 
| 1064 | 
            +
                    FileUtils.mv("#{@tmp_dir}/tail.txt", "#{@tmp_dir}/tail2.txt", force: true)
         | 
| 905 1065 | 
             
                  else
         | 
| 906 | 
            -
                    FileUtils.mv("#{ | 
| 1066 | 
            +
                    FileUtils.mv("#{@tmp_dir}/tail.txt", "#{@tmp_dir}/tail2.txt")
         | 
| 907 1067 | 
             
                  end
         | 
| 908 1068 | 
             
                  sleep(1)
         | 
| 909 | 
            -
                   | 
| 1069 | 
            +
                  if Fluent.windows?
         | 
| 1070 | 
            +
                    Fluent::FileWrapper.open("#{@tmp_dir}/tail2.txt", "wb") { |f|
         | 
| 1071 | 
            +
                      f.puts("test1");
         | 
| 1072 | 
            +
                    }
         | 
| 1073 | 
            +
                  else
         | 
| 1074 | 
            +
                    File.truncate("#{@tmp_dir}/tail2.txt", 6)
         | 
| 1075 | 
            +
                  end
         | 
| 910 1076 | 
             
                  sleep(1)
         | 
| 911 1077 | 
             
                  if Fluent.windows?
         | 
| 912 | 
            -
                    FileUtils.mv("#{ | 
| 1078 | 
            +
                    FileUtils.mv("#{@tmp_dir}/tail2.txt", "#{@tmp_dir}/tail.txt", force: true)
         | 
| 913 1079 | 
             
                  else
         | 
| 914 | 
            -
                    FileUtils.mv("#{ | 
| 1080 | 
            +
                    FileUtils.mv("#{@tmp_dir}/tail2.txt", "#{@tmp_dir}/tail.txt")
         | 
| 915 1081 | 
             
                  end
         | 
| 916 1082 | 
             
                end
         | 
| 917 1083 |  | 
| @@ -923,17 +1089,17 @@ class TailInputTest < Test::Unit::TestCase | |
| 923 1089 | 
             
              end
         | 
| 924 1090 |  | 
| 925 1091 | 
             
              def test_lf
         | 
| 926 | 
            -
                File.open("#{ | 
| 1092 | 
            +
                File.open("#{@tmp_dir}/tail.txt", "wb") {|f| }
         | 
| 927 1093 |  | 
| 928 1094 | 
             
                d = create_driver
         | 
| 929 1095 |  | 
| 930 1096 | 
             
                d.run(expect_emits: 1) do
         | 
| 931 | 
            -
                  File.open("#{ | 
| 1097 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 932 1098 | 
             
                    f.print "test3"
         | 
| 933 1099 | 
             
                  }
         | 
| 934 1100 | 
             
                  sleep 1
         | 
| 935 1101 |  | 
| 936 | 
            -
                  File.open("#{ | 
| 1102 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 937 1103 | 
             
                    f.puts "test4"
         | 
| 938 1104 | 
             
                  }
         | 
| 939 1105 | 
             
                end
         | 
| @@ -944,12 +1110,12 @@ class TailInputTest < Test::Unit::TestCase | |
| 944 1110 | 
             
              end
         | 
| 945 1111 |  | 
| 946 1112 | 
             
              def test_whitespace
         | 
| 947 | 
            -
                File.open("#{ | 
| 1113 | 
            +
                File.open("#{@tmp_dir}/tail.txt", "wb") {|f| }
         | 
| 948 1114 |  | 
| 949 1115 | 
             
                d = create_driver
         | 
| 950 1116 |  | 
| 951 1117 | 
             
                d.run(expect_emits: 1) do
         | 
| 952 | 
            -
                  File.open("#{ | 
| 1118 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 953 1119 | 
             
                    f.puts "    "		# 4 spaces
         | 
| 954 1120 | 
             
                    f.puts "    4 spaces"
         | 
| 955 1121 | 
             
                    f.puts "4 spaces    "
         | 
| @@ -980,7 +1146,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 980 1146 | 
             
                d = create_driver(CONFIG_READ_FROM_HEAD + encoding_config)
         | 
| 981 1147 |  | 
| 982 1148 | 
             
                d.run(expect_emits: 1) do
         | 
| 983 | 
            -
                  File.open("#{ | 
| 1149 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 984 1150 | 
             
                    f.puts "test"
         | 
| 985 1151 | 
             
                  }
         | 
| 986 1152 | 
             
                end
         | 
| @@ -1002,7 +1168,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1002 1168 | 
             
                utf8_message = cp932_message.encode(Encoding::UTF_8)
         | 
| 1003 1169 |  | 
| 1004 1170 | 
             
                d.run(expect_emits: 1) do
         | 
| 1005 | 
            -
                  File.open("#{ | 
| 1171 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "w:cp932") {|f|
         | 
| 1006 1172 | 
             
                    f.puts cp932_message
         | 
| 1007 1173 | 
             
                  }
         | 
| 1008 1174 | 
             
                end
         | 
| @@ -1025,7 +1191,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1025 1191 | 
             
                utf8_message = utf16_message.encode(Encoding::UTF_8).strip
         | 
| 1026 1192 |  | 
| 1027 1193 | 
             
                d.run(expect_emits: 1) do
         | 
| 1028 | 
            -
                  File.open("#{ | 
| 1194 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "w:utf-16le") { |f|
         | 
| 1029 1195 | 
             
                    f.write utf16_message
         | 
| 1030 1196 | 
             
                  }
         | 
| 1031 1197 | 
             
                end
         | 
| @@ -1046,7 +1212,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1046 1212 | 
             
                d = create_driver(conf)
         | 
| 1047 1213 |  | 
| 1048 1214 | 
             
                d.run(expect_emits: 1) do
         | 
| 1049 | 
            -
                  File.open("#{ | 
| 1215 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "w") { |f|
         | 
| 1050 1216 | 
             
                    f.write "te\x86st\n"
         | 
| 1051 1217 | 
             
                  }
         | 
| 1052 1218 | 
             
                end
         | 
| @@ -1061,11 +1227,11 @@ class TailInputTest < Test::Unit::TestCase | |
| 1061 1227 | 
             
                     parse: PARSE_MULTILINE_CONFIG)
         | 
| 1062 1228 | 
             
                def test_multiline(data)
         | 
| 1063 1229 | 
             
                  config = data
         | 
| 1064 | 
            -
                  File.open("#{ | 
| 1230 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 1065 1231 |  | 
| 1066 1232 | 
             
                  d = create_driver(config)
         | 
| 1067 1233 | 
             
                  d.run(expect_emits: 1) do
         | 
| 1068 | 
            -
                    File.open("#{ | 
| 1234 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 1069 1235 | 
             
                      f.puts "f test1"
         | 
| 1070 1236 | 
             
                      f.puts "s test2"
         | 
| 1071 1237 | 
             
                      f.puts "f test3"
         | 
| @@ -1089,11 +1255,11 @@ class TailInputTest < Test::Unit::TestCase | |
| 1089 1255 | 
             
                     parse: PARSE_MULTILINE_CONFIG)
         | 
| 1090 1256 | 
             
                def test_multiline_with_emit_unmatched_lines_true(data)
         | 
| 1091 1257 | 
             
                  config = data + config_element("", "", { "emit_unmatched_lines" => true })
         | 
| 1092 | 
            -
                  File.open("#{ | 
| 1258 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 1093 1259 |  | 
| 1094 1260 | 
             
                  d = create_driver(config)
         | 
| 1095 1261 | 
             
                  d.run(expect_emits: 1) do
         | 
| 1096 | 
            -
                    File.open("#{ | 
| 1262 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 1097 1263 | 
             
                      f.puts "f test1"
         | 
| 1098 1264 | 
             
                      f.puts "s test2"
         | 
| 1099 1265 | 
             
                      f.puts "f test3"
         | 
| @@ -1119,11 +1285,11 @@ class TailInputTest < Test::Unit::TestCase | |
| 1119 1285 | 
             
                  parse: PARSE_MULTILINE_CONFIG_WITH_NEWLINE)
         | 
| 1120 1286 | 
             
                def test_multiline_with_emit_unmatched_lines2(data)
         | 
| 1121 1287 | 
             
                  config = data + config_element("", "", { "emit_unmatched_lines" => true })
         | 
| 1122 | 
            -
                  File.open("#{ | 
| 1288 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 1123 1289 |  | 
| 1124 1290 | 
             
                  d = create_driver(config)
         | 
| 1125 1291 | 
             
                  d.run(expect_emits: 0, timeout: 1) do
         | 
| 1126 | 
            -
                    File.open("#{ | 
| 1292 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 1127 1293 | 
             
                      f.puts "s test0"
         | 
| 1128 1294 | 
             
                      f.puts "f test1"
         | 
| 1129 1295 | 
             
                      f.puts "f test2"
         | 
| @@ -1145,15 +1311,15 @@ class TailInputTest < Test::Unit::TestCase | |
| 1145 1311 | 
             
                data(flat: MULTILINE_CONFIG,
         | 
| 1146 1312 | 
             
                     parse: PARSE_MULTILINE_CONFIG)
         | 
| 1147 1313 | 
             
                def test_multiline_with_flush_interval(data)
         | 
| 1148 | 
            -
                  File.open("#{ | 
| 1314 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 1149 1315 |  | 
| 1150 1316 | 
             
                  config = data + config_element("", "", { "multiline_flush_interval" => "2s" })
         | 
| 1151 1317 | 
             
                  d = create_driver(config)
         | 
| 1152 1318 |  | 
| 1153 | 
            -
                  assert_equal | 
| 1319 | 
            +
                  assert_equal(2, d.instance.multiline_flush_interval)
         | 
| 1154 1320 |  | 
| 1155 1321 | 
             
                  d.run(expect_emits: 1) do
         | 
| 1156 | 
            -
                    File.open("#{ | 
| 1322 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 1157 1323 | 
             
                      f.puts "f test1"
         | 
| 1158 1324 | 
             
                      f.puts "s test2"
         | 
| 1159 1325 | 
             
                      f.puts "f test3"
         | 
| @@ -1188,7 +1354,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1188 1354 | 
             
                  d = create_driver(config + encoding_config)
         | 
| 1189 1355 |  | 
| 1190 1356 | 
             
                  d.run(expect_emits: 1) do
         | 
| 1191 | 
            -
                    File.open("#{ | 
| 1357 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "wb") { |f|
         | 
| 1192 1358 | 
             
                      f.puts "s test"
         | 
| 1193 1359 | 
             
                    }
         | 
| 1194 1360 | 
             
                  end
         | 
| @@ -1211,7 +1377,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1211 1377 | 
             
                  cp932_message = "s \x82\xCD\x82\xEB\x81\x5B\x82\xED\x81\x5B\x82\xE9\x82\xC7".force_encoding(Encoding::CP932)
         | 
| 1212 1378 | 
             
                  utf8_message = "\x82\xCD\x82\xEB\x81\x5B\x82\xED\x81\x5B\x82\xE9\x82\xC7".encode(Encoding::UTF_8, Encoding::CP932)
         | 
| 1213 1379 | 
             
                  d.run(expect_emits: 1) do
         | 
| 1214 | 
            -
                    File.open("#{ | 
| 1380 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "w:cp932") { |f|
         | 
| 1215 1381 | 
             
                      f.puts cp932_message
         | 
| 1216 1382 | 
             
                    }
         | 
| 1217 1383 | 
             
                  end
         | 
| @@ -1243,11 +1409,11 @@ class TailInputTest < Test::Unit::TestCase | |
| 1243 1409 | 
             
                    )
         | 
| 1244 1410 | 
             
                def test_multiline_with_multiple_formats(data)
         | 
| 1245 1411 | 
             
                  config = data
         | 
| 1246 | 
            -
                  File.open("#{ | 
| 1412 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 1247 1413 |  | 
| 1248 1414 | 
             
                  d = create_driver(config)
         | 
| 1249 1415 | 
             
                  d.run(expect_emits: 1) do
         | 
| 1250 | 
            -
                    File.open("#{ | 
| 1416 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 1251 1417 | 
             
                      f.puts "f test1"
         | 
| 1252 1418 | 
             
                      f.puts "s test2"
         | 
| 1253 1419 | 
             
                      f.puts "f test3"
         | 
| @@ -1283,7 +1449,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1283 1449 | 
             
                       ])
         | 
| 1284 1450 | 
             
                    )
         | 
| 1285 1451 | 
             
                def test_multilinelog_with_multiple_paths(data)
         | 
| 1286 | 
            -
                  files = ["#{ | 
| 1452 | 
            +
                  files = ["#{@tmp_dir}/tail1.txt", "#{@tmp_dir}/tail2.txt"]
         | 
| 1287 1453 | 
             
                  files.each { |file| File.open(file, "wb") { |f| } }
         | 
| 1288 1454 |  | 
| 1289 1455 | 
             
                  config = data + config_element("", "", {
         | 
| @@ -1328,12 +1494,12 @@ class TailInputTest < Test::Unit::TestCase | |
| 1328 1494 | 
             
                       ])
         | 
| 1329 1495 | 
             
                    )
         | 
| 1330 1496 | 
             
                def test_multiline_without_firstline(data)
         | 
| 1331 | 
            -
                  File.open("#{ | 
| 1497 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 1332 1498 |  | 
| 1333 1499 | 
             
                  config = data
         | 
| 1334 1500 | 
             
                  d = create_driver(config)
         | 
| 1335 1501 | 
             
                  d.run(expect_emits: 1) do
         | 
| 1336 | 
            -
                    File.open("#{ | 
| 1502 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 1337 1503 | 
             
                      f.puts "foo 1"
         | 
| 1338 1504 | 
             
                      f.puts "bar 1"
         | 
| 1339 1505 | 
             
                      f.puts "baz 1"
         | 
| @@ -1353,35 +1519,22 @@ class TailInputTest < Test::Unit::TestCase | |
| 1353 1519 | 
             
              sub_test_case "path" do
         | 
| 1354 1520 | 
             
                # * path test
         | 
| 1355 1521 | 
             
                # TODO: Clean up tests
         | 
| 1356 | 
            -
                EX_ROTATE_WAIT = 0
         | 
| 1357 | 
            -
                EX_FOLLOW_INODES = false
         | 
| 1358 | 
            -
             | 
| 1359 | 
            -
                EX_CONFIG = config_element("", "", {
         | 
| 1360 | 
            -
                                             "tag" => "tail",
         | 
| 1361 | 
            -
                                             "path" => "test/plugin/*/%Y/%m/%Y%m%d-%H%M%S.log,test/plugin/data/log/**/*.log",
         | 
| 1362 | 
            -
                                             "format" => "none",
         | 
| 1363 | 
            -
                                             "pos_file" => "#{TMP_DIR}/tail.pos",
         | 
| 1364 | 
            -
                                             "read_from_head" => true,
         | 
| 1365 | 
            -
                                             "refresh_interval" => 30,
         | 
| 1366 | 
            -
                                             "rotate_wait" => "#{EX_ROTATE_WAIT}s",
         | 
| 1367 | 
            -
                                             "follow_inodes" => "#{EX_FOLLOW_INODES}",
         | 
| 1368 | 
            -
                                           })
         | 
| 1369 1522 | 
             
                def test_expand_paths
         | 
| 1370 1523 | 
             
                  ex_paths = [
         | 
| 1371 1524 | 
             
                    create_target_info('test/plugin/data/2010/01/20100102-030405.log'),
         | 
| 1372 1525 | 
             
                    create_target_info('test/plugin/data/log/foo/bar.log'),
         | 
| 1373 1526 | 
             
                    create_target_info('test/plugin/data/log/test.log')
         | 
| 1374 1527 | 
             
                  ]
         | 
| 1375 | 
            -
                  plugin = create_driver( | 
| 1528 | 
            +
                  plugin = create_driver(ex_config, false).instance
         | 
| 1376 1529 | 
             
                  flexstub(Time) do |timeclass|
         | 
| 1377 1530 | 
             
                    timeclass.should_receive(:now).with_no_args.and_return(Time.new(2010, 1, 2, 3, 4, 5))
         | 
| 1378 | 
            -
                    assert_equal | 
| 1531 | 
            +
                    assert_equal(ex_paths, plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
         | 
| 1379 1532 | 
             
                  end
         | 
| 1380 1533 |  | 
| 1381 1534 | 
             
                  # Test exclusion
         | 
| 1382 | 
            -
                  exclude_config =  | 
| 1535 | 
            +
                  exclude_config = ex_config + config_element("", "", { "exclude_path" => %Q(["#{ex_paths.last.path}"]) })
         | 
| 1383 1536 | 
             
                  plugin = create_driver(exclude_config, false).instance
         | 
| 1384 | 
            -
                  assert_equal | 
| 1537 | 
            +
                  assert_equal(ex_paths - [ex_paths.last], plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
         | 
| 1385 1538 | 
             
                end
         | 
| 1386 1539 |  | 
| 1387 1540 | 
             
                def test_expand_paths_with_duplicate_configuration
         | 
| @@ -1389,10 +1542,10 @@ class TailInputTest < Test::Unit::TestCase | |
| 1389 1542 | 
             
                    create_target_info('test/plugin/data/log/foo/bar.log'),
         | 
| 1390 1543 | 
             
                    create_target_info('test/plugin/data/log/test.log')
         | 
| 1391 1544 | 
             
                  ]
         | 
| 1392 | 
            -
                  duplicate_config =  | 
| 1545 | 
            +
                  duplicate_config = ex_config.dup
         | 
| 1393 1546 | 
             
                  duplicate_config["path"]="test/plugin/data/log/**/*.log, test/plugin/data/log/**/*.log"
         | 
| 1394 | 
            -
                  plugin = create_driver( | 
| 1395 | 
            -
                  assert_equal | 
| 1547 | 
            +
                  plugin = create_driver(ex_config, false).instance
         | 
| 1548 | 
            +
                  assert_equal(expanded_paths, plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
         | 
| 1396 1549 | 
             
                end
         | 
| 1397 1550 |  | 
| 1398 1551 | 
             
                def test_expand_paths_with_timezone
         | 
| @@ -1402,7 +1555,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1402 1555 | 
             
                    create_target_info('test/plugin/data/log/test.log')
         | 
| 1403 1556 | 
             
                  ]
         | 
| 1404 1557 | 
             
                  ['Asia/Taipei', '+08'].each do |tz_type|
         | 
| 1405 | 
            -
                    taipei_config =  | 
| 1558 | 
            +
                    taipei_config = ex_config + config_element("", "", {"path_timezone" => tz_type})
         | 
| 1406 1559 | 
             
                    plugin = create_driver(taipei_config, false).instance
         | 
| 1407 1560 |  | 
| 1408 1561 | 
             
                    # Test exclude
         | 
| @@ -1414,8 +1567,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 1414 1567 | 
             
                        # env : 2010-01-01 19:04:05 (UTC), tail path : 2010-01-02 03:04:05 (Asia/Taipei)
         | 
| 1415 1568 | 
             
                        timeclass.should_receive(:now).with_no_args.and_return(Time.new(2010, 1, 1, 19, 4, 5))
         | 
| 1416 1569 |  | 
| 1417 | 
            -
                        assert_equal | 
| 1418 | 
            -
                        assert_equal | 
| 1570 | 
            +
                        assert_equal(ex_paths, plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
         | 
| 1571 | 
            +
                        assert_equal(ex_paths - [ex_paths.first], exclude_plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
         | 
| 1419 1572 | 
             
                      end
         | 
| 1420 1573 | 
             
                    end
         | 
| 1421 1574 | 
             
                  end
         | 
| @@ -1433,35 +1586,44 @@ class TailInputTest < Test::Unit::TestCase | |
| 1433 1586 | 
             
                    "tag" => "tail",
         | 
| 1434 1587 | 
             
                    "path" => "test/plugin/data/log/**/*",
         | 
| 1435 1588 | 
             
                    "format" => "none",
         | 
| 1436 | 
            -
                    "pos_file" => "#{ | 
| 1589 | 
            +
                    "pos_file" => "#{@tmp_dir}/tail.pos"
         | 
| 1437 1590 | 
             
                  })
         | 
| 1438 1591 |  | 
| 1439 1592 | 
             
                  plugin = create_driver(config, false).instance
         | 
| 1440 | 
            -
                  assert_equal | 
| 1593 | 
            +
                  assert_equal(expected_files, plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
         | 
| 1441 1594 | 
             
                end
         | 
| 1442 1595 |  | 
| 1443 1596 | 
             
                def test_unwatched_files_should_be_removed
         | 
| 1444 1597 | 
             
                  config = config_element("", "", {
         | 
| 1445 1598 | 
             
                                            "tag" => "tail",
         | 
| 1446 | 
            -
                                            "path" => "#{ | 
| 1599 | 
            +
                                            "path" => "#{@tmp_dir}/*.txt",
         | 
| 1447 1600 | 
             
                                            "format" => "none",
         | 
| 1448 | 
            -
                                            "pos_file" => "#{ | 
| 1601 | 
            +
                                            "pos_file" => "#{@tmp_dir}/tail.pos",
         | 
| 1449 1602 | 
             
                                            "read_from_head" => true,
         | 
| 1450 1603 | 
             
                                            "refresh_interval" => 1,
         | 
| 1451 1604 | 
             
                                          })
         | 
| 1452 1605 | 
             
                  d = create_driver(config, false)
         | 
| 1453 1606 | 
             
                  d.end_if { d.instance.instance_variable_get(:@tails).keys.size >= 1 }
         | 
| 1454 1607 | 
             
                  d.run(expect_emits: 1, shutdown: false) do
         | 
| 1455 | 
            -
                    File.open("#{ | 
| 1608 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f| f.puts "test3\n" }
         | 
| 1456 1609 | 
             
                  end
         | 
| 1457 1610 |  | 
| 1458 | 
            -
                  cleanup_directory( | 
| 1459 | 
            -
                  waiting(20) { sleep 0.1 until Dir.glob("#{ | 
| 1611 | 
            +
                  cleanup_directory(@tmp_dir)
         | 
| 1612 | 
            +
                  waiting(20) { sleep 0.1 until Dir.glob("#{@tmp_dir}/*.txt").size == 0 } # Ensure file is deleted on Windows
         | 
| 1460 1613 | 
             
                  waiting(5) { sleep 0.1 until d.instance.instance_variable_get(:@tails).keys.size <= 0 }
         | 
| 1461 1614 |  | 
| 1462 | 
            -
                  assert_equal | 
| 1463 | 
            -
             | 
| 1464 | 
            -
             | 
| 1615 | 
            +
                  assert_equal(
         | 
| 1616 | 
            +
                    {
         | 
| 1617 | 
            +
                      files: [],
         | 
| 1618 | 
            +
                      tails: []
         | 
| 1619 | 
            +
                    },
         | 
| 1620 | 
            +
                    {
         | 
| 1621 | 
            +
                      files: Dir.glob("#{@tmp_dir}/*.txt"),
         | 
| 1622 | 
            +
                      tails: d.instance.instance_variable_get(:@tails).keys
         | 
| 1623 | 
            +
                    }
         | 
| 1624 | 
            +
                  )
         | 
| 1625 | 
            +
                ensure
         | 
| 1626 | 
            +
                  d.instance_shutdown if d && d.instance
         | 
| 1465 1627 | 
             
                end
         | 
| 1466 1628 |  | 
| 1467 1629 | 
             
                def count_timer_object
         | 
| @@ -1511,55 +1673,55 @@ class TailInputTest < Test::Unit::TestCase | |
| 1511 1673 | 
             
                                        "rotate_wait" => "2s"
         | 
| 1512 1674 | 
             
                                   }) + PARSE_SINGLE_LINE_CONFIG, false)
         | 
| 1513 1675 |  | 
| 1514 | 
            -
                  assert_equal | 
| 1515 | 
            -
                  assert_equal | 
| 1676 | 
            +
                  assert_equal(readable_paths, d.instance.expand_paths.length)
         | 
| 1677 | 
            +
                  assert_equal(result, d.instance.have_read_capability?)
         | 
| 1516 1678 | 
             
                end
         | 
| 1517 1679 | 
             
              end
         | 
| 1518 1680 |  | 
| 1519 1681 | 
             
              def test_pos_file_dir_creation
         | 
| 1520 1682 | 
             
                config = config_element("", "", {
         | 
| 1521 1683 | 
             
                  "tag" => "tail",
         | 
| 1522 | 
            -
                  "path" => "#{ | 
| 1684 | 
            +
                  "path" => "#{@tmp_dir}/*.txt",
         | 
| 1523 1685 | 
             
                  "format" => "none",
         | 
| 1524 | 
            -
                  "pos_file" => "#{ | 
| 1686 | 
            +
                  "pos_file" => "#{@tmp_dir}/pos/tail.pos",
         | 
| 1525 1687 | 
             
                  "read_from_head" => true,
         | 
| 1526 1688 | 
             
                  "refresh_interval" => 1
         | 
| 1527 1689 | 
             
                })
         | 
| 1528 1690 |  | 
| 1529 | 
            -
                assert_path_not_exist("#{ | 
| 1691 | 
            +
                assert_path_not_exist("#{@tmp_dir}/pos")
         | 
| 1530 1692 | 
             
                d = create_driver(config, false)
         | 
| 1531 1693 | 
             
                d.run
         | 
| 1532 | 
            -
                assert_path_exist("#{ | 
| 1533 | 
            -
                assert_equal | 
| 1694 | 
            +
                assert_path_exist("#{@tmp_dir}/pos")
         | 
| 1695 | 
            +
                assert_equal('755', File.stat("#{@tmp_dir}/pos").mode.to_s(8)[-3, 3])
         | 
| 1534 1696 | 
             
              ensure
         | 
| 1535 | 
            -
                cleanup_directory( | 
| 1697 | 
            +
                cleanup_directory(@tmp_dir)
         | 
| 1536 1698 | 
             
              end
         | 
| 1537 1699 |  | 
| 1538 1700 | 
             
              def test_pos_file_dir_creation_with_system_dir_permission
         | 
| 1539 1701 | 
             
                config = config_element("", "", {
         | 
| 1540 1702 | 
             
                  "tag" => "tail",
         | 
| 1541 | 
            -
                  "path" => "#{ | 
| 1703 | 
            +
                  "path" => "#{@tmp_dir}/*.txt",
         | 
| 1542 1704 | 
             
                  "format" => "none",
         | 
| 1543 | 
            -
                  "pos_file" => "#{ | 
| 1705 | 
            +
                  "pos_file" => "#{@tmp_dir}/pos/tail.pos",
         | 
| 1544 1706 | 
             
                  "read_from_head" => true,
         | 
| 1545 1707 | 
             
                  "refresh_interval" => 1
         | 
| 1546 1708 | 
             
                })
         | 
| 1547 1709 |  | 
| 1548 | 
            -
                assert_path_not_exist("#{ | 
| 1710 | 
            +
                assert_path_not_exist("#{@tmp_dir}/pos")
         | 
| 1549 1711 |  | 
| 1550 1712 | 
             
                Fluent::SystemConfig.overwrite_system_config({ "dir_permission" => "744" }) do
         | 
| 1551 1713 | 
             
                  d = create_driver(config, false)
         | 
| 1552 1714 | 
             
                  d.run
         | 
| 1553 1715 | 
             
                end
         | 
| 1554 1716 |  | 
| 1555 | 
            -
                assert_path_exist("#{ | 
| 1717 | 
            +
                assert_path_exist("#{@tmp_dir}/pos")
         | 
| 1556 1718 | 
             
                if Fluent.windows?
         | 
| 1557 | 
            -
                  assert_equal | 
| 1719 | 
            +
                  assert_equal('755', File.stat("#{@tmp_dir}/pos").mode.to_s(8)[-3, 3])
         | 
| 1558 1720 | 
             
                else
         | 
| 1559 | 
            -
                  assert_equal | 
| 1721 | 
            +
                  assert_equal('744', File.stat("#{@tmp_dir}/pos").mode.to_s(8)[-3, 3])
         | 
| 1560 1722 | 
             
                end
         | 
| 1561 1723 | 
             
              ensure
         | 
| 1562 | 
            -
                cleanup_directory( | 
| 1724 | 
            +
                cleanup_directory(@tmp_dir)
         | 
| 1563 1725 | 
             
              end
         | 
| 1564 1726 |  | 
| 1565 1727 | 
             
              def test_z_refresh_watchers
         | 
| @@ -1568,7 +1730,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1568 1730 | 
             
                  create_target_info('test/plugin/data/log/foo/bar.log'),
         | 
| 1569 1731 | 
             
                  create_target_info('test/plugin/data/log/test.log'),
         | 
| 1570 1732 | 
             
                ]
         | 
| 1571 | 
            -
                plugin = create_driver( | 
| 1733 | 
            +
                plugin = create_driver(ex_config, false).instance
         | 
| 1572 1734 | 
             
                sio = StringIO.new
         | 
| 1573 1735 | 
             
                plugin.instance_eval do
         | 
| 1574 1736 | 
             
                  @pf = Fluent::Plugin::TailInput::PositionFile.load(sio, EX_FOLLOW_INODES, {}, logger: $log)
         | 
| @@ -1591,8 +1753,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1591 1753 | 
             
                end
         | 
| 1592 1754 |  | 
| 1593 1755 | 
             
                path = 'test/plugin/data/2010/01/20100102-030405.log'
         | 
| 1594 | 
            -
                 | 
| 1595 | 
            -
                mock.proxy(plugin).detach_watcher_after_rotate_wait(plugin.instance_variable_get(:@tails)[target_info], target_info.ino)
         | 
| 1756 | 
            +
                mock.proxy(plugin).detach_watcher_after_rotate_wait(plugin.instance_variable_get(:@tails)[path], Fluent::FileWrapper.stat(path).ino)
         | 
| 1596 1757 |  | 
| 1597 1758 | 
             
                Timecop.freeze(2010, 1, 2, 3, 4, 6) do
         | 
| 1598 1759 | 
             
                  path = "test/plugin/data/2010/01/20100102-030406.log"
         | 
| @@ -1612,9 +1773,9 @@ class TailInputTest < Test::Unit::TestCase | |
| 1612 1773 | 
             
                test 'type of pos_file_compaction_interval is time' do
         | 
| 1613 1774 | 
             
                  tail = {
         | 
| 1614 1775 | 
             
                    "tag" => "tail",
         | 
| 1615 | 
            -
                    "path" => "#{ | 
| 1776 | 
            +
                    "path" => "#{@tmp_dir}/*.txt",
         | 
| 1616 1777 | 
             
                    "format" => "none",
         | 
| 1617 | 
            -
                    "pos_file" => "#{ | 
| 1778 | 
            +
                    "pos_file" => "#{@tmp_dir}/pos/tail.pos",
         | 
| 1618 1779 | 
             
                    "refresh_interval" => 1,
         | 
| 1619 1780 | 
             
                    "read_from_head" => true,
         | 
| 1620 1781 | 
             
                    'pos_file_compaction_interval' => '24h',
         | 
| @@ -1631,7 +1792,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1631 1792 | 
             
                DummyWatcher = Struct.new("DummyWatcher", :tag)
         | 
| 1632 1793 |  | 
| 1633 1794 | 
             
                def test_tag
         | 
| 1634 | 
            -
                  d = create_driver( | 
| 1795 | 
            +
                  d = create_driver(ex_config, false)
         | 
| 1635 1796 | 
             
                  d.run {}
         | 
| 1636 1797 | 
             
                  plugin = d.instance
         | 
| 1637 1798 | 
             
                  mock(plugin.router).emit_stream('tail', anything).once
         | 
| @@ -1715,13 +1876,13 @@ class TailInputTest < Test::Unit::TestCase | |
| 1715 1876 | 
             
                test 'max_line_size' do |(label, size)|
         | 
| 1716 1877 | 
             
                  config = config_element("", "", {
         | 
| 1717 1878 | 
             
                                            "tag" => "max_line_size",
         | 
| 1718 | 
            -
                                            "path" => "#{ | 
| 1879 | 
            +
                                            "path" => "#{@tmp_dir}/with_long_lines.txt",
         | 
| 1719 1880 | 
             
                                            "format" => "none",
         | 
| 1720 1881 | 
             
                                            "read_from_head" => true,
         | 
| 1721 1882 | 
             
                                            "max_line_size" => label,
         | 
| 1722 1883 | 
             
                                            "log_level" => "debug"
         | 
| 1723 1884 | 
             
                                          })
         | 
| 1724 | 
            -
                  File.open("#{ | 
| 1885 | 
            +
                  File.open("#{@tmp_dir}/with_long_lines.txt", "w+") do |f|
         | 
| 1725 1886 | 
             
                    f.puts "foo"
         | 
| 1726 1887 | 
             
                    f.puts "x" * size # 'x' * size + \n > @max_line_size
         | 
| 1727 1888 | 
             
                    f.puts "bar"
         | 
| @@ -1747,7 +1908,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1747 1908 | 
             
              # Ensure that no fatal exception is raised when a file is missing and that
         | 
| 1748 1909 | 
             
              # files that do exist are still tailed as expected.
         | 
| 1749 1910 | 
             
              def test_missing_file
         | 
| 1750 | 
            -
                File.open("#{ | 
| 1911 | 
            +
                File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 1751 1912 | 
             
                  f.puts "test1"
         | 
| 1752 1913 | 
             
                  f.puts "test2"
         | 
| 1753 1914 | 
             
                }
         | 
| @@ -1756,16 +1917,16 @@ class TailInputTest < Test::Unit::TestCase | |
| 1756 1917 | 
             
                # since their interactions with the filesystem differ.
         | 
| 1757 1918 | 
             
                config1 = config_element("", "", {
         | 
| 1758 1919 | 
             
                                           "tag" => "t1",
         | 
| 1759 | 
            -
                                           "path" => "#{ | 
| 1920 | 
            +
                                           "path" => "#{@tmp_dir}/non_existent_file.txt,#{@tmp_dir}/tail.txt",
         | 
| 1760 1921 | 
             
                                           "format" => "none",
         | 
| 1761 1922 | 
             
                                           "rotate_wait" => "2s",
         | 
| 1762 | 
            -
                                           "pos_file" => "#{ | 
| 1923 | 
            +
                                           "pos_file" => "#{@tmp_dir}/tail.pos"
         | 
| 1763 1924 | 
             
                                         })
         | 
| 1764 1925 | 
             
                config2 = config1 + config_element("", "", { "read_from_head" => true })
         | 
| 1765 1926 | 
             
                [config1, config2].each do |config|
         | 
| 1766 1927 | 
             
                  d = create_driver(config, false)
         | 
| 1767 1928 | 
             
                  d.run(expect_emits: 1) do
         | 
| 1768 | 
            -
                    File.open("#{ | 
| 1929 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 1769 1930 | 
             
                      f.puts "test3"
         | 
| 1770 1931 | 
             
                      f.puts "test4"
         | 
| 1771 1932 | 
             
                    }
         | 
| @@ -1781,19 +1942,19 @@ class TailInputTest < Test::Unit::TestCase | |
| 1781 1942 |  | 
| 1782 1943 | 
             
              sub_test_case 'inode_processing' do
         | 
| 1783 1944 | 
             
                def test_should_delete_file_pos_entry_for_non_existing_file_with_follow_inodes
         | 
| 1784 | 
            -
                  config =  | 
| 1945 | 
            +
                  config = common_follow_inode_config
         | 
| 1785 1946 |  | 
| 1786 | 
            -
                  path = "#{ | 
| 1947 | 
            +
                  path = "#{@tmp_dir}/tail.txt"
         | 
| 1787 1948 | 
             
                  ino = 1
         | 
| 1788 1949 | 
             
                  pos = 1234
         | 
| 1789 | 
            -
                  File.open("#{ | 
| 1950 | 
            +
                  File.open("#{@tmp_dir}/tail.pos", "wb") {|f|
         | 
| 1790 1951 | 
             
                    f.puts ("%s\t%016x\t%016x\n" % [path, pos, ino])
         | 
| 1791 1952 | 
             
                  }
         | 
| 1792 1953 |  | 
| 1793 1954 | 
             
                  d = create_driver(config, false)
         | 
| 1794 1955 | 
             
                  d.run
         | 
| 1795 1956 |  | 
| 1796 | 
            -
                  pos_file = File.open("#{ | 
| 1957 | 
            +
                  pos_file = File.open("#{@tmp_dir}/tail.pos", "r")
         | 
| 1797 1958 | 
             
                  pos_file.pos = 0
         | 
| 1798 1959 |  | 
| 1799 1960 | 
             
                  assert_raise(EOFError) do
         | 
| @@ -1802,21 +1963,21 @@ class TailInputTest < Test::Unit::TestCase | |
| 1802 1963 | 
             
                end
         | 
| 1803 1964 |  | 
| 1804 1965 | 
             
                def test_should_write_latest_offset_after_rotate_wait
         | 
| 1805 | 
            -
                  config =  | 
| 1806 | 
            -
                  File.open("#{ | 
| 1966 | 
            +
                  config = common_follow_inode_config
         | 
| 1967 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 1807 1968 | 
             
                    f.puts "test1"
         | 
| 1808 1969 | 
             
                    f.puts "test2"
         | 
| 1809 1970 | 
             
                  }
         | 
| 1810 1971 |  | 
| 1811 1972 | 
             
                  d = create_driver(config, false)
         | 
| 1812 1973 | 
             
                  d.run(expect_emits: 2, shutdown: false) do
         | 
| 1813 | 
            -
                    File.open("#{ | 
| 1814 | 
            -
                    FileUtils.move("#{ | 
| 1974 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f| f.puts "test3\n"}
         | 
| 1975 | 
            +
                    FileUtils.move("#{@tmp_dir}/tail.txt", "#{@tmp_dir}/tail.txt" + "1")
         | 
| 1815 1976 | 
             
                    sleep 1
         | 
| 1816 | 
            -
                    File.open("#{ | 
| 1977 | 
            +
                    File.open("#{@tmp_dir}/tail.txt" + "1", "ab") {|f| f.puts "test4\n"}
         | 
| 1817 1978 | 
             
                  end
         | 
| 1818 1979 |  | 
| 1819 | 
            -
                  pos_file = File.open("#{ | 
| 1980 | 
            +
                  pos_file = File.open("#{@tmp_dir}/tail.pos", "r")
         | 
| 1820 1981 | 
             
                  pos_file.pos = 0
         | 
| 1821 1982 | 
             
                  line_parts = /^([^\t]+)\t([0-9a-fA-F]+)\t([0-9a-fA-F]+)/.match(pos_file.readline)
         | 
| 1822 1983 | 
             
                  waiting(5) {
         | 
| @@ -1833,16 +1994,16 @@ class TailInputTest < Test::Unit::TestCase | |
| 1833 1994 | 
             
                def test_should_remove_deleted_file
         | 
| 1834 1995 | 
             
                  config = config_element("", "", {"format" => "none"})
         | 
| 1835 1996 |  | 
| 1836 | 
            -
                  path = "#{ | 
| 1997 | 
            +
                  path = "#{@tmp_dir}/tail.txt"
         | 
| 1837 1998 | 
             
                  ino = 1
         | 
| 1838 1999 | 
             
                  pos = 1234
         | 
| 1839 | 
            -
                  File.open("#{ | 
| 2000 | 
            +
                  File.open("#{@tmp_dir}/tail.pos", "wb") {|f|
         | 
| 1840 2001 | 
             
                    f.puts ("%s\t%016x\t%016x\n" % [path, pos, ino])
         | 
| 1841 2002 | 
             
                  }
         | 
| 1842 2003 |  | 
| 1843 2004 | 
             
                  d = create_driver(config)
         | 
| 1844 2005 | 
             
                  d.run do
         | 
| 1845 | 
            -
                    pos_file = File.open("#{ | 
| 2006 | 
            +
                    pos_file = File.open("#{@tmp_dir}/tail.pos", "r")
         | 
| 1846 2007 | 
             
                    pos_file.pos = 0
         | 
| 1847 2008 | 
             
                    assert_equal([], pos_file.readlines)
         | 
| 1848 2009 | 
             
                  end
         | 
| @@ -1850,8 +2011,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 1850 2011 |  | 
| 1851 2012 | 
             
                def test_should_mark_file_unwatched_after_limit_recently_modified_and_rotate_wait
         | 
| 1852 2013 | 
             
                  config = config_element("ROOT", "", {
         | 
| 1853 | 
            -
                      "path" => "#{ | 
| 1854 | 
            -
                      "pos_file" => "#{ | 
| 2014 | 
            +
                      "path" => "#{@tmp_dir}/tail.txt*",
         | 
| 2015 | 
            +
                      "pos_file" => "#{@tmp_dir}/tail.pos",
         | 
| 1855 2016 | 
             
                      "tag" => "t1",
         | 
| 1856 2017 | 
             
                      "rotate_wait" => "1s",
         | 
| 1857 2018 | 
             
                      "refresh_interval" => "1s",
         | 
| @@ -1863,14 +2024,14 @@ class TailInputTest < Test::Unit::TestCase | |
| 1863 2024 |  | 
| 1864 2025 | 
             
                  d = create_driver(config, false)
         | 
| 1865 2026 |  | 
| 1866 | 
            -
                  File.open("#{ | 
| 2027 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 1867 2028 | 
             
                    f.puts "test1"
         | 
| 1868 2029 | 
             
                    f.puts "test2"
         | 
| 1869 2030 | 
             
                  }
         | 
| 1870 | 
            -
                  target_info = create_target_info("#{ | 
| 2031 | 
            +
                  target_info = create_target_info("#{@tmp_dir}/tail.txt")
         | 
| 1871 2032 |  | 
| 1872 2033 | 
             
                  d.run(expect_emits: 1, shutdown: false) do
         | 
| 1873 | 
            -
                    File.open("#{ | 
| 2034 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f| f.puts "test3\n"}
         | 
| 1874 2035 | 
             
                  end
         | 
| 1875 2036 |  | 
| 1876 2037 |  | 
| @@ -1888,8 +2049,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 1888 2049 |  | 
| 1889 2050 | 
             
                def test_should_read_from_head_on_file_renaming_with_star_in_pattern
         | 
| 1890 2051 | 
             
                  config = config_element("ROOT", "", {
         | 
| 1891 | 
            -
                      "path" => "#{ | 
| 1892 | 
            -
                      "pos_file" => "#{ | 
| 2052 | 
            +
                      "path" => "#{@tmp_dir}/tail.txt*",
         | 
| 2053 | 
            +
                      "pos_file" => "#{@tmp_dir}/tail.pos",
         | 
| 1893 2054 | 
             
                      "tag" => "t1",
         | 
| 1894 2055 | 
             
                      "rotate_wait" => "10s",
         | 
| 1895 2056 | 
             
                      "refresh_interval" => "1s",
         | 
| @@ -1901,14 +2062,14 @@ class TailInputTest < Test::Unit::TestCase | |
| 1901 2062 |  | 
| 1902 2063 | 
             
                  d = create_driver(config, false)
         | 
| 1903 2064 |  | 
| 1904 | 
            -
                  File.open("#{ | 
| 2065 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 1905 2066 | 
             
                    f.puts "test1"
         | 
| 1906 2067 | 
             
                    f.puts "test2"
         | 
| 1907 2068 | 
             
                  }
         | 
| 1908 2069 |  | 
| 1909 2070 | 
             
                  d.run(expect_emits: 2, shutdown: false) do
         | 
| 1910 | 
            -
                    File.open("#{ | 
| 1911 | 
            -
                    FileUtils.move("#{ | 
| 2071 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f| f.puts "test3\n"}
         | 
| 2072 | 
            +
                    FileUtils.move("#{@tmp_dir}/tail.txt", "#{@tmp_dir}/tail.txt1")
         | 
| 1912 2073 | 
             
                  end
         | 
| 1913 2074 |  | 
| 1914 2075 | 
             
                  events = d.events
         | 
| @@ -1917,20 +2078,20 @@ class TailInputTest < Test::Unit::TestCase | |
| 1917 2078 | 
             
                end
         | 
| 1918 2079 |  | 
| 1919 2080 | 
             
                def test_should_not_read_from_head_on_rotation_when_watching_inodes
         | 
| 1920 | 
            -
                  config =  | 
| 2081 | 
            +
                  config = common_follow_inode_config
         | 
| 1921 2082 |  | 
| 1922 2083 | 
             
                  d = create_driver(config, false)
         | 
| 1923 2084 |  | 
| 1924 | 
            -
                  File.open("#{ | 
| 2085 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 1925 2086 | 
             
                    f.puts "test1"
         | 
| 1926 2087 | 
             
                    f.puts "test2"
         | 
| 1927 2088 | 
             
                  }
         | 
| 1928 2089 |  | 
| 1929 2090 | 
             
                  d.run(expect_emits: 1, shutdown: false) do
         | 
| 1930 | 
            -
                    File.open("#{ | 
| 2091 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f| f.puts "test3\n"}
         | 
| 1931 2092 | 
             
                  end
         | 
| 1932 2093 |  | 
| 1933 | 
            -
                  FileUtils.move("#{ | 
| 2094 | 
            +
                  FileUtils.move("#{@tmp_dir}/tail.txt", "#{@tmp_dir}/tail.txt1")
         | 
| 1934 2095 | 
             
                  Timecop.travel(Time.now + 10) do
         | 
| 1935 2096 | 
             
                    sleep 2
         | 
| 1936 2097 | 
             
                    events = d.events
         | 
| @@ -1941,23 +2102,23 @@ class TailInputTest < Test::Unit::TestCase | |
| 1941 2102 | 
             
                end
         | 
| 1942 2103 |  | 
| 1943 2104 | 
             
                def test_should_mark_file_unwatched_if_same_name_file_created_with_different_inode
         | 
| 1944 | 
            -
                  config =  | 
| 2105 | 
            +
                  config = common_follow_inode_config
         | 
| 1945 2106 |  | 
| 1946 2107 | 
             
                  d = create_driver(config, false)
         | 
| 1947 2108 |  | 
| 1948 | 
            -
                  File.open("#{ | 
| 2109 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 1949 2110 | 
             
                    f.puts "test1"
         | 
| 1950 2111 | 
             
                    f.puts "test2"
         | 
| 1951 2112 | 
             
                  }
         | 
| 1952 | 
            -
                  target_info = create_target_info("#{ | 
| 2113 | 
            +
                  target_info = create_target_info("#{@tmp_dir}/tail.txt")
         | 
| 1953 2114 |  | 
| 1954 2115 | 
             
                  d.run(expect_emits: 2, shutdown: false) do
         | 
| 1955 | 
            -
                    File.open("#{ | 
| 1956 | 
            -
                    cleanup_file("#{ | 
| 1957 | 
            -
                    File.open("#{ | 
| 2116 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f| f.puts "test3\n"}
         | 
| 2117 | 
            +
                    cleanup_file("#{@tmp_dir}/tail.txt")
         | 
| 2118 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "wb") {|f| f.puts "test4\n"}
         | 
| 1958 2119 | 
             
                  end
         | 
| 1959 2120 |  | 
| 1960 | 
            -
                  new_target_info = create_target_info("#{ | 
| 2121 | 
            +
                  new_target_info = create_target_info("#{@tmp_dir}/tail.txt")
         | 
| 1961 2122 |  | 
| 1962 2123 | 
             
                  pos_file = d.instance.instance_variable_get(:@pf)
         | 
| 1963 2124 |  | 
| @@ -1973,7 +2134,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 1973 2134 |  | 
| 1974 2135 | 
             
                def test_should_close_watcher_after_rotate_wait
         | 
| 1975 2136 | 
             
                  now = Time.now
         | 
| 1976 | 
            -
                  config =  | 
| 2137 | 
            +
                  config = common_follow_inode_config + config_element('', '', {"rotate_wait" => "1s", "limit_recently_modified" => "1s"})
         | 
| 1977 2138 |  | 
| 1978 2139 | 
             
                  d = create_driver(config, false)
         | 
| 1979 2140 | 
             
                  d.instance.instance_eval do
         | 
| @@ -1986,52 +2147,52 @@ class TailInputTest < Test::Unit::TestCase | |
| 1986 2147 | 
             
                    @metrics = Fluent::Plugin::TailInput::MetricsInfo.new(opened_file_metrics, closed_file_metrics, rotated_file_metrics)
         | 
| 1987 2148 | 
             
                  end
         | 
| 1988 2149 |  | 
| 1989 | 
            -
                  File.open("#{ | 
| 2150 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 1990 2151 | 
             
                    f.puts "test1"
         | 
| 1991 2152 | 
             
                    f.puts "test2"
         | 
| 1992 2153 | 
             
                  }
         | 
| 1993 | 
            -
                  target_info = create_target_info("#{ | 
| 2154 | 
            +
                  target_info = create_target_info("#{@tmp_dir}/tail.txt")
         | 
| 1994 2155 | 
             
                  mock.proxy(Fluent::Plugin::TailInput::TailWatcher).new(target_info, anything, anything, true, true, anything, nil, anything, anything).once
         | 
| 1995 2156 | 
             
                  d.run(shutdown: false)
         | 
| 1996 | 
            -
                  assert d.instance.instance_variable_get(:@tails)[target_info]
         | 
| 2157 | 
            +
                  assert d.instance.instance_variable_get(:@tails)[target_info.path]
         | 
| 1997 2158 |  | 
| 1998 2159 | 
             
                  Timecop.travel(now + 10) do
         | 
| 1999 2160 | 
             
                    d.instance.instance_eval do
         | 
| 2000 | 
            -
                      sleep 0.1 until @tails[target_info] == nil
         | 
| 2161 | 
            +
                      sleep 0.1 until @tails[target_info.path] == nil
         | 
| 2001 2162 | 
             
                    end
         | 
| 2002 | 
            -
                    assert_nil d.instance.instance_variable_get(:@tails)[target_info]
         | 
| 2163 | 
            +
                    assert_nil d.instance.instance_variable_get(:@tails)[target_info.path]
         | 
| 2003 2164 | 
             
                  end
         | 
| 2004 2165 | 
             
                  d.instance_shutdown
         | 
| 2005 2166 | 
             
                end
         | 
| 2006 2167 |  | 
| 2007 2168 | 
             
                def test_should_create_new_watcher_for_new_file_with_same_name
         | 
| 2008 2169 | 
             
                  now = Time.now
         | 
| 2009 | 
            -
                  config =  | 
| 2170 | 
            +
                  config = common_follow_inode_config + config_element('', '', {"limit_recently_modified" => "2s"})
         | 
| 2010 2171 |  | 
| 2011 2172 | 
             
                  d = create_driver(config, false)
         | 
| 2012 2173 |  | 
| 2013 | 
            -
                  File.open("#{ | 
| 2174 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 2014 2175 | 
             
                    f.puts "test1"
         | 
| 2015 2176 | 
             
                    f.puts "test2"
         | 
| 2016 2177 | 
             
                  }
         | 
| 2017 | 
            -
                  path_ino = create_target_info("#{ | 
| 2178 | 
            +
                  path_ino = create_target_info("#{@tmp_dir}/tail.txt")
         | 
| 2018 2179 |  | 
| 2019 2180 | 
             
                  d.run(expect_emits: 1, shutdown: false) do
         | 
| 2020 | 
            -
                    File.open("#{ | 
| 2181 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f| f.puts "test3\n"}
         | 
| 2021 2182 | 
             
                  end
         | 
| 2022 2183 |  | 
| 2023 | 
            -
                  cleanup_file("#{ | 
| 2024 | 
            -
                  File.open("#{ | 
| 2184 | 
            +
                  cleanup_file("#{@tmp_dir}/tail.txt")
         | 
| 2185 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 2025 2186 | 
             
                    f.puts "test3"
         | 
| 2026 2187 | 
             
                    f.puts "test4"
         | 
| 2027 2188 | 
             
                  }
         | 
| 2028 | 
            -
                  new_path_ino = create_target_info("#{ | 
| 2189 | 
            +
                  new_path_ino = create_target_info("#{@tmp_dir}/tail.txt")
         | 
| 2029 2190 |  | 
| 2030 2191 | 
             
                  Timecop.travel(now + 10) do
         | 
| 2031 2192 | 
             
                    sleep 3
         | 
| 2032 2193 | 
             
                    d.instance.instance_eval do
         | 
| 2033 | 
            -
                      @tails[path_ino] == nil
         | 
| 2034 | 
            -
                      @tails[new_path_ino] != nil
         | 
| 2194 | 
            +
                      @tails[path_ino.path] == nil
         | 
| 2195 | 
            +
                      @tails[new_path_ino.path] != nil
         | 
| 2035 2196 | 
             
                    end
         | 
| 2036 2197 | 
             
                  end
         | 
| 2037 2198 |  | 
| @@ -2043,19 +2204,19 @@ class TailInputTest < Test::Unit::TestCase | |
| 2043 2204 | 
             
                end
         | 
| 2044 2205 |  | 
| 2045 2206 | 
             
                def test_truncate_file_with_follow_inodes
         | 
| 2046 | 
            -
                  config =  | 
| 2207 | 
            +
                  config = common_follow_inode_config
         | 
| 2047 2208 |  | 
| 2048 2209 | 
             
                  d = create_driver(config, false)
         | 
| 2049 2210 |  | 
| 2050 | 
            -
                  File.open("#{ | 
| 2211 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 2051 2212 | 
             
                    f.puts "test1"
         | 
| 2052 2213 | 
             
                    f.puts "test2"
         | 
| 2053 2214 | 
             
                  }
         | 
| 2054 2215 |  | 
| 2055 2216 | 
             
                  d.run(expect_emits: 3, shutdown: false) do
         | 
| 2056 | 
            -
                    File.open("#{ | 
| 2217 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f| f.puts "test3\n"}
         | 
| 2057 2218 | 
             
                    sleep 2
         | 
| 2058 | 
            -
                    File.open("#{ | 
| 2219 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "w+b") {|f| f.puts "test4\n"}
         | 
| 2059 2220 | 
             
                  end
         | 
| 2060 2221 |  | 
| 2061 2222 | 
             
                  events = d.events
         | 
| @@ -2069,15 +2230,15 @@ class TailInputTest < Test::Unit::TestCase | |
| 2069 2230 |  | 
| 2070 2231 | 
             
                # issue #3464
         | 
| 2071 2232 | 
             
                def test_should_replace_target_info
         | 
| 2072 | 
            -
                  File.open("#{ | 
| 2233 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 2073 2234 | 
             
                    f.puts "test1\n"
         | 
| 2074 2235 | 
             
                  }
         | 
| 2075 | 
            -
                  target_info = create_target_info("#{ | 
| 2236 | 
            +
                  target_info = create_target_info("#{@tmp_dir}/tail.txt")
         | 
| 2076 2237 | 
             
                  inodes = []
         | 
| 2077 2238 |  | 
| 2078 2239 | 
             
                  config = config_element("ROOT", "", {
         | 
| 2079 | 
            -
                                            "path" => "#{ | 
| 2080 | 
            -
                                            "pos_file" => "#{ | 
| 2240 | 
            +
                                            "path" => "#{@tmp_dir}/tail.txt*",
         | 
| 2241 | 
            +
                                            "pos_file" => "#{@tmp_dir}/tail.pos",
         | 
| 2081 2242 | 
             
                                            "tag" => "t1",
         | 
| 2082 2243 | 
             
                                            "refresh_interval" => "60s",
         | 
| 2083 2244 | 
             
                                            "read_from_head" => "true",
         | 
| @@ -2090,21 +2251,21 @@ class TailInputTest < Test::Unit::TestCase | |
| 2090 2251 | 
             
                    while d.events.size < 1 do
         | 
| 2091 2252 | 
             
                      sleep 0.1
         | 
| 2092 2253 | 
             
                    end
         | 
| 2093 | 
            -
                    inodes = d.instance.instance_variable_get(:@tails). | 
| 2094 | 
            -
                       | 
| 2254 | 
            +
                    inodes = d.instance.instance_variable_get(:@tails).values.collect do |tw|
         | 
| 2255 | 
            +
                      tw.ino
         | 
| 2095 2256 | 
             
                    end
         | 
| 2096 2257 | 
             
                    assert_equal([target_info.ino], inodes)
         | 
| 2097 2258 |  | 
| 2098 | 
            -
                    cleanup_file("#{ | 
| 2099 | 
            -
                    File.open("#{ | 
| 2259 | 
            +
                    cleanup_file("#{@tmp_dir}/tail.txt")
         | 
| 2260 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "wb") {|f| f.puts "test2\n"}
         | 
| 2100 2261 |  | 
| 2101 2262 | 
             
                    while d.events.size < 2 do
         | 
| 2102 2263 | 
             
                      sleep 0.1
         | 
| 2103 2264 | 
             
                    end
         | 
| 2104 | 
            -
                    inodes = d.instance.instance_variable_get(:@tails). | 
| 2105 | 
            -
                       | 
| 2265 | 
            +
                    inodes = d.instance.instance_variable_get(:@tails).values.collect do |tw|
         | 
| 2266 | 
            +
                      tw.ino
         | 
| 2106 2267 | 
             
                    end
         | 
| 2107 | 
            -
                    new_target_info = create_target_info("#{ | 
| 2268 | 
            +
                    new_target_info = create_target_info("#{@tmp_dir}/tail.txt")
         | 
| 2108 2269 | 
             
                    assert_not_equal(target_info.ino, new_target_info.ino)
         | 
| 2109 2270 | 
             
                    assert_equal([new_target_info.ino], inodes)
         | 
| 2110 2271 | 
             
                  end
         | 
| @@ -2113,7 +2274,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 2113 2274 |  | 
| 2114 2275 | 
             
              sub_test_case "tail_path" do
         | 
| 2115 2276 | 
             
                def test_tail_path_with_singleline
         | 
| 2116 | 
            -
                  File.open("#{ | 
| 2277 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") {|f|
         | 
| 2117 2278 | 
             
                    f.puts "test1"
         | 
| 2118 2279 | 
             
                    f.puts "test2"
         | 
| 2119 2280 | 
             
                  }
         | 
| @@ -2121,7 +2282,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 2121 2282 | 
             
                  d = create_driver(SINGLE_LINE_CONFIG + config_element("", "", { "path_key" => "path" }))
         | 
| 2122 2283 |  | 
| 2123 2284 | 
             
                  d.run(expect_emits: 1) do
         | 
| 2124 | 
            -
                    File.open("#{ | 
| 2285 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") {|f|
         | 
| 2125 2286 | 
             
                      f.puts "test3"
         | 
| 2126 2287 | 
             
                      f.puts "test4"
         | 
| 2127 2288 | 
             
                    }
         | 
| @@ -2130,12 +2291,12 @@ class TailInputTest < Test::Unit::TestCase | |
| 2130 2291 | 
             
                  events = d.events
         | 
| 2131 2292 | 
             
                  assert_equal(true, events.length > 0)
         | 
| 2132 2293 | 
             
                  events.each do |emit|
         | 
| 2133 | 
            -
                    assert_equal("#{ | 
| 2294 | 
            +
                    assert_equal("#{@tmp_dir}/tail.txt", emit[2]["path"])
         | 
| 2134 2295 | 
             
                  end
         | 
| 2135 2296 | 
             
                end
         | 
| 2136 2297 |  | 
| 2137 2298 | 
             
                def test_tail_path_with_multiline_with_firstline
         | 
| 2138 | 
            -
                  File.open("#{ | 
| 2299 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 2139 2300 |  | 
| 2140 2301 | 
             
                  config = config_element("", "", {
         | 
| 2141 2302 | 
             
                                            "path_key" => "path",
         | 
| @@ -2145,7 +2306,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 2145 2306 | 
             
                                          })
         | 
| 2146 2307 | 
             
                  d = create_driver(config)
         | 
| 2147 2308 | 
             
                  d.run(expect_emits: 1) do
         | 
| 2148 | 
            -
                    File.open("#{ | 
| 2309 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 2149 2310 | 
             
                      f.puts "f test1"
         | 
| 2150 2311 | 
             
                      f.puts "s test2"
         | 
| 2151 2312 | 
             
                      f.puts "f test3"
         | 
| @@ -2160,12 +2321,12 @@ class TailInputTest < Test::Unit::TestCase | |
| 2160 2321 | 
             
                  events = d.events
         | 
| 2161 2322 | 
             
                  assert_equal(4, events.length)
         | 
| 2162 2323 | 
             
                  events.each do |emit|
         | 
| 2163 | 
            -
                    assert_equal("#{ | 
| 2324 | 
            +
                    assert_equal("#{@tmp_dir}/tail.txt", emit[2]["path"])
         | 
| 2164 2325 | 
             
                  end
         | 
| 2165 2326 | 
             
                end
         | 
| 2166 2327 |  | 
| 2167 2328 | 
             
                def test_tail_path_with_multiline_without_firstline
         | 
| 2168 | 
            -
                  File.open("#{ | 
| 2329 | 
            +
                  File.open("#{@tmp_dir}/tail.txt", "wb") { |f| }
         | 
| 2169 2330 |  | 
| 2170 2331 | 
             
                  config = config_element("", "", {
         | 
| 2171 2332 | 
             
                                            "path_key" => "path",
         | 
| @@ -2176,7 +2337,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 2176 2337 | 
             
                                          })
         | 
| 2177 2338 | 
             
                  d = create_driver(config)
         | 
| 2178 2339 | 
             
                  d.run(expect_emits: 1) do
         | 
| 2179 | 
            -
                    File.open("#{ | 
| 2340 | 
            +
                    File.open("#{@tmp_dir}/tail.txt", "ab") { |f|
         | 
| 2180 2341 | 
             
                      f.puts "foo 1"
         | 
| 2181 2342 | 
             
                      f.puts "bar 1"
         | 
| 2182 2343 | 
             
                      f.puts "baz 1"
         | 
| @@ -2186,7 +2347,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 2186 2347 | 
             
                  events = d.events
         | 
| 2187 2348 | 
             
                  assert(events.length > 0)
         | 
| 2188 2349 | 
             
                  events.each do |emit|
         | 
| 2189 | 
            -
                    assert_equal("#{ | 
| 2350 | 
            +
                    assert_equal("#{@tmp_dir}/tail.txt", emit[2]["path"])
         | 
| 2190 2351 | 
             
                  end
         | 
| 2191 2352 | 
             
                end
         | 
| 2192 2353 |  | 
| @@ -2194,7 +2355,7 @@ class TailInputTest < Test::Unit::TestCase | |
| 2194 2355 | 
             
                  if ENV["APPVEYOR"] && Fluent.windows?
         | 
| 2195 2356 | 
             
                    omit "This testcase is unstable on AppVeyor."
         | 
| 2196 2357 | 
             
                  end
         | 
| 2197 | 
            -
                  files = ["#{ | 
| 2358 | 
            +
                  files = ["#{@tmp_dir}/tail1.txt", "#{@tmp_dir}/tail2.txt"]
         | 
| 2198 2359 | 
             
                  files.each { |file| File.open(file, "wb") { |f| } }
         | 
| 2199 2360 |  | 
| 2200 2361 | 
             
                  config = config_element("", "", {
         | 
| @@ -2228,30 +2389,30 @@ class TailInputTest < Test::Unit::TestCase | |
| 2228 2389 |  | 
| 2229 2390 | 
             
              def test_limit_recently_modified
         | 
| 2230 2391 | 
             
                now = Time.new(2010, 1, 2, 3, 4, 5)
         | 
| 2231 | 
            -
                FileUtils.touch("#{ | 
| 2232 | 
            -
                FileUtils.touch("#{ | 
| 2233 | 
            -
                FileUtils.touch("#{ | 
| 2392 | 
            +
                FileUtils.touch("#{@tmp_dir}/tail_unwatch.txt", mtime: (now - 3601))
         | 
| 2393 | 
            +
                FileUtils.touch("#{@tmp_dir}/tail_watch1.txt", mtime: (now - 3600))
         | 
| 2394 | 
            +
                FileUtils.touch("#{@tmp_dir}/tail_watch2.txt", mtime: now)
         | 
| 2234 2395 |  | 
| 2235 2396 | 
             
                config = config_element('', '', {
         | 
| 2236 2397 | 
             
                  'tag' => 'tail',
         | 
| 2237 | 
            -
                  'path' => "#{ | 
| 2398 | 
            +
                  'path' => "#{@tmp_dir}/*.txt",
         | 
| 2238 2399 | 
             
                  'format' => 'none',
         | 
| 2239 2400 | 
             
                  'limit_recently_modified' => '3600s'
         | 
| 2240 2401 | 
             
                })
         | 
| 2241 2402 |  | 
| 2242 2403 | 
             
                expected_files = [
         | 
| 2243 | 
            -
                  create_target_info("#{ | 
| 2244 | 
            -
                  create_target_info("#{ | 
| 2404 | 
            +
                  create_target_info("#{@tmp_dir}/tail_watch1.txt"),
         | 
| 2405 | 
            +
                  create_target_info("#{@tmp_dir}/tail_watch2.txt")
         | 
| 2245 2406 | 
             
                ]
         | 
| 2246 2407 |  | 
| 2247 2408 | 
             
                Timecop.freeze(now) do
         | 
| 2248 2409 | 
             
                  plugin = create_driver(config, false).instance
         | 
| 2249 | 
            -
                  assert_equal | 
| 2410 | 
            +
                  assert_equal(expected_files, plugin.expand_paths.values.sort_by { |path_ino| path_ino.path })
         | 
| 2250 2411 | 
             
                end
         | 
| 2251 2412 | 
             
              end
         | 
| 2252 2413 |  | 
| 2253 2414 | 
             
              def test_skip_refresh_on_startup
         | 
| 2254 | 
            -
                FileUtils.touch("#{ | 
| 2415 | 
            +
                FileUtils.touch("#{@tmp_dir}/tail.txt")
         | 
| 2255 2416 | 
             
                config = config_element('', '', {
         | 
| 2256 2417 | 
             
                                          'format' => 'none',
         | 
| 2257 2418 | 
             
                                          'refresh_interval' => 1,
         | 
| @@ -2259,37 +2420,42 @@ class TailInputTest < Test::Unit::TestCase | |
| 2259 2420 | 
             
                                        })
         | 
| 2260 2421 | 
             
                d = create_driver(config)
         | 
| 2261 2422 | 
             
                d.run(shutdown: false) {}
         | 
| 2262 | 
            -
                assert_equal | 
| 2423 | 
            +
                assert_equal(0, d.instance.instance_variable_get(:@tails).keys.size)
         | 
| 2263 2424 | 
             
                # detect a file at first execution of in_tail_refresh_watchers timer
         | 
| 2264 2425 | 
             
                waiting(5) { sleep 0.1 until d.instance.instance_variable_get(:@tails).keys.size == 1 }
         | 
| 2265 2426 | 
             
                d.instance_shutdown
         | 
| 2266 2427 | 
             
              end
         | 
| 2267 2428 |  | 
| 2268 2429 | 
             
              def test_ENOENT_error_after_setup_watcher
         | 
| 2269 | 
            -
                path = "#{ | 
| 2430 | 
            +
                path = "#{@tmp_dir}/tail.txt"
         | 
| 2270 2431 | 
             
                FileUtils.touch(path)
         | 
| 2271 2432 | 
             
                config = config_element('', '', {
         | 
| 2272 2433 | 
             
                                          'format' => 'none',
         | 
| 2273 2434 | 
             
                                        })
         | 
| 2274 2435 | 
             
                d = create_driver(config)
         | 
| 2275 | 
            -
                 | 
| 2276 | 
            -
             | 
| 2277 | 
            -
                   | 
| 2278 | 
            -
             | 
| 2436 | 
            +
                file_deleted = false
         | 
| 2437 | 
            +
                mock.proxy(d.instance).existence_path do |hash|
         | 
| 2438 | 
            +
                  unless file_deleted
         | 
| 2439 | 
            +
                    cleanup_file(path)
         | 
| 2440 | 
            +
                    file_deleted = true
         | 
| 2441 | 
            +
                  end
         | 
| 2442 | 
            +
                  hash
         | 
| 2443 | 
            +
                end.twice
         | 
| 2279 2444 | 
             
                assert_nothing_raised do
         | 
| 2280 2445 | 
             
                  d.run(shutdown: false) {}
         | 
| 2281 2446 | 
             
                end
         | 
| 2282 | 
            -
                assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed | 
| 2447 | 
            +
                assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed. Continuing without tailing it.\n") },
         | 
| 2448 | 
            +
                       $log.out.logs.join("\n"))
         | 
| 2283 2449 | 
             
              ensure
         | 
| 2284 2450 | 
             
                d.instance_shutdown if d && d.instance
         | 
| 2285 2451 | 
             
              end
         | 
| 2286 2452 |  | 
| 2287 2453 | 
             
              def test_EACCES_error_after_setup_watcher
         | 
| 2288 2454 | 
             
                omit "Cannot test with root user" if Process::UID.eid == 0
         | 
| 2289 | 
            -
                path = "#{ | 
| 2455 | 
            +
                path = "#{@tmp_dir}/noaccess/tail.txt"
         | 
| 2290 2456 | 
             
                begin
         | 
| 2291 | 
            -
                  FileUtils.mkdir_p("#{ | 
| 2292 | 
            -
                  FileUtils.chmod(0755, "#{ | 
| 2457 | 
            +
                  FileUtils.mkdir_p("#{@tmp_dir}/noaccess")
         | 
| 2458 | 
            +
                  FileUtils.chmod(0755, "#{@tmp_dir}/noaccess")
         | 
| 2293 2459 | 
             
                  FileUtils.touch(path)
         | 
| 2294 2460 | 
             
                  config = config_element('', '', {
         | 
| 2295 2461 | 
             
                                            'tag' => "tail",
         | 
| @@ -2297,25 +2463,26 @@ class TailInputTest < Test::Unit::TestCase | |
| 2297 2463 | 
             
                                            'format' => 'none',
         | 
| 2298 2464 | 
             
                                          })
         | 
| 2299 2465 | 
             
                  d = create_driver(config, false)
         | 
| 2300 | 
            -
                  mock.proxy(d.instance). | 
| 2301 | 
            -
                    FileUtils.chmod(0000, "#{ | 
| 2302 | 
            -
                     | 
| 2303 | 
            -
                  end
         | 
| 2466 | 
            +
                  mock.proxy(d.instance).existence_path do |hash|
         | 
| 2467 | 
            +
                    FileUtils.chmod(0000, "#{@tmp_dir}/noaccess")
         | 
| 2468 | 
            +
                    hash
         | 
| 2469 | 
            +
                  end.twice
         | 
| 2304 2470 | 
             
                  assert_nothing_raised do
         | 
| 2305 2471 | 
             
                    d.run(shutdown: false) {}
         | 
| 2306 2472 | 
             
                  end
         | 
| 2307 | 
            -
                  assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed | 
| 2473 | 
            +
                  assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed. Continuing without tailing it.\n") },
         | 
| 2474 | 
            +
                         $log.out.logs.join("\n"))
         | 
| 2308 2475 | 
             
                end
         | 
| 2309 2476 | 
             
              ensure
         | 
| 2310 2477 | 
             
                d.instance_shutdown if d && d.instance
         | 
| 2311 | 
            -
                if File.exist?("#{ | 
| 2312 | 
            -
                  FileUtils.chmod(0755, "#{ | 
| 2313 | 
            -
                  FileUtils.rm_rf("#{ | 
| 2478 | 
            +
                if File.exist?("#{@tmp_dir}/noaccess")
         | 
| 2479 | 
            +
                  FileUtils.chmod(0755, "#{@tmp_dir}/noaccess")
         | 
| 2480 | 
            +
                  FileUtils.rm_rf("#{@tmp_dir}/noaccess")
         | 
| 2314 2481 | 
             
                end
         | 
| 2315 2482 | 
             
              end unless Fluent.windows?
         | 
| 2316 2483 |  | 
| 2317 2484 | 
             
              def test_EACCES
         | 
| 2318 | 
            -
                path = "#{ | 
| 2485 | 
            +
                path = "#{@tmp_dir}/tail.txt"
         | 
| 2319 2486 | 
             
                FileUtils.touch(path)
         | 
| 2320 2487 | 
             
                config = config_element('', '', {
         | 
| 2321 2488 | 
             
                                          'format' => 'none',
         | 
| @@ -2333,8 +2500,8 @@ class TailInputTest < Test::Unit::TestCase | |
| 2333 2500 | 
             
              end
         | 
| 2334 2501 |  | 
| 2335 2502 | 
             
              def test_shutdown_timeout
         | 
| 2336 | 
            -
                 | 
| 2337 | 
            -
             | 
| 2503 | 
            +
                File.open("#{@tmp_dir}/tail.txt", "wb") do |f|
         | 
| 2504 | 
            +
                  # Should be large enough to take too long time to consume
         | 
| 2338 2505 | 
             
                  (1024 * 1024 * 5).times do
         | 
| 2339 2506 | 
             
                    f.puts "{\"test\":\"fizzbuzz\"}"
         | 
| 2340 2507 | 
             
                  end
         | 
| @@ -2346,18 +2513,127 @@ class TailInputTest < Test::Unit::TestCase | |
| 2346 2513 | 
             
                                          'format' => 'json',
         | 
| 2347 2514 | 
             
                                          'skip_refresh_on_startup' => true,
         | 
| 2348 2515 | 
             
                                        })
         | 
| 2516 | 
            +
                shutdown_start_time = 0
         | 
| 2517 | 
            +
             | 
| 2349 2518 | 
             
                d = create_driver(config)
         | 
| 2350 2519 | 
             
                mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
         | 
| 2520 | 
            +
                  mock.proxy(io_handler).ready_to_shutdown(anything) do
         | 
| 2521 | 
            +
                    shutdown_start_time = Fluent::Clock.now
         | 
| 2522 | 
            +
                  end
         | 
| 2351 2523 | 
             
                  io_handler.shutdown_timeout = 0.5
         | 
| 2352 2524 | 
             
                  io_handler
         | 
| 2353 2525 | 
             
                end
         | 
| 2354 2526 |  | 
| 2355 | 
            -
                start_time = Fluent::Clock.now
         | 
| 2356 2527 | 
             
                assert_nothing_raised do
         | 
| 2357 2528 | 
             
                  d.run(expect_emits: 1)
         | 
| 2358 2529 | 
             
                end
         | 
| 2359 2530 |  | 
| 2360 | 
            -
                elapsed = Fluent::Clock.now -  | 
| 2361 | 
            -
                assert_true(elapsed > 0.5 && elapsed < 2. | 
| 2531 | 
            +
                elapsed = Fluent::Clock.now - shutdown_start_time
         | 
| 2532 | 
            +
                assert_true(elapsed > 0.5 && elapsed < 2.0,
         | 
| 2533 | 
            +
                            "elapsed time: #{elapsed}")
         | 
| 2534 | 
            +
              end
         | 
| 2535 | 
            +
             | 
| 2536 | 
            +
              sub_test_case "throttling logs at in_tail level" do
         | 
| 2537 | 
            +
                data("file test1.log no_limit 5120 text: msg" => ["test1.log", 5120, "msg"],
         | 
| 2538 | 
            +
                     "file test2.log no_limit 1024 text: test" => ["test2.log", 1024, "test"])
         | 
| 2539 | 
            +
                def test_lines_collected_with_no_throttling(data)
         | 
| 2540 | 
            +
                  file, num_lines, msg = data
         | 
| 2541 | 
            +
             | 
| 2542 | 
            +
                  pattern = "/^#{@tmp_dir}\/(?<file>.+)\.log$/"
         | 
| 2543 | 
            +
                  rule = create_rule_directive({
         | 
| 2544 | 
            +
                    "file" => "/test.*/",
         | 
| 2545 | 
            +
                  }, -1)
         | 
| 2546 | 
            +
                  group = create_group_directive(pattern, "1s", rule)
         | 
| 2547 | 
            +
                  path_element = create_path_element(file)
         | 
| 2548 | 
            +
             | 
| 2549 | 
            +
                  conf = ROOT_CONFIG + group + path_element + CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG
         | 
| 2550 | 
            +
             | 
| 2551 | 
            +
                  File.open("#{@tmp_dir}/#{file}", 'wb') do |f|
         | 
| 2552 | 
            +
                    num_lines.times do
         | 
| 2553 | 
            +
                      f.puts "#{msg}\n"
         | 
| 2554 | 
            +
                    end
         | 
| 2555 | 
            +
                  end
         | 
| 2556 | 
            +
             | 
| 2557 | 
            +
             | 
| 2558 | 
            +
                  d = create_driver(conf, false)
         | 
| 2559 | 
            +
                  d.run(timeout: 3) do
         | 
| 2560 | 
            +
                    start_time = Fluent::Clock.now
         | 
| 2561 | 
            +
             | 
| 2562 | 
            +
                    assert_equal(num_lines, d.record_count)
         | 
| 2563 | 
            +
                    assert_equal({ "message" => msg }, d.events[0][2])
         | 
| 2564 | 
            +
             | 
| 2565 | 
            +
                    prev_count = d.record_count
         | 
| 2566 | 
            +
                    sleep(0.1) while d.emit_count < 1
         | 
| 2567 | 
            +
                    assert_true(Fluent::Clock.now - start_time < 2)
         | 
| 2568 | 
            +
                    ## after waiting for 1 (+ jitter) secs, limit will reset
         | 
| 2569 | 
            +
                    ## Plugin will start reading but it will encounter EOF Error
         | 
| 2570 | 
            +
                    ## since no logs are left to be read
         | 
| 2571 | 
            +
                    ## Hence, d.record_count = prev_count
         | 
| 2572 | 
            +
                    tail_watcher_interval = 1.0 # hard coded value in in_tail
         | 
| 2573 | 
            +
                    safety_ratio = 1.2
         | 
| 2574 | 
            +
                    jitter = tail_watcher_interval * safety_ratio
         | 
| 2575 | 
            +
                    sleep(1.0 + jitter)
         | 
| 2576 | 
            +
                    assert_equal(0, d.record_count - prev_count)
         | 
| 2577 | 
            +
                  end
         | 
| 2578 | 
            +
                end
         | 
| 2579 | 
            +
             | 
| 2580 | 
            +
                test "lines collected with throttling" do
         | 
| 2581 | 
            +
                  file = "podname1_namespace12_container-123456.log"
         | 
| 2582 | 
            +
                  limit = 1000
         | 
| 2583 | 
            +
                  rate_period = 2
         | 
| 2584 | 
            +
                  num_lines = 3000
         | 
| 2585 | 
            +
                  msg = "a" * 8190 # Total size = 8190 bytes + 2 (\n) bytes
         | 
| 2586 | 
            +
             | 
| 2587 | 
            +
                  rule = create_rule_directive({
         | 
| 2588 | 
            +
                    "namespace"=> "/namespace.+/",
         | 
| 2589 | 
            +
                    "podname"=> "/podname.+/",
         | 
| 2590 | 
            +
                  }, limit)
         | 
| 2591 | 
            +
                  path_element = create_path_element(file)
         | 
| 2592 | 
            +
                  conf = ROOT_CONFIG + create_group_directive(tailing_group_pattern, "#{rate_period}s", rule) + path_element + SINGLE_LINE_CONFIG + CONFIG_READ_FROM_HEAD
         | 
| 2593 | 
            +
             | 
| 2594 | 
            +
                  d = create_driver(conf, false)
         | 
| 2595 | 
            +
                  file_path = "#{@tmp_dir}/#{file}"
         | 
| 2596 | 
            +
             | 
| 2597 | 
            +
                  File.open(file_path, 'wb') do |f|
         | 
| 2598 | 
            +
                    num_lines.times do
         | 
| 2599 | 
            +
                      f.puts msg
         | 
| 2600 | 
            +
                    end
         | 
| 2601 | 
            +
                  end
         | 
| 2602 | 
            +
             | 
| 2603 | 
            +
                  d.run(timeout: 15) do
         | 
| 2604 | 
            +
                    sleep_interval = 0.1
         | 
| 2605 | 
            +
                    tail_watcher_interval = 1.0 # hard coded value in in_tail
         | 
| 2606 | 
            +
                    safety_ratio = 1.2
         | 
| 2607 | 
            +
                    lower_jitter = sleep_interval * safety_ratio
         | 
| 2608 | 
            +
                    upper_jitter = (tail_watcher_interval + sleep_interval) * safety_ratio
         | 
| 2609 | 
            +
                    lower_interval = rate_period - lower_jitter
         | 
| 2610 | 
            +
                    upper_interval = rate_period + upper_jitter
         | 
| 2611 | 
            +
             | 
| 2612 | 
            +
                    emit_count = 0
         | 
| 2613 | 
            +
                    prev_count = 0
         | 
| 2614 | 
            +
             | 
| 2615 | 
            +
                    while emit_count < 3 do
         | 
| 2616 | 
            +
                      start_time = Fluent::Clock.now
         | 
| 2617 | 
            +
                      sleep(sleep_interval) while d.emit_count <= emit_count
         | 
| 2618 | 
            +
                      elapsed_seconds = Fluent::Clock.now - start_time
         | 
| 2619 | 
            +
                      if emit_count > 0
         | 
| 2620 | 
            +
                        assert_true(elapsed_seconds > lower_interval && elapsed_seconds < upper_interval,
         | 
| 2621 | 
            +
                                    "elapsed_seconds #{elapsed_seconds} is out of allowed range:\n" +
         | 
| 2622 | 
            +
                                    "  lower: #{lower_interval} [sec]\n" +
         | 
| 2623 | 
            +
                                    "  upper: #{upper_interval} [sec]")
         | 
| 2624 | 
            +
                      end
         | 
| 2625 | 
            +
                      assert_equal(limit, d.record_count - prev_count)
         | 
| 2626 | 
            +
                      emit_count = d.emit_count
         | 
| 2627 | 
            +
                      prev_count = d.record_count
         | 
| 2628 | 
            +
                    end
         | 
| 2629 | 
            +
             | 
| 2630 | 
            +
                    ## When all the lines are read and rate_period seconds are over
         | 
| 2631 | 
            +
                    ## limit will reset and since there are no more logs to be read,
         | 
| 2632 | 
            +
                    ## number_lines_read will be 0
         | 
| 2633 | 
            +
                    sleep upper_interval
         | 
| 2634 | 
            +
                    gw = d.instance.find_group_from_metadata(file_path)
         | 
| 2635 | 
            +
                    assert_equal(0, gw.current_paths[file_path].number_lines_read)
         | 
| 2636 | 
            +
                  end
         | 
| 2637 | 
            +
                end
         | 
| 2362 2638 | 
             
              end
         | 
| 2363 2639 | 
             
            end
         |