Skip to content

Commit

Permalink
Merge pull request #3325 from ashie/fix-incorrect-win32-error
Browse files Browse the repository at this point in the history
WindowsFile: Fix incorrect error message
  • Loading branch information
kenhys authored Apr 13, 2021
2 parents 4b1ee63 + 780e741 commit 9b756ef
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 2 deletions.
32 changes: 30 additions & 2 deletions lib/fluent/plugin/file_wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,34 @@ def s.ino; @ino; end
end
end

class Win32Error < StandardError
require 'windows/error'
include Windows::Error

attr_reader :errcode

def initialize(errcode)
@errcode = errcode
end

def format_english_message(errcode)
buf = 0.chr * 260
flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY
english_lang_id = 1033 # The result of MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
FormatMessageA.call(flags, 0, errcode, english_lang_id, buf, buf.size, 0)
buf.force_encoding(Encoding.default_external).strip
end

def message
"code: #{@errcode}, #{format_english_message(@errcode)}"
end

def ==(other)
return false if other.class != Win32Error
@errcode == other.errcode
end
end

# To open and get stat with setting FILE_SHARE_DELETE
class WindowsFile
require 'windows/file'
Expand Down Expand Up @@ -79,9 +107,9 @@ def initialize(path, mode='r', sharemode=FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_S
if @file_handle == INVALID_HANDLE_VALUE
err = GetLastError.call
if err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND || err == ERROR_ACCESS_DENIED
raise SystemCallError.new(2)
raise Errno::ENOENT
end
raise SystemCallError.new(err)
raise Win32Error.new(err)
end
end

Expand Down
84 changes: 84 additions & 0 deletions test/plugin/test_file_wrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require_relative '../helper'
require 'fluent/plugin/file_wrapper'

class FileWrapperTest < Test::Unit::TestCase
require 'windows/file'
require 'windows/error'
include Windows::File
include Windows::Error

TMP_DIR = File.dirname(__FILE__) + "/../tmp/file_wrapper#{ENV['TEST_ENV_NUMBER']}"

def setup
FileUtils.mkdir_p(TMP_DIR)
end

def teardown
FileUtils.rm_rf(TMP_DIR)
end

sub_test_case 'Win32Error' do
test 'equal' do
assert_equal(Fluent::Win32Error.new(ERROR_SHARING_VIOLATION),
Fluent::Win32Error.new(ERROR_SHARING_VIOLATION))
end

test 'different error code' do
assert_not_equal(Fluent::Win32Error.new(ERROR_FILE_NOT_FOUND),
Fluent::Win32Error.new(ERROR_SHARING_VIOLATION))
end

test 'different class' do
assert_not_equal(Errno::EPIPE,
Fluent::Win32Error.new(ERROR_SHARING_VIOLATION))
end

test 'ERROR_SHARING_VIOLATION message' do
assert_equal(Fluent::Win32Error.new(ERROR_SHARING_VIOLATION).message,
"code: 32, The process cannot access the file because it is being used by another process.")
end
end

sub_test_case 'WindowsFile exceptions' do
test 'nothing raised' do
begin
path = "#{TMP_DIR}/test_windows_file.txt"
file1 = file2 = nil
file1 = File.open(path, "wb") do |f|
end
assert_nothing_raised do
file2 = Fluent::WindowsFile.new(path)
ensure
file2.close
end
ensure
file1.close if file1
end
end

test 'Errno::ENOENT raised' do
path = "#{TMP_DIR}/nofile.txt"
file = nil
assert_raise(Errno::ENOENT) do
file = Fluent::WindowsFile.new(path)
ensure
file.close if file
end
end

test 'ERROR_SHARING_VIOLATION raised' do
begin
path = "#{TMP_DIR}/test_windows_file.txt"
file1 = file2 = nil
file1 = File.open(path, "wb")
assert_raise(Fluent::Win32Error.new(ERROR_SHARING_VIOLATION)) do
file2 = Fluent::WindowsFile.new(path, 'r', FILE_SHARE_READ)
ensure
file2.close if file2
end
ensure
file1.close if file1
end
end
end
end if Fluent.windows?

0 comments on commit 9b756ef

Please sign in to comment.