summaryrefslogtreecommitdiff
path: root/spec/ruby/core/dir
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/dir')
-rw-r--r--spec/ruby/core/dir/children_spec.rb25
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb20
-rw-r--r--spec/ruby/core/dir/each_spec.rb11
-rw-r--r--spec/ruby/core/dir/entries_spec.rb9
-rw-r--r--spec/ruby/core/dir/exist_spec.rb8
-rw-r--r--spec/ruby/core/dir/fchdir_spec.rb68
-rw-r--r--spec/ruby/core/dir/fixtures/common.rb22
-rw-r--r--spec/ruby/core/dir/foreach_spec.rb12
-rw-r--r--spec/ruby/core/dir/glob_spec.rb167
-rw-r--r--spec/ruby/core/dir/home_spec.rb50
-rw-r--r--spec/ruby/core/dir/mkdir_spec.rb18
-rw-r--r--spec/ruby/core/dir/read_spec.rb33
-rw-r--r--spec/ruby/core/dir/shared/chroot.rb13
-rw-r--r--spec/ruby/core/dir/shared/exist.rb8
-rw-r--r--spec/ruby/core/dir/shared/glob.rb59
15 files changed, 466 insertions, 57 deletions
diff --git a/spec/ruby/core/dir/children_spec.rb b/spec/ruby/core/dir/children_spec.rb
index 986c8f38c0..0ad3df4669 100644
--- a/spec/ruby/core/dir/children_spec.rb
+++ b/spec/ruby/core/dir/children_spec.rb
@@ -47,7 +47,7 @@ describe "Dir.children" do
encoding = Encoding.find("filesystem")
encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
platform_is_not :windows do
- children.should include("こんにちは.txt".force_encoding(encoding))
+ children.should include("こんにちは.txt".dup.force_encoding(encoding))
end
children.first.encoding.should equal(Encoding.find("filesystem"))
end
@@ -105,14 +105,6 @@ describe "Dir#children" do
dirs.each { |d| d.encoding.should == Encoding::UTF_8 }
end
- ruby_version_is ""..."2.7" do
- it "accepts nil options" do
- @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", nil)
- dirs = @dir.to_a.sort
- dirs.each { |d| d.encoding.should == Encoding.find("filesystem") }
- end
- end
-
it "returns children encoded with the filesystem encoding by default" do
# This spec depends on the locale not being US-ASCII because if it is, the
# children that are not ascii_only? will be BINARY encoded.
@@ -121,7 +113,7 @@ describe "Dir#children" do
encoding = Encoding.find("filesystem")
encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
platform_is_not :windows do
- children.should include("こんにちは.txt".force_encoding(encoding))
+ children.should include("こんにちは.txt".dup.force_encoding(encoding))
end
children.first.encoding.should equal(Encoding.find("filesystem"))
end
@@ -139,4 +131,17 @@ describe "Dir#children" do
children = @dir.children.sort
children.first.encoding.should equal(Encoding::EUC_KR)
end
+
+ it "returns the same result when called repeatedly" do
+ @dir = Dir.open DirSpecs.mock_dir
+
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
+ end
end
diff --git a/spec/ruby/core/dir/each_child_spec.rb b/spec/ruby/core/dir/each_child_spec.rb
index f7980991e5..7194273b95 100644
--- a/spec/ruby/core/dir/each_child_spec.rb
+++ b/spec/ruby/core/dir/each_child_spec.rb
@@ -15,13 +15,6 @@ describe "Dir.each_child" do
dirs.each {|dir| dir.encoding.should == Encoding::UTF_8}
end
- ruby_version_is ""..."2.7" do
- it "accepts nil options" do
- dirs = Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort
- dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")}
- end
- end
-
it "yields all names in an existing directory to the provided block" do
a, b = [], []
@@ -93,6 +86,19 @@ describe "Dir#each_child" do
@dir.each_child { |f| f }.should == @dir
end
+ it "returns the same result when called repeatedly" do
+ @dir = Dir.open DirSpecs.mock_dir
+
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
+ end
+
describe "when no block is given" do
it "returns an Enumerator" do
@dir = Dir.new(DirSpecs.mock_dir)
diff --git a/spec/ruby/core/dir/each_spec.rb b/spec/ruby/core/dir/each_spec.rb
index 8c69a7212b..7674663d82 100644
--- a/spec/ruby/core/dir/each_spec.rb
+++ b/spec/ruby/core/dir/each_spec.rb
@@ -35,6 +35,17 @@ describe "Dir#each" do
ls.should include(@dir.read)
end
+ it "returns the same result when called repeatedly" do
+ a = []
+ @dir.each {|dir| a << dir}
+
+ b = []
+ @dir.each {|dir| b << dir}
+
+ a.sort.should == b.sort
+ a.sort.should == DirSpecs.expected_paths
+ end
+
describe "when no block is given" do
it "returns an Enumerator" do
@dir.each.should be_an_instance_of(Enumerator)
diff --git a/spec/ruby/core/dir/entries_spec.rb b/spec/ruby/core/dir/entries_spec.rb
index 9aa58657db..7462542acf 100644
--- a/spec/ruby/core/dir/entries_spec.rb
+++ b/spec/ruby/core/dir/entries_spec.rb
@@ -40,13 +40,6 @@ describe "Dir.entries" do
dirs.each {|dir| dir.encoding.should == Encoding::UTF_8}
end
- ruby_version_is ""..."2.7" do
- it "accepts nil options" do
- dirs = Dir.entries("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort
- dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")}
- end
- end
-
it "returns entries encoded with the filesystem encoding by default" do
# This spec depends on the locale not being US-ASCII because if it is, the
# entries that are not ascii_only? will be BINARY encoded.
@@ -54,7 +47,7 @@ describe "Dir.entries" do
encoding = Encoding.find("filesystem")
encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
platform_is_not :windows do
- entries.should include("こんにちは.txt".force_encoding(encoding))
+ entries.should include("こんにちは.txt".dup.force_encoding(encoding))
end
entries.first.encoding.should equal(Encoding.find("filesystem"))
end
diff --git a/spec/ruby/core/dir/exist_spec.rb b/spec/ruby/core/dir/exist_spec.rb
index 43987b0f32..9023de533f 100644
--- a/spec/ruby/core/dir/exist_spec.rb
+++ b/spec/ruby/core/dir/exist_spec.rb
@@ -13,3 +13,11 @@ describe "Dir.exist?" do
it_behaves_like :dir_exist, :exist?
end
+
+ruby_version_is "3.2" do
+ describe "Dir.exists?" do
+ it "has been removed" do
+ Dir.should_not.respond_to?(:exists?)
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/fchdir_spec.rb b/spec/ruby/core/dir/fchdir_spec.rb
new file mode 100644
index 0000000000..429e569691
--- /dev/null
+++ b/spec/ruby/core/dir/fchdir_spec.rb
@@ -0,0 +1,68 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+
+ruby_version_is '3.3' do
+ guard -> { Dir.respond_to? :fchdir } do
+ describe "Dir.fchdir" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
+
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
+
+ before :each do
+ @dirs = [Dir.new('.')]
+ @original = @dirs.first.fileno
+ end
+
+ after :each do
+ Dir.fchdir(@original)
+ @dirs.each(&:close)
+ end
+
+ it "changes to the specified directory" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ @dirs << dir
+ Dir.fchdir dir.fileno
+ Dir.pwd.should == DirSpecs.mock_dir
+ end
+
+ it "returns 0 when successfully changing directory" do
+ Dir.fchdir(@original).should == 0
+ end
+
+ it "returns the value of the block when a block is given" do
+ Dir.fchdir(@original) { :block_value }.should == :block_value
+ end
+
+ it "changes to the specified directory for the duration of the block" do
+ pwd = Dir.pwd
+ dir = Dir.new(DirSpecs.mock_dir)
+ @dirs << dir
+ Dir.fchdir(dir.fileno) { Dir.pwd }.should == DirSpecs.mock_dir
+ Dir.pwd.should == pwd
+ end
+
+ it "raises a SystemCallError if the file descriptor given is not valid" do
+ -> { Dir.fchdir(-1) }.should raise_error(SystemCallError)
+ -> { Dir.fchdir(-1) { } }.should raise_error(SystemCallError)
+ end
+
+ it "raises a SystemCallError if the file descriptor given is not for a directory" do
+ -> { Dir.fchdir $stdout.fileno }.should raise_error(SystemCallError)
+ -> { Dir.fchdir($stdout.fileno) { } }.should raise_error(SystemCallError)
+ end
+ end
+ end
+
+ guard_not -> { Dir.respond_to? :fchdir } do
+ describe "Dir.fchdir" do
+ it "raises NotImplementedError" do
+ -> { Dir.fchdir 1 }.should raise_error(NotImplementedError)
+ -> { Dir.fchdir(1) { } }.should raise_error(NotImplementedError)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/fixtures/common.rb b/spec/ruby/core/dir/fixtures/common.rb
index a1ea3db215..087f46b331 100644
--- a/spec/ruby/core/dir/fixtures/common.rb
+++ b/spec/ruby/core/dir/fixtures/common.rb
@@ -81,6 +81,8 @@ module DirSpecs
special/}
special/test{1}/file[1]
+ special/{}/special
+ special/test\ +()[]{}/hello_world.erb
]
platform_is_not :windows do
@@ -91,19 +93,39 @@ module DirSpecs
special/|
special/こんにちは.txt
+ special/\a
]
+ @mock_dir_files << "special/_\u{1f60e}.erb"
end
end
@mock_dir_files
end
+ def self.mock_dir_links
+ unless @mock_dir_links
+ @mock_dir_links = []
+ platform_is_not :windows do
+ @mock_dir_links += [
+ ['special/ln', 'subdir_one']
+ ]
+ end
+ end
+ @mock_dir_links
+ end
+
def self.create_mock_dirs
mock_dir_files.each do |name|
file = File.join mock_dir, name
mkdir_p File.dirname(file)
touch file
end
+ mock_dir_links.each do |link, target|
+ full_link = File.join mock_dir, link
+ full_target = File.join mock_dir, target
+
+ File.symlink full_target, full_link
+ end
end
def self.delete_mock_dirs
diff --git a/spec/ruby/core/dir/foreach_spec.rb b/spec/ruby/core/dir/foreach_spec.rb
index c3ddb27a84..9cf34b1d71 100644
--- a/spec/ruby/core/dir/foreach_spec.rb
+++ b/spec/ruby/core/dir/foreach_spec.rb
@@ -41,13 +41,13 @@ describe "Dir.foreach" do
it "accepts an encoding keyword for the encoding of the entries" do
dirs = Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").to_a.sort
- dirs.each {|dir| dir.encoding.should == Encoding::UTF_8}
- end
+ dirs.each { |dir| dir.encoding.should == Encoding::UTF_8 }
+
+ dirs = Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", encoding: Encoding::ISO_8859_1).to_a.sort
+ dirs.each { |dir| dir.encoding.should == Encoding::ISO_8859_1 }
- ruby_version_is ""..."2.7" do
- it "accepts nil options" do
- dirs = Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", nil).to_a.sort
- dirs.each {|dir| dir.encoding.should == Encoding.find("filesystem")}
+ Dir.foreach("#{DirSpecs.mock_dir}/deeply/nested", encoding: Encoding::ISO_8859_1) do |f|
+ f.encoding.should == Encoding::ISO_8859_1
end
end
diff --git a/spec/ruby/core/dir/glob_spec.rb b/spec/ruby/core/dir/glob_spec.rb
index 6533c9b65a..32f515c81d 100644
--- a/spec/ruby/core/dir/glob_spec.rb
+++ b/spec/ruby/core/dir/glob_spec.rb
@@ -79,7 +79,9 @@ describe "Dir.glob" do
nested/
nested/.dotsubir/
special/
+ special/test\ +()[]{}/
special/test{1}/
+ special/{}/
subdir_one/
subdir_two/
]
@@ -104,11 +106,11 @@ describe "Dir.glob" do
ruby_version_is '3.1' do
it "recursively matches files and directories in nested dot subdirectory except . with 'nested/**/*' from the current directory and option File::FNM_DOTMATCH" do
expected = %w[
- nested/.
- nested/.dotsubir
- nested/.dotsubir/.dotfile
- nested/.dotsubir/nondotfile
- ]
+ nested/.
+ nested/.dotsubir
+ nested/.dotsubir/.dotfile
+ nested/.dotsubir/nondotfile
+ ]
Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
end
@@ -129,7 +131,9 @@ describe "Dir.glob" do
./nested/
./nested/.dotsubir/
./special/
+ ./special/test\ +()[]{}/
./special/test{1}/
+ ./special/{}/
./subdir_one/
./subdir_two/
]
@@ -178,6 +182,134 @@ describe "Dir.glob" do
Dir.glob('**/**/**').should_not.empty?
end
+ it "handles **/** with base keyword argument" do
+ Dir.glob('**/**', base: "dir").should == ["filename_ordering"]
+
+ expected = %w[
+ nested
+ nested/directory
+ nested/directory/structure
+ nested/directory/structure/bar
+ nested/directory/structure/baz
+ nested/directory/structure/file_one
+ nested/directory/structure/file_one.ext
+ nested/directory/structure/foo
+ nondotfile
+ ].sort
+
+ Dir.glob('**/**', base: "deeply").sort.should == expected
+ end
+
+ it "handles **/ with base keyword argument" do
+ expected = %w[
+ /
+ directory/
+ directory/structure/
+ ]
+ Dir.glob('**/', base: "deeply/nested").sort.should == expected
+ end
+
+ it "handles **/nondotfile with base keyword argument" do
+ expected = %w[
+ deeply/nondotfile
+ nondotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ ]
+ Dir.glob('**/nondotfile', base: ".").sort.should == expected
+ end
+
+ it "handles **/nondotfile with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .dotsubdir/nondotfile
+ deeply/nondotfile
+ nested/.dotsubir/nondotfile
+ nondotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ ]
+ Dir.glob('**/nondotfile', File::FNM_DOTMATCH, base: ".").sort.should == expected
+ end
+
+ it "handles **/.dotfile with base keyword argument" do
+ expected = %w[
+ .dotfile
+ deeply/.dotfile
+ subdir_one/.dotfile
+ ]
+ Dir.glob('**/.dotfile', base: ".").sort.should == expected
+ end
+
+ it "handles **/.dotfile with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .dotfile
+ .dotsubdir/.dotfile
+ deeply/.dotfile
+ nested/.dotsubir/.dotfile
+ subdir_one/.dotfile
+ ]
+ Dir.glob('**/.dotfile', File::FNM_DOTMATCH, base: ".").sort.should == expected
+ end
+
+ it "handles **/.* with base keyword argument" do
+ expected = %w[
+ .dotfile.ext
+ directory/structure/.ext
+ ].sort
+
+ Dir.glob('**/.*', base: "deeply/nested").sort.should == expected
+ end
+
+ # < 3.1 include a "." entry for every dir: ["directory/.", "directory/structure/.", ...]
+ ruby_version_is '3.1' do
+ it "handles **/.* with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .
+ .dotfile.ext
+ directory/structure/.ext
+ ].sort
+
+ Dir.glob('**/.*', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
+ end
+
+ it "handles **/** with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .
+ .dotfile.ext
+ directory
+ directory/structure
+ directory/structure/.ext
+ directory/structure/bar
+ directory/structure/baz
+ directory/structure/file_one
+ directory/structure/file_one.ext
+ directory/structure/foo
+ ].sort
+
+ Dir.glob('**/**', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
+ end
+ end
+
+ it "handles **/*pattern* with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .dotfile.ext
+ directory/structure/file_one
+ directory/structure/file_one.ext
+ ]
+
+ Dir.glob('**/*file*', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
+ end
+
+ it "handles **/glob with base keyword argument and FNM_EXTGLOB" do
+ expected = %w[
+ directory/structure/bar
+ directory/structure/file_one
+ directory/structure/file_one.ext
+ ]
+
+ Dir.glob('**/*{file,bar}*', File::FNM_EXTGLOB, base: "deeply/nested").sort.should == expected
+ end
+
it "handles simple filename patterns" do
Dir.glob('.dotfile').should == ['.dotfile']
end
@@ -220,5 +352,30 @@ describe "Dir.glob" do
Dir.rmdir('no_permission')
end
end
+
+ it "will follow symlinks when processing a `*/` pattern." do
+ expected = ['special/ln/nondotfile']
+ Dir.glob('special/*/nondotfile').should == expected
+ end
+
+ it "will not follow symlinks when recursively traversing directories" do
+ expected = %w[
+ deeply/nondotfile
+ nondotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ ]
+ Dir.glob('**/nondotfile').sort.should == expected
+ end
+
+ it "will follow symlinks when testing directory after recursive directory in pattern" do
+ expected = %w[
+ deeply/nondotfile
+ special/ln/nondotfile
+ subdir_one/nondotfile
+ subdir_two/nondotfile
+ ]
+ Dir.glob('**/*/nondotfile').sort.should == expected
+ end
end
end
diff --git a/spec/ruby/core/dir/home_spec.rb b/spec/ruby/core/dir/home_spec.rb
index 713ba9db9a..3cf745ab46 100644
--- a/spec/ruby/core/dir/home_spec.rb
+++ b/spec/ruby/core/dir/home_spec.rb
@@ -19,6 +19,44 @@ describe "Dir.home" do
it "returns a non-frozen string" do
Dir.home.should_not.frozen?
end
+
+ it "returns a string with the filesystem encoding" do
+ Dir.home.encoding.should == Encoding.find("filesystem")
+ end
+
+ platform_is_not :windows do
+ it "works even if HOME is unset" do
+ ENV.delete('HOME')
+ Dir.home.should.start_with?('/')
+ Dir.home.encoding.should == Encoding.find("filesystem")
+ end
+ end
+
+ platform_is :windows do
+ ruby_version_is "3.2" do
+ it "returns the home directory with forward slashs and as UTF-8" do
+ ENV['HOME'] = "C:\\rubyspäc\\home"
+ home = Dir.home
+ home.should == "C:/rubyspäc/home"
+ home.encoding.should == Encoding::UTF_8
+ end
+
+ it "retrieves the directory from HOME, USERPROFILE, HOMEDRIVE/HOMEPATH and the WinAPI in that order" do
+ old_dirs = [ENV.delete('HOME'), ENV.delete('USERPROFILE'), ENV.delete('HOMEDRIVE'), ENV.delete('HOMEPATH')]
+
+ Dir.home.should == old_dirs[1].gsub("\\", "/")
+ ENV['HOMEDRIVE'] = "C:"
+ ENV['HOMEPATH'] = "\\rubyspec\\home1"
+ Dir.home.should == "C:/rubyspec/home1"
+ ENV['USERPROFILE'] = "C:\\rubyspec\\home2"
+ Dir.home.should == "C:/rubyspec/home2"
+ ENV['HOME'] = "C:\\rubyspec\\home3"
+ Dir.home.should == "C:/rubyspec/home3"
+ ensure
+ ENV['HOME'], ENV['USERPROFILE'], ENV['HOMEDRIVE'], ENV['HOMEPATH'] = *old_dirs
+ end
+ end
+ end
end
describe "when called with the current user name" do
@@ -28,7 +66,7 @@ describe "Dir.home" do
end
end
- platform_is_not :windows, :solaris, :android do
+ platform_is_not :windows, :solaris, :android, :wasi do
it "returns the named user's home directory, from the user database" do
Dir.home(ENV['USER']).should == `echo ~#{ENV['USER']}`.chomp
end
@@ -37,9 +75,19 @@ describe "Dir.home" do
it "returns a non-frozen string" do
Dir.home(ENV['USER']).should_not.frozen?
end
+
+ it "returns a string with the filesystem encoding" do
+ Dir.home(ENV['USER']).encoding.should == Encoding.find("filesystem")
+ end
end
it "raises an ArgumentError if the named user doesn't exist" do
-> { Dir.home('geuw2n288dh2k') }.should raise_error(ArgumentError)
end
+
+ describe "when called with a nil user name" do
+ it "returns the current user's home directory, reading $HOME first" do
+ Dir.home(nil).should == "/rubyspec_home"
+ end
+ end
end
diff --git a/spec/ruby/core/dir/mkdir_spec.rb b/spec/ruby/core/dir/mkdir_spec.rb
index 0ed28f5a99..076ec19dd9 100644
--- a/spec/ruby/core/dir/mkdir_spec.rb
+++ b/spec/ruby/core/dir/mkdir_spec.rb
@@ -46,7 +46,7 @@ describe "Dir.mkdir" do
end
end
- it "calls #to_path on non-String arguments" do
+ it "calls #to_path on non-String path arguments" do
DirSpecs.clear_dirs
p = mock('path')
p.should_receive(:to_path).and_return(DirSpecs.mock_dir('nonexisting'))
@@ -54,6 +54,22 @@ describe "Dir.mkdir" do
DirSpecs.clear_dirs
end
+ it "calls #to_int on non-Integer permissions argument" do
+ DirSpecs.clear_dirs
+ path = DirSpecs.mock_dir('nonexisting')
+ permissions = mock('permissions')
+ permissions.should_receive(:to_int).and_return(0666)
+ Dir.mkdir(path, permissions)
+ DirSpecs.clear_dirs
+ end
+
+ it "raises TypeError if non-Integer permissions argument does not have #to_int method" do
+ path = DirSpecs.mock_dir('nonexisting')
+ permissions = Object.new
+
+ -> { Dir.mkdir(path, permissions) }.should raise_error(TypeError, 'no implicit conversion of Object into Integer')
+ end
+
it "raises a SystemCallError if any of the directories in the path before the last does not exist" do
-> { Dir.mkdir "#{DirSpecs.nonexistent}/subdir" }.should raise_error(SystemCallError)
end
diff --git a/spec/ruby/core/dir/read_spec.rb b/spec/ruby/core/dir/read_spec.rb
index 59de2e81cf..276930c6b7 100644
--- a/spec/ruby/core/dir/read_spec.rb
+++ b/spec/ruby/core/dir/read_spec.rb
@@ -39,5 +39,38 @@ describe "Dir#read" do
entries.sort.should == DirSpecs.expected_paths
end
+ platform_is_not :windows do
+ it "returns all directory entries even when encoding conversion will fail" do
+ dir = Dir.open(File.join(DirSpecs.mock_dir, 'special'))
+ utf8_entries = []
+ begin
+ while entry = dir.read
+ utf8_entries << entry
+ end
+ ensure
+ dir.close
+ end
+ old_internal_encoding = Encoding::default_internal
+ old_external_encoding = Encoding::default_external
+ Encoding.default_internal = Encoding::UTF_8
+ Encoding.default_external = Encoding::SHIFT_JIS
+ shift_jis_entries = []
+ begin
+ Dir.open(File.join(DirSpecs.mock_dir, 'special')) do |d|
+ -> {
+ while entry = d.read
+ shift_jis_entries << entry
+ end
+ }.should_not raise_error
+ end
+ ensure
+ Encoding.default_internal = old_internal_encoding
+ Encoding.default_external = old_external_encoding
+ end
+ shift_jis_entries.size.should == utf8_entries.size
+ shift_jis_entries.filter { |f| f.encoding == Encoding::SHIFT_JIS }.size.should == 1
+ end
+ end
+
it_behaves_like :dir_closed, :read
end
diff --git a/spec/ruby/core/dir/shared/chroot.rb b/spec/ruby/core/dir/shared/chroot.rb
index b14a433670..a8f7c10a19 100644
--- a/spec/ruby/core/dir/shared/chroot.rb
+++ b/spec/ruby/core/dir/shared/chroot.rb
@@ -2,8 +2,8 @@ describe :dir_chroot_as_root, shared: true do
before :all do
DirSpecs.create_mock_dirs
- @real_root = "../" * (File.dirname(__FILE__).count('/') - 1)
- @ref_dir = File.join("/", Dir.new('/').entries.first)
+ @real_root = "../" * (__dir__.count('/') - 1)
+ @ref_dir = File.join("/", File.basename(Dir["/*"].first))
end
after :all do
@@ -14,10 +14,13 @@ describe :dir_chroot_as_root, shared: true do
DirSpecs.delete_mock_dirs
end
+ # Pending until https://github.com/ruby/ruby/runs/8075149420 is fixed
+ compilations_ci = ENV["GITHUB_WORKFLOW"] == "Compilations"
+
it "can be used to change the process' root directory" do
- -> { Dir.send(@method, File.dirname(__FILE__)) }.should_not raise_error
+ -> { Dir.send(@method, __dir__) }.should_not raise_error
File.should.exist?("/#{File.basename(__FILE__)}")
- end
+ end unless compilations_ci
it "returns 0 if successful" do
Dir.send(@method, '/').should == 0
@@ -31,7 +34,7 @@ describe :dir_chroot_as_root, shared: true do
Dir.send(@method, @real_root)
File.should.exist?(@ref_dir)
File.should_not.exist?("/#{File.basename(__FILE__)}")
- end
+ end unless compilations_ci
it "calls #to_path on non-String argument" do
p = mock('path')
diff --git a/spec/ruby/core/dir/shared/exist.rb b/spec/ruby/core/dir/shared/exist.rb
index 765d1b656c..2ea4f88a80 100644
--- a/spec/ruby/core/dir/shared/exist.rb
+++ b/spec/ruby/core/dir/shared/exist.rb
@@ -1,6 +1,6 @@
describe :dir_exist, shared: true do
it "returns true if the given directory exists" do
- Dir.send(@method, File.dirname(__FILE__)).should be_true
+ Dir.send(@method, __dir__).should be_true
end
it "returns true for '.'" do
@@ -20,7 +20,7 @@ describe :dir_exist, shared: true do
end
it "understands relative paths" do
- Dir.send(@method, File.dirname(__FILE__) + '/../').should be_true
+ Dir.send(@method, __dir__ + '/../').should be_true
end
it "returns false if the given directory doesn't exist" do
@@ -28,7 +28,7 @@ describe :dir_exist, shared: true do
end
it "doesn't require the name to have a trailing slash" do
- dir = File.dirname(__FILE__)
+ dir = __dir__
dir.sub!(/\/$/,'')
Dir.send(@method, dir).should be_true
end
@@ -50,7 +50,7 @@ describe :dir_exist, shared: true do
it "calls #to_path on non String arguments" do
p = mock('path')
- p.should_receive(:to_path).and_return(File.dirname(__FILE__))
+ p.should_receive(:to_path).and_return(__dir__)
Dir.send(@method, p)
end
end
diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb
index ae5c2a114b..745f02d46b 100644
--- a/spec/ruby/core/dir/shared/glob.rb
+++ b/spec/ruby/core/dir/shared/glob.rb
@@ -12,7 +12,7 @@ describe :dir_glob, shared: true do
end
it "raises an Encoding::CompatibilityError if the argument encoding is not compatible with US-ASCII" do
- pattern = "file*".force_encoding Encoding::UTF_16BE
+ pattern = "file*".dup.force_encoding Encoding::UTF_16BE
-> { Dir.send(@method, pattern) }.should raise_error(Encoding::CompatibilityError)
end
@@ -23,18 +23,43 @@ describe :dir_glob, shared: true do
Dir.send(@method, obj).should == %w[file_one.ext]
end
- ruby_version_is ""..."2.7" do
- it "splits the string on \\0 if there is only one string given and warns" do
- -> {
- Dir.send(@method, "file_o*\0file_t*").should ==
- %w!file_one.ext file_two.ext!
- }.should complain(/warning: use glob patterns list instead of nul-separated patterns/)
+ it "raises an ArgumentError if the string contains \\0" do
+ -> {Dir.send(@method, "file_o*\0file_t*")}.should raise_error ArgumentError, /nul-separated/
+ end
+
+ it "result is sorted by default" do
+ result = Dir.send(@method, '*')
+ result.should == result.sort
+ end
+
+ it "result is sorted with sort: true" do
+ result = Dir.send(@method, '*', sort: true)
+ result.should == result.sort
+ end
+
+ it "sort: false returns same files" do
+ result = Dir.send(@method,'*', sort: false)
+ result.sort.should == Dir.send(@method, '*').sort
+ end
+
+ ruby_version_is ""..."3.1" do
+ it "result is sorted with any non false value of sort:" do
+ result = Dir.send(@method, '*', sort: 0)
+ result.should == result.sort
+
+ result = Dir.send(@method, '*', sort: nil)
+ result.should == result.sort
+
+ result = Dir.send(@method, '*', sort: 'false')
+ result.should == result.sort
end
end
- ruby_version_is "2.7" do
- it "raises an ArgumentError if the string contains \\0" do
- -> {Dir.send(@method, "file_o*\0file_t*")}.should raise_error ArgumentError, /nul-separated/
+ ruby_version_is "3.1" do
+ it "raises an ArgumentError if sort: is not true or false" do
+ -> { Dir.send(@method, '*', sort: 0) }.should raise_error ArgumentError, /expected true or false/
+ -> { Dir.send(@method, '*', sort: nil) }.should raise_error ArgumentError, /expected true or false/
+ -> { Dir.send(@method, '*', sort: 'false') }.should raise_error ArgumentError, /expected true or false/
end
end
@@ -64,6 +89,10 @@ describe :dir_glob, shared: true do
Dir.send(@method, 'special/+').should == ['special/+']
end
+ it "matches directories with special characters when escaped" do
+ Dir.send(@method, 'special/\{}/special').should == ["special/{}/special"]
+ end
+
platform_is_not :windows do
it "matches regexp special *" do
Dir.send(@method, 'special/\*').should == ['special/*']
@@ -76,6 +105,14 @@ describe :dir_glob, shared: true do
it "matches regexp special |" do
Dir.send(@method, 'special/|').should == ['special/|']
end
+
+ it "matches files with backslashes in their name" do
+ Dir.glob('special/\\\\{a,b}').should == ['special/\a']
+ end
+
+ it "matches directory with special characters in their name in complex patterns" do
+ Dir.glob("special/test +()\\[\\]\\{\\}/hello_world{.{en},}{.{html},}{+{phone},}{.{erb},}").should == ['special/test +()[]{}/hello_world.erb']
+ end
end
it "matches regexp special ^" do
@@ -190,7 +227,9 @@ describe :dir_glob, shared: true do
dir/
nested/
special/
+ special/test\ +()[]{}/
special/test{1}/
+ special/{}/
subdir_one/
subdir_two/
]