Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5a42ddc
Replace usage of `Errno` with `IO::FileSystemError` for fs operations
waj Feb 19, 2020
8690d2a
Replace some untested occurrences of `Errno` in file system functions
waj Feb 19, 2020
80e53b1
Renamed IO::FileSystemError -> File::Error
waj Feb 21, 2020
a541b6d
Removed exception re-raise at `File.size`
waj Feb 21, 2020
28fdabd
Refactor `File::Error.from_errno` into `Exception.from_errno`
waj Feb 21, 2020
4ee40f6
Socket::Error: it now extends IO::Error
waj Feb 26, 2020
f7b28ab
Replaced all occurrences of Errno by Socket::Error in socket classes
waj Feb 27, 2020
7cdaece
Introduce RuntimeError. Used for iconv errors.
waj Feb 27, 2020
e2f7195
Use RuntimeError within Process class
waj Feb 27, 2020
8d267ec
Replaced all occurrences of Errno exceptions by RuntimeError and some…
waj Mar 4, 2020
2feb466
Fixing Windows specs. Raising exceptions from WinError codes.
waj Mar 4, 2020
d25f5da
Replaced WinError raised objects by calls to `from_winerror`
waj Mar 5, 2020
da47b83
Replaced some remaining `rescue Errno` by the corresponding class
waj Mar 5, 2020
eb39225
Don't rescue Errno anymore
waj Mar 5, 2020
e9bb43f
Socket#send raises Socket::ConnectError for ECONNREFUSED
waj Mar 5, 2020
e43e73d
expect_raises_errno helper not needed anymore
waj Mar 5, 2020
4164afe
Errno and WinError are now enums
waj Mar 5, 2020
f54a8f2
Remove unnecessary usage of Errno
waj Mar 5, 2020
f320a4b
Updated some comments regarding Errno
waj Mar 5, 2020
d6e2eb5
Save the `os_error` within the exception
waj Mar 5, 2020
c464ec8
Fix specs in Windows: re-add special exception when a fd is not opene…
waj Mar 5, 2020
130a066
Rename IO::Timeout -> IO::TimeoutError
waj Mar 5, 2020
73f1776
Add File::Error subclasses: File::AlreadyExistsError and File::Access…
waj Mar 6, 2020
c3786ec
Map EADDRINUSE to Socket::BindError
waj Mar 6, 2020
99a3a66
Use WinError#to_errno by default to construct exceptions from WinError
waj Mar 6, 2020
1605a0a
Refactor `from_errno` and `from_winerror` into a separate module (Sys…
waj Mar 6, 2020
1f6bc58
IO::TimeoutError extends IO::Error
waj Mar 6, 2020
e8e584a
Bring back Socket#bind(Socket::Address) to the public
waj Mar 6, 2020
3e97f0c
Reuse WinError value
waj Mar 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions spec/std/dir_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require "./spec_helper"
require "../support/errno"

private def unset_tempdir
{% if flag?(:windows) %}
Expand Down Expand Up @@ -63,14 +62,14 @@ describe "Dir" do
end

it "tests empty? on nonexistent directory" do
expect_raises_errno(Errno::ENOENT, "Error determining size of '#{datapath("foo", "bar")}'") do
expect_raises(File::NotFoundError, "Error opening directory: '#{datapath("foo", "bar").inspect_unquoted}'") do
Dir.empty?(datapath("foo", "bar"))
end
end

# TODO: do we even want this?
pending_win32 "tests empty? on a directory path to a file" do
expect_raises_errno(Errno::ENOTDIR, "Error determining size of '#{datapath("dir", "f1.txt", "/")}'") do
expect_raises(File::Error, "Error opening directory: '#{datapath("dir", "f1.txt", "/").inspect_unquoted}'") do
Dir.empty?(datapath("dir", "f1.txt", "/"))
end
end
Expand All @@ -86,7 +85,7 @@ describe "Dir" do
end

it "tests mkdir with an existing path" do
expect_raises_errno(Errno::EEXIST, "Unable to create directory '#{datapath}'") do
expect_raises(File::AlreadyExistsError, "Unable to create directory: '#{datapath.inspect_unquoted}'") do
Dir.mkdir(datapath, 0o700)
end
end
Expand All @@ -104,7 +103,7 @@ describe "Dir" do

context "path exists" do
it "fails when path is a file" do
expect_raises_errno(Errno::EEXIST, "Unable to create directory '#{datapath("test_file.txt")}': File exists") do
expect_raises(File::AlreadyExistsError, "Unable to create directory: '#{datapath("test_file.txt").inspect_unquoted}': File exists") do
Dir.mkdir_p(datapath("test_file.txt"))
end
end
Expand All @@ -119,14 +118,14 @@ describe "Dir" do

it "tests rmdir with an nonexistent path" do
with_tempfile("nonexistant") do |path|
expect_raises_errno(Errno::ENOENT, "Unable to remove directory '#{path}'") do
expect_raises(File::NotFoundError, "Unable to remove directory: '#{path.inspect_unquoted}'") do
Dir.rmdir(path)
end
end
end

it "tests rmdir with a path that cannot be removed" do
expect_raises_errno(Errno::ENOTEMPTY, "Unable to remove directory '#{datapath}'") do
expect_raises(File::Error, "Unable to remove directory: '#{datapath.inspect_unquoted}'") do
Dir.rmdir(datapath)
end
end
Expand Down Expand Up @@ -372,7 +371,7 @@ describe "Dir" do
end

it "raises" do
expect_raises_errno(Errno::ENOENT, {{ flag?(:win32) ? /SetCurrentDirectory: .* No such file or directory/ : "Error while changing directory to '/nope'" }}) do
expect_raises(File::NotFoundError, "Error while changing directory: '/nope'") do
Dir.cd("/nope")
end
end
Expand Down
3 changes: 1 addition & 2 deletions spec/std/file/tempfile_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require "../spec_helper"
require "../../support/errno"

describe File do
describe ".tempname" do
Expand Down Expand Up @@ -86,7 +85,7 @@ describe File do
end

it "fails in unwritable folder" do
expect_raises_errno(Errno::ENOENT, "mkstemp: '#{datapath("non-existing-folder")}/") do
expect_raises(File::NotFoundError, "Error creating temporary file: '#{datapath("non-existing-folder")}/") do
File.tempfile dir: datapath("non-existing-folder")
end
end
Expand Down
41 changes: 24 additions & 17 deletions spec/std/file_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require "./spec_helper"
require "../support/errno"

private def base
Dir.current
Expand Down Expand Up @@ -106,14 +105,14 @@ describe "File" do

it "raises an error when the file does not exist" do
filename = datapath("non_existing_file.txt")
expect_raises_errno(Errno::ENOENT, "Error determining size of '#{filename}'") do
expect_raises(File::NotFoundError, "Unable to get file info: '#{filename}'") do
File.empty?(filename)
end
end

# TODO: do we even want this?
pending_win32 "raises an error when a component of the path is a file" do
expect_raises_errno(Errno::ENOTDIR, "Error determining size of '#{datapath("test_file.txt", "")}'") do
expect_raises(File::Error, "Unable to get file info: '#{datapath("test_file.txt", "")}'") do
File.empty?(datapath("test_file.txt", ""))
end
end
Expand Down Expand Up @@ -387,7 +386,7 @@ describe "File" do
end

it "raises when destination doesn't exist" do
expect_raises_errno(Errno::ENOENT, "Error changing permissions of '#{datapath("unknown_chmod_path.txt")}'") do
expect_raises(File::NotFoundError, "Error changing permissions: '#{datapath("unknown_chmod_path.txt")}'") do
File.chmod(datapath("unknown_chmod_path.txt"), 0o664)
end
end
Expand Down Expand Up @@ -430,7 +429,7 @@ describe "File" do
end

it "gets for non-existent file and raises" do
expect_raises_errno(Errno::ENOENT, "Unable to get info for 'non-existent'") do
expect_raises(File::NotFoundError, "Unable to get file info: 'non-existent'") do
File.info("non-existent")
end
end
Expand Down Expand Up @@ -472,14 +471,14 @@ describe "File" do

it "raises an error when the file does not exist" do
filename = datapath("non_existing_file.txt")
expect_raises_errno(Errno::ENOENT, "Error determining size of '#{filename}'") do
expect_raises(File::NotFoundError, "Unable to get file info: '#{filename}'") do
File.size(filename)
end
end

# TODO: do we even want this?
pending_win32 "raises an error when a component of the path is a file" do
expect_raises_errno(Errno::ENOTDIR, "Error determining size of '#{datapath("test_file.txt", "")}'") do
expect_raises(File::Error, "Unable to get file info: '#{datapath("test_file.txt", "")}'") do
File.size(datapath("test_file.txt", ""))
end
end
Expand All @@ -495,9 +494,9 @@ describe "File" do
end
end

it "raises errno when file doesn't exist" do
it "raises when file doesn't exist" do
with_tempfile("nonexistant_file.txt") do |path|
expect_raises_errno(Errno::ENOENT, "Error deleting file '#{path}'") do
expect_raises(File::NotFoundError, "Error deleting file: '#{path}'") do
File.delete(path)
end
end
Expand All @@ -518,7 +517,7 @@ describe "File" do

it "raises if old file doesn't exist" do
with_tempfile("rename-fail-source.txt", "rename-fail-target.txt") do |source_path, target_path|
expect_raises_errno(Errno::ENOENT, "Error renaming file '#{source_path}' to '#{target_path}'") do
expect_raises(File::NotFoundError, "Error renaming file: '#{source_path}' -> '#{target_path}'") do
File.rename(source_path, target_path)
end
end
Expand Down Expand Up @@ -635,8 +634,8 @@ describe "File" do
{% end %}
end

it "raises Errno if file doesn't exist" do
expect_raises_errno(Errno::ENOENT, "Error resolving real path of '/usr/share/foo/bar'") do
it "raises if file doesn't exist" do
expect_raises(File::NotFoundError, "Error resolving real path: '/usr/share/foo/bar'") do
File.real_path("/usr/share/foo/bar")
end
end
Expand Down Expand Up @@ -841,6 +840,14 @@ describe "File" do
end
end

it "raises when reading a file with no permission" do
with_tempfile("file.txt") do |path|
File.touch(path)
File.chmod(path, 0)
expect_raises(File::AccessDeniedError) { File.read(path) }
end
end

describe "truncate" do
it "truncates" do
with_tempfile("truncate.txt") do |path|
Expand Down Expand Up @@ -872,7 +879,7 @@ describe "File" do
with_tempfile("truncate-opened.txt") do |path|
File.write(path, "0123456789")
File.open(path, "r") do |f|
expect_raises_errno(Errno::EINVAL, "Error truncating file '#{path}'") do
expect_raises(File::Error, "Error truncating file: '#{path}'") do
f.truncate(4)
end
end
Expand All @@ -899,7 +906,7 @@ describe "File" do
File.open(datapath("test_file.txt")) do |file2|
file1.flock_exclusive do
# BUG: check for EWOULDBLOCK when exception filters are implemented
expect_raises_errno(Errno::EAGAIN, "flock") do
expect_raises(IO::Error, "Error applying or removing file lock") do
file2.flock_exclusive(blocking: false) { }
end
end
Expand Down Expand Up @@ -1152,7 +1159,7 @@ describe "File" do
atime = Time.utc(2000, 1, 2)
mtime = Time.utc(2000, 3, 4)

expect_raises_errno(Errno::ENOENT, "Error setting time on file '#{datapath("nonexistent_file.txt")}'") do
expect_raises(File::NotFoundError, "Error setting time on file: '#{datapath("nonexistent_file.txt")}'") do
File.utime(atime, mtime, datapath("nonexistent_file.txt"))
end
end
Expand Down Expand Up @@ -1188,15 +1195,15 @@ describe "File" do

it "raises if path contains non-existent directory" do
with_tempfile(File.join("nonexistant-dir", "touch.txt")) do |path|
expect_raises_errno(Errno::ENOENT, "Error opening file '#{path}'") do
expect_raises(File::NotFoundError, "Error opening file with mode 'a': '#{path}'") do
File.touch(path)
end
end
end

# TODO: there is no file which is reliably unwritable on windows
pending_win32 "raises if file cannot be accessed" do
expect_raises_errno(Errno::EPERM, "Error setting time on file '/bin/ls'") do
expect_raises(File::Error, "Error setting time on file: '/bin/ls'") do
File.touch("/bin/ls")
end
end
Expand Down
39 changes: 22 additions & 17 deletions spec/std/file_utils_spec.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require "./spec_helper"
require "file_utils"
require "../support/errno"

private class OneByOneIO < IO
@bytes : Bytes
Expand Down Expand Up @@ -34,7 +33,7 @@ describe "FileUtils" do
end

it "raises" do
expect_raises_errno(Errno::ENOENT, "Error while changing directory to '/nope'") do
expect_raises(File::NotFoundError, "Error while changing directory: '/nope'") do
FileUtils.cd("/nope")
end
end
Expand Down Expand Up @@ -230,6 +229,12 @@ describe "FileUtils" do
end

it "doesn't return error on non existing file" do
with_tempfile("rm_rf-nonexistent") do |path|
FileUtils.rm_rf(path).should be_nil
end
end

it "doesn't return error on non existing files" do
with_tempfile("rm_rf-nonexistent") do |path1|
path2 = File.join(path1, "a")
FileUtils.mkdir(path1)
Expand All @@ -253,7 +258,7 @@ describe "FileUtils" do

it "raises an error if non correct arguments" do
with_tempfile("mv-nonexitent") do |path|
expect_raises_errno(Errno::ENOENT, "Error renaming file '#{File.join(path, "a")}' to '#{File.join(path, "b")}'") do
expect_raises(File::NotFoundError, "Error renaming file: '#{File.join(path, "a")}' -> '#{File.join(path, "b")}'") do
FileUtils.mv(File.join(path, "a"), File.join(path, "b"))
end
end
Expand Down Expand Up @@ -323,18 +328,18 @@ describe "FileUtils" do
end

it "tests mkdir with an existing path" do
expect_raises_errno(Errno::EEXIST, "Unable to create directory '#{datapath}'") do
expect_raises(File::AlreadyExistsError, "Unable to create directory: '#{datapath}'") do
Dir.mkdir(datapath, 0o700)
end
end

it "tests mkdir with multiples existing paths" do
expect_raises_errno(Errno::EEXIST, "Unable to create directory '#{datapath}'") do
expect_raises(File::AlreadyExistsError, "Unable to create directory: '#{datapath}'") do
FileUtils.mkdir([datapath, datapath], 0o700)
end

with_tempfile("mkdir-nonexisting") do |path|
expect_raises_errno(Errno::EEXIST, "Unable to create directory '#{datapath}'") do
expect_raises(File::AlreadyExistsError, "Unable to create directory: '#{datapath}'") do
FileUtils.mkdir([path, datapath], 0o700)
end
end
Expand All @@ -356,36 +361,36 @@ describe "FileUtils" do
it "tests mkdir_p with multiple existing path" do
FileUtils.mkdir_p([datapath, datapath]).should be_nil
with_tempfile("mkdir_p-existing") do |path|
expect_raises_errno(Errno::EEXIST, "Unable to create directory '#{datapath("test_file.txt")}'") do
expect_raises(File::AlreadyExistsError, "Unable to create directory: '#{datapath("test_file.txt")}'") do
FileUtils.mkdir_p([datapath("test_file.txt"), path])
end
end
end

it "tests rmdir with an non existing path" do
with_tempfile("rmdir-nonexisting") do |path|
expect_raises_errno(Errno::ENOENT, "Unable to remove directory '#{path}'") do
expect_raises(File::NotFoundError, "Unable to remove directory: '#{path}'") do
FileUtils.rmdir(path)
end
end
end

it "tests rmdir with multiple non existing path" do
with_tempfile("rmdir-nonexisting") do |path|
expect_raises_errno(Errno::ENOENT, "Unable to remove directory '#{path}1'") do
expect_raises(File::NotFoundError, "Unable to remove directory: '#{path}1'") do
FileUtils.rmdir(["#{path}1", "#{path}2"])
end
end
end

it "tests rmdir with a path that cannot be removed" do
expect_raises_errno(Errno::ENOTEMPTY, "Unable to remove directory '#{datapath}'") do
expect_raises(File::Error, "Unable to remove directory: '#{datapath}'") do
FileUtils.rmdir(datapath)
end
end

it "tests rmdir with multiple path that cannot be removed" do
expect_raises_errno(Errno::ENOTEMPTY, "Unable to remove directory '#{datapath}'") do
expect_raises(File::Error, "Unable to remove directory: '#{datapath}'") do
FileUtils.rmdir([datapath, datapath])
end
end
Expand All @@ -400,7 +405,7 @@ describe "FileUtils" do

it "tests rm with non existing path" do
with_tempfile("rm-nonexistinent") do |path|
expect_raises_errno(Errno::ENOENT, "Error deleting file '#{path}'") do
expect_raises(File::NotFoundError, "Error deleting file: '#{path}'") do
FileUtils.rm(path)
end
end
Expand All @@ -421,7 +426,7 @@ describe "FileUtils" do
File.write(path1, "")
File.write(path2, "")

expect_raises_errno(Errno::ENOENT, "Error deleting file '#{path2}'") do
expect_raises(File::NotFoundError, "Error deleting file: '#{path2}'") do
FileUtils.rm([path1, path2, path2])
end
end
Expand Down Expand Up @@ -482,7 +487,7 @@ describe "FileUtils" do
path1 = "/tmp/crystal_ln_test_#{Process.pid}"
path2 = "/tmp/crystal_ln_test_#{Process.pid + 1}"

ex = expect_raises_errno(Errno::ENOENT, "Error creating link from '#{path1}' to '#{path2}'") do
ex = expect_raises(File::NotFoundError, "Error creating link: '#{path1}' -> '#{path2}'") do
FileUtils.ln(path1, path2)
end
end
Expand All @@ -494,7 +499,7 @@ describe "FileUtils" do
begin
FileUtils.touch([path1, path2])

expect_raises_errno(Errno::EEXIST, "Error creating link from '#{path1}' to '#{path2}'") do
expect_raises(File::AlreadyExistsError, "Error creating link: '#{path1}' -> '#{path2}'") do
FileUtils.ln(path1, path2)
end
ensure
Expand Down Expand Up @@ -563,7 +568,7 @@ describe "FileUtils" do
File.exists?(path2).should be_false
File.symlink?(path2).should be_true

expect_raises_errno(Errno::ENOENT, "Error resolving real path of '#{path2}'") do
expect_raises(File::NotFoundError, "Error resolving real path: '#{path2}'") do
File.real_path(path2)
end
ensure
Expand All @@ -578,7 +583,7 @@ describe "FileUtils" do
begin
FileUtils.touch([path1, path2])

expect_raises_errno(Errno::EEXIST, "Error creating symlink from '#{path1}' to '#{path2}'") do
expect_raises(File::AlreadyExistsError, "Error creating symlink: '#{path1}' -> '#{path2}'") do
FileUtils.ln_s(path1, path2)
end
ensure
Expand Down
Loading