From 11b7ef35b94ed66f98e4a1bbed9d3af32d3ff206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Sun, 15 Apr 2018 17:24:47 +0200 Subject: [PATCH 01/10] Add spec helper `with_tempfile` --- spec/support/tempfile.cr | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 spec/support/tempfile.cr diff --git a/spec/support/tempfile.cr b/spec/support/tempfile.cr new file mode 100644 index 000000000000..5499993cd899 --- /dev/null +++ b/spec/support/tempfile.cr @@ -0,0 +1,43 @@ +require "tempfile" +require "file_utils" + +SPEC_TEMPFILE_PATH = File.join(Tempfile.dirname, "crystal-spec-#{Random.new.hex(8)}") + +SPEC_TEMPFILE_CLEANUP = ENV["SPEC_TEMPFILE_CLEANUP"]? != "0" + +# Expands *paths* in a unique temp folder and yield them to the block. +# +# The *paths* are interpreted relative to a unique folder for every spec run and +# prefixed by the name of the spec file that requests them. +# +# The constructed path is yielded to the block and cleaned up afterwards. +# +# Paths should still be uniquely chosen inside a spec file. This helper +# ensures they're placed in the temporary location (`Tempfile.dirname`), +# avoids name clashes between parallel spec runs and cleans up afterwards. +# +# The unique directory for the spec run is removed `at_exit`. +# +# If the environment variable `SPEC_TEMPFILE_CLEANUP` is set to `0`, no paths +# will be cleaned up, enabling easier debugging. +def with_tempfile(*paths, file = __FILE__) + calling_spec = File.basename(file).gsub("_spec.cr", "") + paths = paths.map { |path| File.join(SPEC_TEMPFILE_PATH, calling_spec, path) } + FileUtils.mkdir_p(File.join(SPEC_TEMPFILE_PATH, calling_spec)) + + begin + yield *paths + ensure + if SPEC_TEMPFILE_CLEANUP + paths.each do |path| + FileUtils.rm_r(path) if File.exists?(path) + end + end + end +end + +if SPEC_TEMPFILE_CLEANUP + at_exit do + FileUtils.rm_r(SPEC_TEMPFILE_PATH) if Dir.exists?(SPEC_TEMPFILE_PATH) + end +end From 9c1c54519f7e6f5802a76afdaa751184a58efdb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Sun, 15 Apr 2018 18:32:53 +0000 Subject: [PATCH 02/10] Add spec_helper with datapath in spec/std --- spec/std/spec_helper.cr | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 spec/std/spec_helper.cr diff --git a/spec/std/spec_helper.cr b/spec/std/spec_helper.cr new file mode 100644 index 000000000000..a5bf95ab0d62 --- /dev/null +++ b/spec/std/spec_helper.cr @@ -0,0 +1,6 @@ +require "spec" +require "../support/tempfile" + +def datapath(*components) + File.join("spec", "std", "data", *components) +end From 346a2d2ae09269753148596ece2a6812cf83261a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Sun, 15 Apr 2018 21:41:22 +0000 Subject: [PATCH 03/10] Use with_tempfile and datapath in spec/std --- spec/std/callstack_spec.cr | 95 ++-- .../{openssl => data}/cipher_spec.ciphertext | 0 .../{openssl/ssl => data/openssl}/openssl.crt | 0 .../{openssl/ssl => data/openssl}/openssl.key | 0 .../static_file_handler}/test.txt | 0 spec/std/dir_spec.cr | 279 +++++----- spec/std/file_spec.cr | 507 ++++++++---------- spec/std/file_utils_spec.cr | 309 +++++------ .../handlers/static_file_handler_spec.cr | 22 +- spec/std/http/web_socket_spec.cr | 8 +- spec/std/ini_spec.cr | 8 +- spec/std/io/argf_spec.cr | 14 +- spec/std/io/io_spec.cr | 10 +- spec/std/kernel_spec.cr | 2 - spec/std/openssl/cipher_spec.cr | 4 +- spec/std/openssl/ssl/context_spec.cr | 14 +- spec/std/process_spec.cr | 23 +- spec/std/socket_spec.cr | 206 +++---- spec/std/time/location_spec.cr | 6 +- spec/std/time/spec_helper.cr | 4 +- spec/std/zip/zip_file_spec.cr | 6 +- spec/std/zip/zip_spec.cr | 4 +- 22 files changed, 715 insertions(+), 806 deletions(-) rename spec/std/{openssl => data}/cipher_spec.ciphertext (100%) rename spec/std/{openssl/ssl => data/openssl}/openssl.crt (100%) rename spec/std/{openssl/ssl => data/openssl}/openssl.key (100%) rename spec/std/{http/server/handlers/static => data/static_file_handler}/test.txt (100%) diff --git a/spec/std/callstack_spec.cr b/spec/std/callstack_spec.cr index 78c131734163..40b916aee825 100644 --- a/spec/std/callstack_spec.cr +++ b/spec/std/callstack_spec.cr @@ -1,75 +1,68 @@ -require "spec" -require "tempfile" +require "./spec_helper" describe "Backtrace" do it "prints file line:colunm" do - tempfile = Tempfile.new("compiler_spec_output") - tempfile.close - sample = "#{__DIR__}/data/backtrace_sample" + with_tempfile("compiler_spec_output") do |path| + sample = datapath("backtrace_sample") - # CallStack tries to make files relative to the current dir, - # so we do the same for tests - current_dir = Dir.current - current_dir += File::SEPARATOR unless current_dir.ends_with?(File::SEPARATOR) - sample = sample.lchop(current_dir) + # CallStack tries to make files relative to the current dir, + # so we do the same for tests + current_dir = Dir.current + current_dir += File::SEPARATOR unless current_dir.ends_with?(File::SEPARATOR) + sample = sample.lchop(current_dir) - `bin/crystal build --debug #{sample.inspect} -o #{tempfile.path.inspect}` - File.exists?(tempfile.path).should be_true + `bin/crystal build --debug #{sample.inspect} -o #{path.inspect}` + File.exists?(path).should be_true - {% if flag?(:darwin) %} - `dsymutil --flat #{tempfile.path}` - {% end %} + {% if flag?(:darwin) %} + `dsymutil --flat #{path}` + {% end %} - output = `#{tempfile.path}` + output = `#{path}` - # resolved file line:column - output.should match(/#{sample}:3:10 in 'callee1'/) + # resolved file line:column + output.should match(/#{sample}:3:10 in 'callee1'/) - unless output =~ /#{sample}:13:5 in 'callee3'/ - fail "didn't find callee3 in the backtrace" - end + unless output =~ /#{sample}:13:5 in 'callee3'/ + fail "didn't find callee3 in the backtrace" + end - # skipped internal details - output.should_not match(/src\/callstack\.cr/) - output.should_not match(/src\/exception\.cr/) - output.should_not match(/src\/raise\.cr/) - ensure - File.delete(tempfile.path) if tempfile + # skipped internal details + output.should_not match(/src\/callstack\.cr/) + output.should_not match(/src\/exception\.cr/) + output.should_not match(/src\/raise\.cr/) + end end it "prints exception backtrace to stderr" do - tempfile = Tempfile.new("compiler_spec_output") - tempfile.close - sample = "#{__DIR__}/data/exception_backtrace_sample" + with_tempfile("compiler_spec_output") do |path| + sample = datapath("exception_backtrace_sample") - `bin/crystal build --debug #{sample.inspect} -o #{tempfile.path.inspect}` - File.exists?(tempfile.path).should be_true + `bin/crystal build --debug #{sample.inspect} -o #{path.inspect}` + File.exists?(path).should be_true - output, error = {IO::Memory.new, IO::Memory.new}.tap do |outio, errio| - Process.run tempfile.path, output: outio, error: errio - end + output, error = {IO::Memory.new, IO::Memory.new}.tap do |outio, errio| + Process.run path, output: outio, error: errio + end - output.to_s.empty?.should be_true - error.to_s.should contain("IndexError") - ensure - File.delete(tempfile.path) if tempfile + output.to_s.empty?.should be_true + error.to_s.should contain("IndexError") + end end it "prints crash backtrace to stderr" do - tempfile = Tempfile.new("compiler_spec_output") - tempfile.close - sample = "#{__DIR__}/data/crash_backtrace_sample" + with_tempfile("compiler_spec_output") do |path| + sample = datapath("crash_backtrace_sample") - `bin/crystal build --debug #{sample.inspect} -o #{tempfile.path.inspect}` - File.exists?(tempfile.path).should be_true + `bin/crystal build --debug #{sample.inspect} -o #{path.inspect}` + File.exists?(path).should be_true - output, error = {IO::Memory.new, IO::Memory.new}.tap do |outio, errio| - Process.run tempfile.path, output: outio, error: errio - end + output, error = {IO::Memory.new, IO::Memory.new}.tap do |outio, errio| + Process.run path, output: outio, error: errio + end - output.to_s.empty?.should be_true - error.to_s.should contain("Invalid memory access") - ensure - File.delete(tempfile.path) if tempfile + output.to_s.empty?.should be_true + error.to_s.should contain("Invalid memory access") + end end end diff --git a/spec/std/openssl/cipher_spec.ciphertext b/spec/std/data/cipher_spec.ciphertext similarity index 100% rename from spec/std/openssl/cipher_spec.ciphertext rename to spec/std/data/cipher_spec.ciphertext diff --git a/spec/std/openssl/ssl/openssl.crt b/spec/std/data/openssl/openssl.crt similarity index 100% rename from spec/std/openssl/ssl/openssl.crt rename to spec/std/data/openssl/openssl.crt diff --git a/spec/std/openssl/ssl/openssl.key b/spec/std/data/openssl/openssl.key similarity index 100% rename from spec/std/openssl/ssl/openssl.key rename to spec/std/data/openssl/openssl.key diff --git a/spec/std/http/server/handlers/static/test.txt b/spec/std/data/static_file_handler/test.txt similarity index 100% rename from spec/std/http/server/handlers/static/test.txt rename to spec/std/data/static_file_handler/test.txt diff --git a/spec/std/dir_spec.cr b/spec/std/dir_spec.cr index 7ce00220e969..4a2a9903f90c 100644 --- a/spec/std/dir_spec.cr +++ b/spec/std/dir_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "./spec_helper" private def it_raises_on_null_byte(operation, &block) it "errors on #{operation}" do @@ -10,214 +10,219 @@ end describe "Dir" do it "tests exists? on existing directory" do - Dir.exists?(File.join([__DIR__, "../"])).should be_true + Dir.exists?(datapath).should be_true end it "tests exists? on existing file" do - Dir.exists?(__FILE__).should be_false + Dir.exists?(datapath("dir", "f1.txt")).should be_false end it "tests exists? on nonexistent directory" do - Dir.exists?(File.join([__DIR__, "/foo/bar/"])).should be_false + Dir.exists?(datapath("foo", "bar")).should be_false end it "tests exists? on a directory path to a file" do - Dir.exists?("#{__FILE__}/").should be_false + Dir.exists?(datapath("dir", "f1.txt", "/")).should be_false end describe "empty?" do it "tests empty? on a full directory" do - Dir.empty?(File.join([__DIR__, "../"])).should be_false + Dir.empty?(datapath).should be_false end it "tests empty? on an empty directory" do - path = "/tmp/crystal_empty_test_#{Process.pid}/" - Dir.mkdir(path, 0o700) - Dir.empty?(path).should be_true + with_tempfile "empty_directory" do |path| + Dir.mkdir(path, 0o700) + Dir.empty?(path).should be_true + end end it "tests empty? on nonexistent directory" do expect_raises(Errno, /Error determining size of/) do - Dir.empty?(File.join([__DIR__, "/foo/bar/"])) + Dir.empty?(datapath("foo", "bar")) end end it "tests empty? on a directory path to a file" do ex = expect_raises(Errno, /Error determining size of/) do - Dir.empty?("#{__FILE__}/") + Dir.empty?(datapath("dir", "f1.txt", "/")) end ex.errno.should eq(Errno::ENOTDIR) end end it "tests mkdir and rmdir with a new path" do - path = "/tmp/crystal_mkdir_test_#{Process.pid}/" - Dir.mkdir(path, 0o700) - Dir.exists?(path).should be_true - Dir.rmdir(path) - Dir.exists?(path).should be_false + with_tempfile("mkdir") do |path| + Dir.mkdir(path, 0o700) + Dir.exists?(path).should be_true + Dir.rmdir(path) + Dir.exists?(path).should be_false + end end it "tests mkdir with an existing path" do expect_raises Errno do - Dir.mkdir(__DIR__, 0o700) + Dir.mkdir(datapath, 0o700) end end it "tests mkdir_p with a new path" do - path = "/tmp/crystal_mkdir_ptest_#{Process.pid}/" - Dir.mkdir_p(path) - Dir.exists?(path).should be_true - path = File.join({path, "a", "b", "c"}) - Dir.mkdir_p(path) - Dir.exists?(path).should be_true + with_tempfile("mkdir_p") do |path| + Dir.mkdir_p(path) + Dir.exists?(path).should be_true + path = File.join(path, "a", "b", "c") + Dir.mkdir_p(path) + Dir.exists?(path).should be_true + end end it "tests mkdir_p with an existing path" do - Dir.mkdir_p(__DIR__) + Dir.mkdir_p(datapath) expect_raises Errno do - Dir.mkdir_p(__FILE__) + Dir.mkdir_p(datapath("dir", "f1.txt")) end end it "tests rmdir with an nonexistent path" do - expect_raises Errno do - Dir.rmdir("/tmp/crystal_mkdir_test_#{Process.pid}/") + with_tempfile("nonexistant") do |path| + expect_raises Errno do + Dir.rmdir(path) + end end end it "tests rmdir with a path that cannot be removed" do expect_raises Errno do - Dir.rmdir(__DIR__) + Dir.rmdir(datapath) end end describe "glob" do it "tests glob with a single pattern" do - Dir["#{__DIR__}/data/dir/*.txt"].sort.should eq [ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "g2.txt"), + Dir["#{datapath}/dir/*.txt"].sort.should eq [ + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "g2.txt"), ].sort end it "tests glob with multiple patterns" do - Dir["#{__DIR__}/data/dir/*.txt", "#{__DIR__}/data/dir/subdir/*.txt"].sort.should eq [ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "g2.txt"), - File.join(__DIR__, "data", "dir", "subdir", "f1.txt"), + Dir["#{datapath}/dir/*.txt", "#{datapath}/dir/subdir/*.txt"].sort.should eq [ + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "g2.txt"), + datapath("dir", "subdir", "f1.txt"), ].sort end it "tests glob with a single pattern with block" do result = [] of String - Dir.glob("#{__DIR__}/data/dir/*.txt") do |filename| + Dir.glob("#{datapath}/dir/*.txt") do |filename| result << filename end result.sort.should eq([ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "g2.txt"), + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "g2.txt"), ].sort) end it "tests a recursive glob" do - Dir["#{__DIR__}/data/dir/**/*.txt"].sort.should eq [ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "g2.txt"), - File.join(__DIR__, "data", "dir", "subdir", "f1.txt"), - File.join(__DIR__, "data", "dir", "subdir", "subdir2", "f2.txt"), + Dir["#{datapath}/dir/**/*.txt"].sort.should eq [ + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "g2.txt"), + datapath("dir", "subdir", "f1.txt"), + datapath("dir", "subdir", "subdir2", "f2.txt"), ].sort end it "tests a recursive glob with '?'" do - Dir["#{__DIR__}/data/dir/f?.tx?"].sort.should eq [ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "f3.txx"), + Dir["#{datapath}/dir/f?.tx?"].sort.should eq [ + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "f3.txx"), ].sort end it "tests a recursive glob with alternation" do - Dir["#{__DIR__}/data/{dir,dir/subdir}/*.txt"].sort.should eq [ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "g2.txt"), - File.join(__DIR__, "data", "dir", "subdir", "f1.txt"), + Dir["#{datapath}/{dir,dir/subdir}/*.txt"].sort.should eq [ + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "g2.txt"), + datapath("dir", "subdir", "f1.txt"), ].sort end it "tests a glob with recursion inside alternation" do - Dir["#{__DIR__}/data/dir/{**/*.txt,**/*.txx}"].sort.should eq [ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "f3.txx"), - File.join(__DIR__, "data", "dir", "g2.txt"), - File.join(__DIR__, "data", "dir", "subdir", "f1.txt"), - File.join(__DIR__, "data", "dir", "subdir", "subdir2", "f2.txt"), + Dir["#{datapath}/dir/{**/*.txt,**/*.txx}"].sort.should eq [ + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "f3.txx"), + datapath("dir", "g2.txt"), + datapath("dir", "subdir", "f1.txt"), + datapath("dir", "subdir", "subdir2", "f2.txt"), ].sort end it "tests a recursive glob with nested alternations" do - Dir["#{__DIR__}/data/dir/{?1.*,{f,g}2.txt}"].sort.should eq [ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "g2.txt"), + Dir["#{datapath}/dir/{?1.*,{f,g}2.txt}"].sort.should eq [ + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "g2.txt"), ].sort end it "tests with *" do - Dir["#{__DIR__}/data/dir/*"].sort.should eq [ - File.join(__DIR__, "data", "dir", "dots"), - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "f3.txx"), - File.join(__DIR__, "data", "dir", "g2.txt"), - File.join(__DIR__, "data", "dir", "subdir"), - File.join(__DIR__, "data", "dir", "subdir2"), + Dir["#{datapath}/dir/*"].sort.should eq [ + datapath("dir", "dots"), + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "f3.txx"), + datapath("dir", "g2.txt"), + datapath("dir", "subdir"), + datapath("dir", "subdir2"), ].sort end it "tests with ** (same as *)" do - Dir["#{__DIR__}/data/dir/**"].sort.should eq [ - File.join(__DIR__, "data", "dir", "dots"), - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "f3.txx"), - File.join(__DIR__, "data", "dir", "g2.txt"), - File.join(__DIR__, "data", "dir", "subdir"), - File.join(__DIR__, "data", "dir", "subdir2"), + Dir["#{datapath}/dir/**"].sort.should eq [ + datapath("dir", "dots"), + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "f3.txx"), + datapath("dir", "g2.txt"), + datapath("dir", "subdir"), + datapath("dir", "subdir2"), ].sort end it "tests with */" do - Dir["#{__DIR__}/data/dir/*/"].sort.should eq [ - File.join(__DIR__, "data", "dir", "dots", ""), - File.join(__DIR__, "data", "dir", "subdir", ""), - File.join(__DIR__, "data", "dir", "subdir2", ""), + Dir["#{datapath}/dir/*/"].sort.should eq [ + datapath("dir", "dots", ""), + datapath("dir", "subdir", ""), + datapath("dir", "subdir2", ""), ].sort end it "tests glob with a single pattern with extra slashes" do - Dir["#{__DIR__}////data////dir////*.txt"].sort.should eq [ - File.join(__DIR__, "data", "dir", "f1.txt"), - File.join(__DIR__, "data", "dir", "f2.txt"), - File.join(__DIR__, "data", "dir", "g2.txt"), + Dir["spec/std////data////dir////*.txt"].sort.should eq [ + datapath("dir", "f1.txt"), + datapath("dir", "f2.txt"), + datapath("dir", "g2.txt"), ].sort end it "tests with relative path" do - Dir["spec/std/data/dir/*/"].sort.should eq [ - File.join("spec", "std", "data", "dir", "dots", ""), - File.join("spec", "std", "data", "dir", "subdir", ""), - File.join("spec", "std", "data", "dir", "subdir2", ""), + Dir["#{datapath}/dir/*/"].sort.should eq [ + datapath("dir", "dots", ""), + datapath("dir", "subdir", ""), + datapath("dir", "subdir2", ""), ].sort end it "tests with relative path (starts with .)" do - Dir["./spec/std/data/dir/*/"].sort.should eq [ + Dir["./#{datapath}/dir/*/"].sort.should eq [ File.join(".", "spec", "std", "data", "dir", "dots", ""), File.join(".", "spec", "std", "data", "dir", "subdir", ""), File.join(".", "spec", "std", "data", "dir", "subdir2", ""), @@ -225,8 +230,8 @@ describe "Dir" do end it "tests with relative path (starts with ..)" do - base_path = File.join("..", File.basename(File.dirname(File.dirname(__DIR__))), "spec", "std", "data", "dir") - Dir["../#{File.basename(File.dirname(File.dirname(__DIR__)))}/spec/std/data/dir/*/"].sort.should eq [ + base_path = File.join("..", File.basename(Dir.current), "spec", "std", "data", "dir") + Dir["../#{File.basename(Dir.current)}/#{datapath}/dir/*/"].sort.should eq [ File.join(base_path, "dots", ""), File.join(base_path, "subdir", ""), File.join(base_path, "subdir2", ""), @@ -235,23 +240,23 @@ describe "Dir" do it "tests with relative path starting recursive" do Dir["**/dir/*/"].sort.should eq [ - File.join("spec", "std", "data", "dir", "dots", ""), - File.join("spec", "std", "data", "dir", "subdir", ""), - File.join("spec", "std", "data", "dir", "subdir2", ""), + datapath("dir", "dots", ""), + datapath("dir", "subdir", ""), + datapath("dir", "subdir2", ""), ].sort end it "matches symlinks" do - link = File.join(__DIR__, "data", "f1_link.txt") - non_link = File.join(__DIR__, "data", "non_link.txt") + link = datapath("f1_link.txt") + non_link = datapath("non_link.txt") - File.symlink(File.join(__DIR__, "data", "dir", "f1.txt"), link) - File.symlink(File.join(__DIR__, "data", "dir", "nonexisting"), non_link) + File.symlink(datapath("dir", "f1.txt"), link) + File.symlink(datapath("dir", "nonexisting"), non_link) begin - Dir["#{__DIR__}/data/*_link.txt"].sort.should eq [ - File.join(__DIR__, "data", "f1_link.txt"), - File.join(__DIR__, "data", "non_link.txt"), + Dir["#{datapath}/*_link.txt"].sort.should eq [ + datapath("f1_link.txt"), + datapath("non_link.txt"), ].sort ensure File.delete link @@ -274,39 +279,39 @@ describe "Dir" do end it "pattern ending with .." do - Dir["#{__DIR__}/data/dir/.."].sort.should eq [ - File.join(__DIR__, "data", "dir", ".."), + Dir["#{datapath}/dir/.."].sort.should eq [ + datapath("dir", ".."), ] end it "pattern ending with */.." do - Dir["#{__DIR__}/data/dir/*/.."].sort.should eq [ - File.join(__DIR__, "data", "dir", "dots", ".."), - File.join(__DIR__, "data", "dir", "subdir", ".."), - File.join(__DIR__, "data", "dir", "subdir2", ".."), + Dir["#{datapath}/dir/*/.."].sort.should eq [ + datapath("dir", "dots", ".."), + datapath("dir", "subdir", ".."), + datapath("dir", "subdir2", ".."), ] end it "pattern ending with ." do - Dir["#{__DIR__}/data/dir/."].sort.should eq [ - File.join(__DIR__, "data", "dir", "."), + Dir["#{datapath}/dir/."].sort.should eq [ + datapath("dir", "."), ] end it "pattern ending with */." do - Dir["#{__DIR__}/data/dir/*/."].sort.should eq [ - File.join(__DIR__, "data", "dir", "dots", "."), - File.join(__DIR__, "data", "dir", "subdir", "."), - File.join(__DIR__, "data", "dir", "subdir2", "."), + Dir["#{datapath}/dir/*/."].sort.should eq [ + datapath("dir", "dots", "."), + datapath("dir", "subdir", "."), + datapath("dir", "subdir2", "."), ] end context "match_hidden: true" do it "matches hidden files" do - Dir.glob("#{__DIR__}/data/dir/dots/**/*", match_hidden: true).sort.should eq [ - File.join(__DIR__, "data", "dir", "dots", ".dot.hidden"), - File.join(__DIR__, "data", "dir", "dots", ".hidden"), - File.join(__DIR__, "data", "dir", "dots", ".hidden", "f1.txt"), + Dir.glob("#{datapath}/dir/dots/**/*", match_hidden: true).sort.should eq [ + datapath("dir", "dots", ".dot.hidden"), + datapath("dir", "dots", ".hidden"), + datapath("dir", "dots", ".hidden", "f1.txt"), ].sort end end @@ -341,70 +346,70 @@ describe "Dir" do it "opens with new" do filenames = [] of String - dir = Dir.new(__DIR__) + dir = Dir.new(datapath("dir")) dir.each do |filename| filenames << filename end.should be_nil dir.close - filenames.includes?("dir_spec.cr").should be_true + filenames.includes?("f1.txt").should be_true end it "opens with open" do filenames = [] of String - Dir.open(__DIR__) do |dir| + Dir.open(datapath("dir")) do |dir| dir.each do |filename| filenames << filename end.should be_nil end - filenames.includes?("dir_spec.cr").should be_true + filenames.includes?("f1.txt").should be_true end it "lists entries" do - filenames = Dir.entries(__DIR__) + filenames = Dir.entries(datapath("dir")) filenames.includes?(".").should be_true filenames.includes?("..").should be_true - filenames.includes?("dir_spec.cr").should be_true + filenames.includes?("f1.txt").should be_true end it "lists children" do - Dir.children(__DIR__).should eq(Dir.entries(__DIR__) - %w(. ..)) + Dir.children(datapath("dir")).should eq(Dir.entries(datapath("dir")) - %w(. ..)) end it "does to_s" do - Dir.new(__DIR__).to_s.should eq("#") + Dir.new(datapath("dir")).to_s.should eq("#") end it "gets dir iterator" do filenames = [] of String - iter = Dir.new(__DIR__).each + iter = Dir.new(datapath("dir")).each iter.each do |filename| filenames << filename end filenames.includes?(".").should be_true filenames.includes?("..").should be_true - filenames.includes?("dir_spec.cr").should be_true + filenames.includes?("f1.txt").should be_true end it "gets child iterator" do filenames = [] of String - iter = Dir.new(__DIR__).each_child + iter = Dir.new(datapath("dir")).each_child iter.each do |filename| filenames << filename end filenames.includes?(".").should be_false filenames.includes?("..").should be_false - filenames.includes?("dir_spec.cr").should be_true + filenames.includes?("f1.txt").should be_true end it "double close doesn't error" do - dir = Dir.open(__DIR__) do |dir| + dir = Dir.open(datapath("dir")) do |dir| dir.close dir.close end diff --git a/spec/std/file_spec.cr b/spec/std/file_spec.cr index 650f3f44807f..c93039be9a81 100644 --- a/spec/std/file_spec.cr +++ b/spec/std/file_spec.cr @@ -1,5 +1,4 @@ -require "spec" -require "tempfile" +require "./spec_helper" private def base Dir.current @@ -30,13 +29,13 @@ end describe "File" do it "gets path" do - path = "#{__DIR__}/data/test_file.txt" + path = datapath("test_file.txt") file = File.new path file.path.should eq(path) end it "reads entire file" do - str = File.read "#{__DIR__}/data/test_file.txt" + str = File.read datapath("test_file.txt") str.should eq("Hello World\n" * 20) end @@ -50,20 +49,20 @@ describe "File" do {% end %} it "reads lines from file" do - lines = File.read_lines "#{__DIR__}/data/test_file.txt" + lines = File.read_lines datapath("test_file.txt") lines.size.should eq(20) lines.first.should eq("Hello World") end it "reads lines from file with chomp = false" do - lines = File.read_lines "#{__DIR__}/data/test_file.txt", chomp: false + lines = File.read_lines datapath("test_file.txt"), chomp: false lines.size.should eq(20) lines.first.should eq("Hello World\n") end it "reads lines from file with each" do idx = 0 - File.each_line("#{__DIR__}/data/test_file.txt") do |line| + File.each_line(datapath("test_file.txt")) do |line| if idx == 0 line.should eq("Hello World") end @@ -74,7 +73,7 @@ describe "File" do it "reads lines from file with each, chomp = false" do idx = 0 - File.each_line("#{__DIR__}/data/test_file.txt", chomp: false) do |line| + File.each_line(datapath("test_file.txt"), chomp: false) do |line| if idx == 0 line.should eq("Hello World\n") end @@ -85,7 +84,7 @@ describe "File" do it "reads lines from file with each as iterator" do idx = 0 - File.each_line("#{__DIR__}/data/test_file.txt").each do |line| + File.each_line(datapath("test_file.txt")).each do |line| if idx == 0 line.should eq("Hello World") end @@ -96,7 +95,7 @@ describe "File" do it "reads lines from file with each as iterator, chomp = false" do idx = 0 - File.each_line("#{__DIR__}/data/test_file.txt", chomp: false).each do |line| + File.each_line(datapath("test_file.txt"), chomp: false).each do |line| if idx == 0 line.should eq("Hello World\n") end @@ -107,24 +106,23 @@ describe "File" do describe "empty?" do it "gives true when file is empty" do - File.empty?("#{__DIR__}/data/blank_test_file.txt").should be_true + File.empty?(datapath("blank_test_file.txt")).should be_true end it "gives false when file is not empty" do - File.empty?("#{__DIR__}/data/test_file.txt").should be_false + File.empty?(datapath("test_file.txt")).should be_false end it "raises an error when the file does not exist" do - filename = "#{__DIR__}/data/non_existing_file.txt" + filename = datapath("non_existing_file.txt") expect_raises(Errno, /Error determining size/) do File.empty?(filename) end end it "raises an error when a component of the path is a file" do - filename = "#{__DIR__}/data/non_existing_file.txt" ex = expect_raises(Errno, /Error determining size/) do - File.empty?("#{__FILE__}/") + File.empty?(datapath("test_file.txt", "")) end ex.errno.should eq(Errno::ENOTDIR) end @@ -132,160 +130,151 @@ describe "File" do describe "exists?" do it "gives true" do - File.exists?("#{__DIR__}/data/test_file.txt").should be_true + File.exists?(datapath("test_file.txt")).should be_true end it "gives false" do - File.exists?("#{__DIR__}/data/non_existing_file.txt").should be_false + File.exists?(datapath("non_existing_file.txt")).should be_false end it "gives false when a component of the path is a file" do - File.exists?("#{__FILE__}/").should be_false + File.exists?(datapath("dir", "test_file.txt", "")).should be_false end end describe "executable?" do it "gives false" do - File.executable?("#{__DIR__}/data/test_file.txt").should be_false + File.executable?(datapath("test_file.txt")).should be_false end it "gives false when the file doesn't exist" do - File.executable?("#{__DIR__}/data/non_existing_file.txt").should be_false + File.executable?(datapath("non_existing_file.txt")).should be_false end it "gives false when a component of the path is a file" do - File.executable?("#{__FILE__}/").should be_false + File.executable?(datapath("dir", "test_file.txt", "")).should be_false end end describe "readable?" do it "gives true" do - File.readable?("#{__DIR__}/data/test_file.txt").should be_true + File.readable?(datapath("test_file.txt")).should be_true end it "gives false when the file doesn't exist" do - File.readable?("#{__DIR__}/data/non_existing_file.txt").should be_false + File.readable?(datapath("non_existing_file.txt")).should be_false end it "gives false when a component of the path is a file" do - File.readable?("#{__FILE__}/").should be_false + File.readable?(datapath("dir", "test_file.txt", "")).should be_false end end describe "writable?" do it "gives true" do - File.writable?("#{__DIR__}/data/test_file.txt").should be_true + File.writable?(datapath("test_file.txt")).should be_true end it "gives false when the file doesn't exist" do - File.writable?("#{__DIR__}/data/non_existing_file.txt").should be_false + File.writable?(datapath("non_existing_file.txt")).should be_false end it "gives false when a component of the path is a file" do - File.writable?("#{__FILE__}/").should be_false + File.writable?(datapath("dir", "test_file.txt", "")).should be_false end end describe "file?" do it "gives true" do - File.file?("#{__DIR__}/data/test_file.txt").should be_true + File.file?(datapath("test_file.txt")).should be_true end it "gives false" do - File.file?("#{__DIR__}/data").should be_false + File.file?(datapath("nonexistent_dir")).should be_false end it "gives false when the file doesn't exist" do - File.file?("#{__DIR__}/data/non_existing_file.txt").should be_false + File.file?(datapath("non_existing_file.txt")).should be_false end it "gives false when a component of the path is a file" do - File.file?("#{__FILE__}/").should be_false + File.file?(datapath("dir", "test_file.txt", "")).should be_false end end describe "directory?" do it "gives true" do - File.directory?("#{__DIR__}/data").should be_true + File.directory?(datapath).should be_true end it "gives false" do - File.directory?("#{__DIR__}/data/test_file.txt").should be_false + File.directory?(datapath("test_file.txt")).should be_false end it "gives false when the directory doesn't exist" do - File.directory?("#{__DIR__}/data/non_existing").should be_false + File.directory?(datapath("non_existing")).should be_false end it "gives false when a component of the path is a file" do - File.directory?("#{__FILE__}/").should be_false + File.directory?(datapath("dir", "test_file.txt", "")).should be_false end end describe "link" do it "creates a hard link" do - in_path = "#{__DIR__}/data/test_file.txt" - out_path = "#{__DIR__}/data/test_file_link.txt" - begin + with_tempfile("hard_link_source.txt", "hard_link_target.txt") do |in_path, out_path| + File.write(in_path, "") File.link(in_path, out_path) File.exists?(out_path).should be_true File.symlink?(out_path).should be_false File.same?(in_path, out_path).should be_true - ensure - File.delete(out_path) if File.exists?(out_path) end end end describe "same?" do it "compares following symlinks only if requested" do - file = "#{__DIR__}/data/test_file.txt" - symlink = "#{__DIR__}/data/test_file_symlink.txt" - other = "#{__DIR__}/data/test_file.ini" + file = File.expand_path(datapath("test_file.txt")) + other = File.expand_path(datapath("test_file.ini")) - begin + with_tempfile("test_file_symlink.txt") do |symlink| File.symlink(file, symlink) File.same?(file, symlink).should be_false File.same?(file, symlink, follow_symlinks: true).should be_true File.same?(file, symlink, follow_symlinks: false).should be_false File.same?(file, other).should be_false - ensure - File.delete(symlink) if File.exists?(symlink) end end end describe "symlink" do it "creates a symbolic link" do - in_path = "#{__DIR__}/data/test_file.txt" - out_path = "#{__DIR__}/data/test_file_symlink.txt" - begin + in_path = File.expand_path(datapath("test_file.txt")) + with_tempfile("test_file_link.txt") do |out_path| File.symlink(in_path, out_path) File.symlink?(out_path).should be_true File.same?(in_path, out_path, follow_symlinks: true).should be_true - ensure - File.delete(out_path) if File.exists?(out_path) end end end describe "symlink?" do it "gives true" do - File.symlink?("#{__DIR__}/data/symlink.txt").should be_true + File.symlink?(datapath("symlink.txt")).should be_true end it "gives false" do - File.symlink?("#{__DIR__}/data/test_file.txt").should be_false - File.symlink?("#{__DIR__}/data/unknown_file.txt").should be_false + File.symlink?(datapath("test_file.txt")).should be_false + File.symlink?(datapath("unknown_file.txt")).should be_false end it "gives false when the symlink doesn't exist" do - File.symlink?("#{__DIR__}/data/non_existing_file.txt").should be_false + File.symlink?(datapath("non_existing_file.txt")).should be_false end it "gives false when a component of the path is a file" do - File.symlink?("#{__FILE__}/").should be_false + File.symlink?(datapath("dir", "test_file.txt", "")).should be_false end end @@ -344,7 +333,7 @@ describe "File" do describe "chmod" do it "changes file permissions" do - path = "#{__DIR__}/data/chmod.txt" + path = datapath("chmod.txt") begin File.write(path, "") File.chmod(path, 0o775) @@ -355,7 +344,7 @@ describe "File" do end it "changes dir permissions" do - path = "#{__DIR__}/data/chmod" + path = datapath("chmod") begin Dir.mkdir(path, 0o775) File.chmod(path, 0o664) @@ -366,7 +355,7 @@ describe "File" do end it "can take File::Permissions" do - path = "#{__DIR__}/data/chmod.txt" + path = datapath("chmod.txt") begin File.write(path, "") File.chmod(path, File::Permissions.flags(OwnerAll, GroupAll, OtherExecute, OtherRead)) @@ -377,33 +366,28 @@ describe "File" do end it "follows symlinks" do - path = "#{__DIR__}/data/chmod_destination.txt" - link = "#{__DIR__}/data/chmod.txt" - begin - File.write(path, "") - File.symlink(path, link) - File.chmod(link, 0o775) - File.info(link).permissions.should eq(File::Permissions.new(0o775)) - ensure - File.delete(path) if File.exists?(path) - File.delete(link) if File.symlink?(link) + with_tempfile("chmod-destination.txt", "chmod-source.txt") do |source_path, target_path| + File.write(source_path, "") + File.symlink(source_path, target_path) + File.chmod(target_path, 0o775) + File.info(target_path).permissions.should eq(File::Permissions.new(0o775)) end end it "raises when destination doesn't exist" do expect_raises(Errno) do - File.chmod("#{__DIR__}/data/unknown_chmod_path.txt", 0o664) + File.chmod(datapath("unknown_chmod_path.txt"), 0o664) end end end it "gets info for this file" do - info = File.info(__FILE__) + info = File.info(datapath("test_file.txt")) info.type.should eq(File::Type::File) end it "gets info for this directory" do - info = File.info(__DIR__) + info = File.info(datapath) info.type.should eq(File::Type::Directory) end @@ -413,12 +397,12 @@ describe "File" do end it "gets info for a symlink" do - info = File.info("#{__DIR__}/data/symlink.txt", follow_symlinks: false) + info = File.info(datapath("symlink.txt"), follow_symlinks: false) info.type.should eq(File::Type::Symlink) end it "gets info for open file" do - File.open(__FILE__, "r") do |file| + File.open(datapath("test_file.txt"), "r") do |file| info = file.info info.type.should eq(File::Type::File) end @@ -438,52 +422,49 @@ describe "File" do end it "gets info mtime for new file" do - tmp = Tempfile.new "tmp" - begin - tmp.info.modification_time.should be_close(Time.now, 5.seconds) - File.info(tmp.path).modification_time.should be_close(Time.now, 5.seconds) - ensure - tmp.delete + with_tempfile("mtime") do |path| + File.touch(path) + File.new(path).info.modification_time.should be_close(Time.now, 1.seconds) + File.info(path).modification_time.should be_close(Time.now, 1.seconds) end end describe "File::Info" do it "tests equal for the same file" do - File.info(__FILE__).should eq(File.info(__FILE__)) + File.info(datapath("test_file.txt")).should eq(File.info(datapath("test_file.txt"))) end it "tests equal for the same directory" do - File.info(__DIR__).should eq(File.info(__DIR__)) + File.info(datapath("dir")).should eq(File.info(datapath("dir"))) end it "tests unequal for different files" do - File.info(__FILE__).should_not eq(File.info("#{__DIR__}/data/test_file.txt")) + File.info(datapath("test_file.txt")).should_not eq(File.info(datapath("test_file.ini"))) end it "tests unequal for file and directory" do - File.info(__DIR__).should_not eq(File.info("#{__DIR__}/data/test_file.txt")) + File.info(datapath("dir")).should_not eq(File.info(datapath("test_file.txt"))) end end describe "size" do - it { File.size("#{__DIR__}/data/test_file.txt").should eq(240) } + it { File.size(datapath("test_file.txt")).should eq(240) } it do - File.open("#{__DIR__}/data/test_file.txt", "r") do |file| + File.open(datapath("test_file.txt"), "r") do |file| file.size.should eq(240) end end it "raises an error when the file does not exist" do - filename = "#{__DIR__}/data/non_existing_file.txt" + filename = datapath("non_existing_file.txt") expect_raises(Errno, /Error determining size/) do File.size(filename) end end it "raises an error when a component of the path is a file" do - filename = "#{__DIR__}/data/non_existing_file.txt" ex = expect_raises(Errno, /Error determining size/) do - File.size("#{__FILE__}/") + File.size(datapath("test_file.txt", "")) end ex.errno.should eq(Errno::ENOTDIR) end @@ -491,37 +472,40 @@ describe "File" do describe "delete" do it "deletes a file" do - filename = "#{__DIR__}/data/temp1.txt" - File.open(filename, "w") { } - File.exists?(filename).should be_true - File.delete(filename) - File.exists?(filename).should be_false + with_tempfile("delete-file.txt") do |filename| + File.open(filename, "w") { } + File.exists?(filename).should be_true + File.delete(filename) + File.exists?(filename).should be_false + end end it "raises errno when file doesn't exist" do - filename = "#{__DIR__}/data/temp1.txt" - expect_raises Errno do - File.delete(filename) + with_tempfile("nonexistant_file.txt") do |path| + expect_raises Errno do + File.delete(path) + end end end end describe "rename" do it "renames a file" do - filename = "#{__DIR__}/data/temp1.txt" - filename2 = "#{__DIR__}/data/temp2.txt" - File.open(filename, "w") { |f| f.puts "hello" } - File.rename(filename, filename2) - File.exists?(filename).should be_false - File.exists?(filename2).should be_true - File.read(filename2).strip.should eq("hello") - File.delete(filename2) + with_tempfile("rename-source.txt", "rename-target.txt") do |source_path, target_path| + File.write(source_path, "hello") + File.rename(source_path, target_path) + File.exists?(source_path).should be_false + File.exists?(target_path).should be_true + File.read(target_path).strip.should eq("hello") + File.delete(target_path) + end end it "raises if old file doesn't exist" do - filename = "#{__DIR__}/data/temp1.txt" - expect_raises Errno do - File.rename(filename, "#{filename}.new") + with_tempfile("rename-fail-source.txt", "rename-fail-target.txt") do |source_path, target_path| + expect_raises Errno do + File.rename(source_path, target_path) + end end end end @@ -594,7 +578,7 @@ describe "File" do it "converts a pathname to an absolute pathname, using ~ (home) as base (trailing /)" do prev_home = home begin - ENV["HOME"] = __DIR__ + "/" + ENV["HOME"] = File.expand_path(datapath("", "")) File.expand_path("~/").should eq(home) File.expand_path("~/..badfilename").should eq(File.join(home, "..badfilename")) File.expand_path("..").should eq("/#{base.split('/')[0...-1].join('/')}".gsub(%r{\A//}, "/")) @@ -637,147 +621,138 @@ describe "File" do end it "expands paths of symlinks" do - symlink_path = "/tmp/test_file_symlink.txt" - file_path = "#{__DIR__}/data/test_file.txt" - begin + file_path = File.expand_path(datapath("test_file.txt")) + with_tempfile("symlink.txt") do |symlink_path| File.symlink(file_path, symlink_path) real_symlink_path = File.real_path(symlink_path) real_file_path = File.real_path(file_path) real_symlink_path.should eq(real_file_path) - ensure - File.delete(symlink_path) if File.exists?(symlink_path) end end end describe "write" do it "can write to a file" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello") - File.read(filename).should eq("hello") - File.delete(filename) + with_tempfile("write.txt") do |path| + File.write(path, "hello") + File.read(path).should eq("hello") + end end it "writes bytes" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello".to_slice) - File.read(filename).should eq("hello") - File.delete(filename) + with_tempfile("write-bytes.txt") do |path| + File.write(path, "hello".to_slice) + File.read(path).should eq("hello") + end end it "writes io" do - filename = "#{__DIR__}/data/temp_write.txt" - File.open("#{__DIR__}/data/test_file.txt") do |file| - File.write(filename, file) + with_tempfile("write-io.txt") do |path| + File.open(datapath("test_file.txt")) do |file| + File.write(path, file) + end + File.read(path).should eq(File.read(datapath("test_file.txt"))) end - File.read(filename).should eq(File.read("#{__DIR__}/data/test_file.txt")) - File.delete(filename) end it "raises if trying to write to a file not opened for writing" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello") - expect_raises(IO::Error, "File not open for writing") do - File.open(filename) { |file| file << "hello" } + with_tempfile("write-fails.txt") do |path| + File.write(path, "hello") + expect_raises(IO::Error, "File not open for writing") do + File.open(path) { |file| file << "hello" } + end end - File.delete(filename) end it "can create a new file in append mode" do - filename = Tempfile.tempname - begin - File.write(filename, "hello", mode: "a") - File.read(filename).should eq("hello") - ensure - File.delete(filename) + with_tempfile("append-create.txt") do |path| + File.write(path, "hello", mode: "a") + File.read(path).should eq("hello") end end it "can append to an existing file" do - filename = Tempfile.tempname - begin - File.write(filename, "hello") - File.read(filename).should eq("hello") - File.write(filename, " world", mode: "a") - File.read(filename).should eq("hello world") - ensure - File.delete(filename) + with_tempfile("append-existing.txt") do |path| + File.write(path, "hello") + File.read(path).should eq("hello") + File.write(path, " world", mode: "a") + File.read(path).should eq("hello world") end end end it "does to_s" do - file = File.new(__FILE__) + file = File.new(datapath("test_file.txt")) file.to_s.should eq("#") - File.new(__FILE__).inspect.should eq("#") + file.inspect.should eq("#") end describe "close" do it "is not closed when opening" do - file = File.new(__FILE__) + file = File.new(datapath("test_file.txt")) file.closed?.should be_false end it "is closed when closed" do - file = File.new(__FILE__) + file = File.new(datapath("test_file.txt")) file.close file.closed?.should be_true end it "should not raise when closing twice" do - file = File.new(__FILE__) + file = File.new(datapath("test_file.txt")) file.close file.close end it "does to_s when closed" do - file = File.new(__FILE__) + file = File.new(datapath("test_file.txt")) file.close file.to_s.should eq("#") - file.inspect.should eq("#") + file.inspect.should eq("#") end end it "opens with perm (int)" do - filename = "#{__DIR__}/data/temp_write.txt" - perm = 0o600 - File.open(filename, "w", perm) do |file| - file.info.permissions.should eq(File::Permissions.new(perm)) + with_tempfile("write_with_perm-int.txt") do |path| + perm = 0o600 + File.open(path, "w", perm) do |file| + file.info.permissions.should eq(File::Permissions.new(perm)) + end end - File.delete filename end it "opens with perm (File::Permissions)" do - filename = "#{__DIR__}/data/temp_write.txt" - perm = File::Permissions.flags(OwnerRead, OwnerWrite) - File.open(filename, "w", perm) do |file| - file.info.permissions.should eq(perm) + with_tempfile("write_with_perm.txt") do |path| + perm = File::Permissions.flags(OwnerRead, OwnerWrite) + File.open(path, "w", perm) do |file| + file.info.permissions.should eq(perm) + end end - File.delete filename end it "clears the read buffer after a seek" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) file.gets(5).should eq("Hello") file.seek(1) file.gets(4).should eq("ello") end it "seeks from the current position" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) file.gets(5) file.seek(-4, IO::Seek::Current) file.tell.should eq(1) end it "raises if invoking seek with a closed file" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) file.close expect_raises(IO::Error, "Closed stream") { file.seek(1) } end it "returns the current read position with tell" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) file.tell.should eq(0) file.gets(5).should eq("Hello") file.tell.should eq(5) @@ -786,7 +761,7 @@ describe "File" do end it "can navigate with pos" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) file.pos = 3 file.gets(2).should eq("lo") file.pos -= 4 @@ -794,13 +769,13 @@ describe "File" do end it "raises if invoking tell with a closed file" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) file.close expect_raises(IO::Error, "Closed stream") { file.tell } end it "iterates with each_char" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) i = 0 file.each_char do |char| case i @@ -814,7 +789,7 @@ describe "File" do end it "iterates with each_byte" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) i = 0 file.each_byte do |byte| case i @@ -828,7 +803,7 @@ describe "File" do end it "rewinds" do - file = File.new("#{__DIR__}/data/test_file.txt") + file = File.new(datapath("test_file.txt")) content = file.gets_to_end content.size.should_not eq(0) file.rewind @@ -837,47 +812,47 @@ describe "File" do describe "truncate" do it "truncates" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "0123456789") - File.open(filename, "r+") do |f| - f.gets_to_end.should eq("0123456789") - f.rewind - f.puts("333") - f.truncate(4) - end + with_tempfile("truncate.txt") do |path| + File.write(path, "0123456789") + File.open(path, "r+") do |f| + f.gets_to_end.should eq("0123456789") + f.rewind + f.puts("333") + f.truncate(4) + end - File.read(filename).should eq("333\n") - File.delete filename + File.read(path).should eq("333\n") + end end it "truncates completely when no size is passed" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "0123456789") - File.open(filename, "r+") do |f| - f.puts("333") - f.truncate - end + with_tempfile("truncate-no_size.txt") do |path| + File.write(path, "0123456789") + File.open(path, "r+") do |f| + f.puts("333") + f.truncate + end - File.read(filename).should eq("") - File.delete filename + File.read(path).should eq("") + end end it "requires a file opened for writing" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "0123456789") - File.open(filename, "r") do |f| - expect_raises(Errno) do - f.truncate(4) + with_tempfile("truncate-opened.txt") do |path| + File.write(path, "0123456789") + File.open(path, "r") do |f| + expect_raises(Errno) do + f.truncate(4) + end end end - File.delete filename end end describe "flock" do it "exlusively locks a file" do - File.open(__FILE__) do |file1| - File.open(__FILE__) do |file2| + File.open(datapath("test_file.txt")) do |file1| + File.open(datapath("test_file.txt")) do |file2| file1.flock_exclusive do # BUG: check for EWOULDBLOCK when exception filters are implemented expect_raises(Errno) do @@ -889,8 +864,8 @@ describe "File" do end it "shared locks a file" do - File.open(__FILE__) do |file1| - File.open(__FILE__) do |file2| + File.open(datapath("test_file.txt")) do |file1| + File.open(datapath("test_file.txt")) do |file2| file1.flock_shared do file2.flock_shared(blocking: false) { } end @@ -900,7 +875,7 @@ describe "File" do end it "reads at offset" do - filename = "#{__DIR__}/data/test_file.txt" + filename = datapath("test_file.txt") file = File.open(filename) file.read_at(6, 100) do |io| io.gets_to_end.should eq("World\nHello World\nHello World\nHello World\nHello World\nHello World\nHello World\nHello World\nHello Worl") @@ -911,25 +886,24 @@ describe "File" do end it "raises when reading at offset outside of bounds" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello world") + with_tempfile("read-out_of_bounds") do |path| + File.write(path, "hello world") - begin - File.open(filename) do |io| - expect_raises(ArgumentError, "Negative bytesize") do - io.read_at(3, -1) { } - end + begin + File.open(path) do |io| + expect_raises(ArgumentError, "Negative bytesize") do + io.read_at(3, -1) { } + end - expect_raises(ArgumentError, "Offset out of bounds") do - io.read_at(12, 1) { } - end + expect_raises(ArgumentError, "Offset out of bounds") do + io.read_at(12, 1) { } + end - expect_raises(ArgumentError, "Bytesize out of bounds") do - io.read_at(6, 6) { } + expect_raises(ArgumentError, "Bytesize out of bounds") do + io.read_at(6, 6) { } + end end end - ensure - File.delete(filename) end end @@ -1041,48 +1015,48 @@ describe "File" do describe "encoding" do it "writes with encoding" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello", encoding: "UCS-2LE") - File.read(filename).to_slice.should eq("hello".encode("UCS-2LE")) - File.delete(filename) + with_tempfile("encoding-write.txt") do |path| + File.write(path, "hello", encoding: "UCS-2LE") + File.read(path).to_slice.should eq("hello".encode("UCS-2LE")) + end end it "reads with encoding" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello", encoding: "UCS-2LE") - File.read(filename, encoding: "UCS-2LE").should eq("hello") - File.delete(filename) + with_tempfile("encoding-read.txt") do |path| + File.write(path, "hello", encoding: "UCS-2LE") + File.read(path, encoding: "UCS-2LE").should eq("hello") + end end it "opens with encoding" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello", encoding: "UCS-2LE") - File.open(filename, encoding: "UCS-2LE") do |file| - file.gets_to_end.should eq("hello") + with_tempfile("encoding-open.txt") do |path| + File.write(path, "hello", encoding: "UCS-2LE") + File.open(path, encoding: "UCS-2LE") do |file| + file.gets_to_end.should eq("hello") + end end - File.delete filename end it "does each line with encoding" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello", encoding: "UCS-2LE") - File.each_line(filename, encoding: "UCS-2LE") do |line| - line.should eq("hello") + with_tempfile("encoding-each_line.txt") do |path| + File.write(path, "hello", encoding: "UCS-2LE") + File.each_line(path, encoding: "UCS-2LE") do |line| + line.should eq("hello") + end end - File.delete filename end it "reads lines with encoding" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "hello", encoding: "UCS-2LE") - File.read_lines(filename, encoding: "UCS-2LE").should eq(["hello"]) - File.delete filename + with_tempfile("encoding-read_lines.txt") do |path| + File.write(path, "hello", encoding: "UCS-2LE") + File.read_lines(path, encoding: "UCS-2LE").should eq(["hello"]) + end end end describe "closed stream" do it "raises if writing on a closed stream" do - io = File.open(__FILE__, "r") + io = File.open(datapath("test_file.txt"), "r") io.close expect_raises(IO::Error, "Closed stream") { io.gets_to_end } @@ -1097,18 +1071,17 @@ describe "File" do describe "utime" do it "sets times with utime" do - filename = "#{__DIR__}/data/temp_write.txt" - File.write(filename, "") - - atime = Time.utc(2000, 1, 2) - mtime = Time.utc(2000, 3, 4) + with_tempfile("utime-set.txt") do |path| + File.write(path, "") - File.utime(atime, mtime, filename) + atime = Time.utc(2000, 1, 2) + mtime = Time.utc(2000, 3, 4) - info = File.info(filename) - info.modification_time.should eq(mtime) + File.utime(atime, mtime, path) - File.delete filename + info = File.info(path) + info.modification_time.should eq(mtime) + end end it "raises if file not found" do @@ -1116,52 +1089,44 @@ describe "File" do mtime = Time.utc(2000, 3, 4) expect_raises Errno, "Error setting time to file" do - File.utime(atime, mtime, "#{__DIR__}/nonexistent_file") + File.utime(atime, mtime, datapath("nonexistent_file.txt")) end end end describe "touch" do it "creates file if it doesn't exists" do - filename = "#{__DIR__}/data/temp_touch.txt" - begin - File.exists?(filename).should be_false - File.touch(filename) - File.exists?(filename).should be_true - ensure - File.delete filename + with_tempfile("touch-create.txt") do |path| + File.exists?(path).should be_false + File.touch(path) + File.exists?(path).should be_true end end it "sets file times to given time" do - filename = "#{__DIR__}/data/temp_touch.txt" time = Time.utc(2000, 3, 4) - begin - File.touch(filename, time) + with_tempfile("touch-times.txt") do |path| + File.touch(path, time) - info = File.info(filename) + info = File.info(path) info.modification_time.should eq(time) - ensure - File.delete filename end end it "sets file times to Time.now if no time argument given" do - filename = "#{__DIR__}/data/temp_touch.txt" - time = Time.now - begin - File.touch(filename) + with_tempfile("touch-time_now.txt") do |path| + File.touch(path) - info = File.info(filename) - info.modification_time.should be_close(time, 1.second) - ensure - File.delete filename + info = File.info(path) + info.modification_time.should be_close(Time.now, 1.second) end end it "raises if path contains non-existent directory" do - expect_raises Errno, "Error opening file" do - File.touch("/tmp/non/existent/directory/test.tmp") + with_tempfile(File.join("nonexistant-dir", "touch.txt")) do |path| + expect_raises Errno, "Error opening file" do + File.touch(path) + end end end diff --git a/spec/std/file_utils_spec.cr b/spec/std/file_utils_spec.cr index 648fb1ab4298..b6e7a9491c8a 100644 --- a/spec/std/file_utils_spec.cr +++ b/spec/std/file_utils_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "./spec_helper" require "file_utils" private class OneByOneIO < IO @@ -58,15 +58,15 @@ describe "FileUtils" do describe "cmp" do it "compares two equal files" do FileUtils.cmp( - File.join(__DIR__, "data/test_file.txt"), - File.join(__DIR__, "data/test_file.txt") + datapath("test_file.txt"), + datapath("test_file.txt") ).should be_true end it "compares two different files" do FileUtils.cmp( - File.join(__DIR__, "data/test_file.txt"), - File.join(__DIR__, "data/test_file.ini") + datapath("test_file.txt"), + datapath("test_file.ini") ).should be_false end @@ -97,49 +97,35 @@ describe "FileUtils" do describe "touch" do it "creates file if it doesn't exists" do - filename = File.join(__DIR__, "data/test_touch.txt") - begin - File.exists?(filename).should be_false - FileUtils.touch(filename) - File.exists?(filename).should be_true - ensure - File.delete filename + with_tempfile("touch.txt") do |path| + File.exists?(path).should be_false + FileUtils.touch(path) + File.exists?(path).should be_true end end - it "creates multiple files if they doesn't exists" do - paths = [ - File.join(__DIR__, "data/test_touch_1.txt"), - File.join(__DIR__, "data/test_touch_2.txt"), - File.join(__DIR__, "data/test_touch_3.txt"), - ] - begin + it "creates multiple files if they don't exists" do + with_tempfile("touch1", "touch2", "touch3") do |path1, path2, path3| + paths = [path1, path2, path3] paths.each { |path| File.exists?(path).should be_false } FileUtils.touch(paths) paths.each { |path| File.exists?(path).should be_true } - ensure - FileUtils.rm_rf(paths) end end end describe "cp" do it "copies a file" do - src_path = File.join(__DIR__, "data/test_file.txt") - out_path = File.join(__DIR__, "data/test_file_cp.txt") - begin + src_path = datapath("test_file.txt") + with_tempfile("cp.txt") do |out_path| FileUtils.cp(src_path, out_path) File.exists?(out_path).should be_true FileUtils.cmp(src_path, out_path).should be_true - ensure - File.delete(out_path) if File.exists?(out_path) end end it "copies permissions" do - src_path = File.join(__DIR__, "data/new_test_file.txt") - out_path = File.join(__DIR__, "data/test_file_cp.txt") - begin + with_tempfile("cp-permissions-src.txt", "cp-permissions-out.txt") do |src_path, out_path| File.write(src_path, "foo") File.chmod(src_path, 0o700) @@ -147,45 +133,34 @@ describe "FileUtils" do File.info(out_path).permissions.should eq(File::Permissions.new(0o700)) FileUtils.cmp(src_path, out_path).should be_true - ensure - File.delete(src_path) if File.exists?(out_path) - File.delete(out_path) if File.exists?(out_path) end end it "raises an error if the directory doesn't exists" do expect_raises(ArgumentError, "No such directory : not_existing_dir") do - FileUtils.cp({File.join(__DIR__, "data/test_file.text")}, "not_existing_dir") + FileUtils.cp({datapath("test_file.txt")}, "not_existing_dir") end end it "copies multiple files" do src_name1 = "test_file.txt" src_name2 = "test_file.ini" - src_path = File.join(__DIR__, "data") - out_path = File.join(__DIR__, "data/cps_path") - - begin - Dir.mkdir(out_path) rescue nil + src_path = datapath + with_tempfile("cp-multiple") do |out_path| + Dir.mkdir_p(out_path) FileUtils.cp({File.join(src_path, src_name1), File.join(src_path, src_name2)}, out_path) File.exists?(File.join(out_path, src_name1)).should be_true File.exists?(File.join(out_path, src_name2)).should be_true FileUtils.cmp(File.join(src_path, src_name1), File.join(out_path, src_name1)).should be_true FileUtils.cmp(File.join(src_path, src_name2), File.join(out_path, src_name2)).should be_true - ensure - FileUtils.rm_r(out_path) if File.exists?(out_path) end end end describe "cp_r" do it "copies a directory recursively" do - path = File.join(__DIR__, "data") - src_path = File.join(path, "cp_r_test") - dest_path = File.join(path, "cp_r_test_copied") - - begin - Dir.mkdir(src_path) + with_tempfile("cp_r-test", "cp_r-test-copied") do |src_path, dest_path| + Dir.mkdir_p(src_path) File.write(File.join(src_path, "a"), "") Dir.mkdir(File.join(src_path, "b")) File.write(File.join(src_path, "b/c"), "") @@ -193,19 +168,13 @@ describe "FileUtils" do FileUtils.cp_r(src_path, dest_path) File.exists?(File.join(dest_path, "a")).should be_true File.exists?(File.join(dest_path, "b/c")).should be_true - ensure - FileUtils.rm_r(src_path) if File.exists?(src_path) - FileUtils.rm_r(dest_path) if File.exists?(dest_path) end end end describe "rm_r" do it "deletes a directory recursively" do - data_path = File.join(__DIR__, "data") - path = File.join(data_path, "rm_r_test") - - begin + with_tempfile("rm_r") do |path| Dir.mkdir(path) File.write(File.join(path, "a"), "") Dir.mkdir(File.join(path, "b")) @@ -213,22 +182,14 @@ describe "FileUtils" do FileUtils.rm_r(path) Dir.exists?(path).should be_false - ensure - File.delete(File.join(path, "b/c")) if File.exists?(File.join(path, "b/c")) - File.delete(File.join(path, "a")) if File.exists?(File.join(path, "a")) - Dir.rmdir(File.join(path, "b")) if Dir.exists?(File.join(path, "b")) - Dir.rmdir(path) if Dir.exists?(path) end end it "doesn't follow symlinks" do - data_path = File.join(__DIR__, "data") - removed_path = File.join(data_path, "rm_r_test_removed") - linked_path = File.join(data_path, "rm_r_test_linked") - link_path = File.join(removed_path, "link") - file_path = File.join(linked_path, "file") + with_tempfile("rm_r-removed", "rm_r-linked") do |removed_path, linked_path| + link_path = File.join(removed_path, "link") + file_path = File.join(linked_path, "file") - begin Dir.mkdir(removed_path) Dir.mkdir(linked_path) File.symlink(linked_path, link_path) @@ -238,52 +199,47 @@ describe "FileUtils" do Dir.exists?(removed_path).should be_false Dir.exists?(linked_path).should be_true File.exists?(file_path).should be_true - ensure - File.delete(file_path) if File.exists?(file_path) - File.delete(link_path) if File.exists?(link_path) - Dir.rmdir(linked_path) if Dir.exists?(linked_path) - Dir.rmdir(removed_path) if Dir.exists?(removed_path) end end end describe "rm_rf" do it "delete recursively a directory" do - path = "/tmp/crystal_rm_rftest_#{Process.pid}/" - FileUtils.mkdir(path) - File.write(File.join(path, "a"), "") - FileUtils.mkdir(File.join(path, "b")) - FileUtils.rm_rf(path).should be_nil - Dir.exists?(path).should be_false + with_tempfile("rm_rf") do |path| + FileUtils.mkdir(path) + File.write(File.join(path, "a"), "") + FileUtils.mkdir(File.join(path, "b")) + FileUtils.rm_rf(path).should be_nil + Dir.exists?(path).should be_false + end end it "delete recursively multiple directory" do - path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/" - path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/" - FileUtils.mkdir(path1) - FileUtils.mkdir(path2) - File.write(File.join(path1, "a"), "") - File.write(File.join(path2, "a"), "") - FileUtils.mkdir(File.join(path1, "b")) - FileUtils.mkdir(File.join(path2, "b")) - FileUtils.rm_rf([path1, path2]).should be_nil - Dir.exists?(path1).should be_false - Dir.exists?(path2).should be_false + with_tempfile("rm_rf-multi1", "rm_rf-multi2") do |path1, path2| + FileUtils.mkdir(path1) + FileUtils.mkdir(path2) + File.write(File.join(path1, "a"), "") + File.write(File.join(path2, "a"), "") + FileUtils.mkdir(File.join(path1, "b")) + FileUtils.mkdir(File.join(path2, "b")) + FileUtils.rm_rf([path1, path2]).should be_nil + Dir.exists?(path1).should be_false + Dir.exists?(path2).should be_false + end end it "doesn't return error on non existing file" do - path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/" - path2 = File.join(path1, "a") - FileUtils.mkdir(path1) - FileUtils.rm_rf([path1, path2]).should be_nil + with_tempfile("rm_rf-nonexistent") do |path1| + path2 = File.join(path1, "a") + FileUtils.mkdir(path1) + FileUtils.rm_rf([path1, path2]).should be_nil + end end end describe "mv" do it "moves a file from one place to another" do - begin - path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/" - path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/" + with_tempfile("mv1", "mv2") do |path1, path2| FileUtils.mkdir([path1, path2]) path1 = File.join(path1, "a") path2 = File.join(path2, "b") @@ -291,24 +247,19 @@ describe "FileUtils" do FileUtils.mv(path1, path2).should be_nil File.exists?(path1).should be_false File.exists?(path2).should be_true - ensure - path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/" - path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/" - FileUtils.rm_rf([path1, path2]) end end it "raises an error if non correct arguments" do - expect_raises Errno do - FileUtils.mv("/tmp/crystal_mv_test/a", "/tmp/crystal_mv_test/b") + with_tempfile("mv-nonexitent") do |path| + expect_raises Errno do + FileUtils.mv(File.join(path, "a"), File.join(path, "b")) + end end end it "moves multiple files to one place" do - begin - path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/" - path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/" - path3 = "/tmp/crystal_rm_rftest_#{Process.pid + 2}/" + with_tempfile("mv-multi1", "mv-multi2", "mv-multi3") do |path1, path2, path3| FileUtils.mkdir([path1, path2, path3]) path1 = File.join(path1, "a") path2 = File.join(path2, "b") @@ -319,101 +270,87 @@ describe "FileUtils" do File.exists?(path2).should be_false File.exists?(File.join(path3, "a")).should be_true File.exists?(File.join(path3, "b")).should be_true - ensure - path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/" - path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/" - path3 = "/tmp/crystal_rm_rftest_#{Process.pid + 2}/" - FileUtils.rm_rf([path1, path2, path3]) end end it "raises an error if dest is non correct" do expect_raises ArgumentError do - FileUtils.mv(["/tmp/crystal_mv_test/a", "/tmp/crystal_mv_test/b"], "/tmp/crystal_not_here") + with_tempfile("mv-nonexistent") do |path| + FileUtils.mv([File.join(path, "a"), File.join(path, "b")], File.join(path, "c")) + end end end it "moves all existing files to destination" do - begin - path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/" - path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/" - path3 = "/tmp/crystal_rm_rftest_#{Process.pid + 2}/" - path4 = "/tmp/crystal_rm_rftest_#{Process.pid + 3}/a" - FileUtils.mkdir([path1, path2, path3]) + with_tempfile("mv-source", "mv-target") do |source_path, target_path| + path1 = File.join(source_path, "a") + path2 = File.join(source_path, "b") + path3 = File.join(source_path, "c", "sub") + + FileUtils.mkdir_p([path1, path2, target_path]) path1 = File.join(path1, "a") path2 = File.join(path2, "b") File.write(path1, "") File.write(path2, "") - FileUtils.mv([path1, path2, path4], path3).should be_nil + FileUtils.mv([path1, path2, path3], target_path).should be_nil File.exists?(path1).should be_false File.exists?(path2).should be_false - File.exists?(File.join(path3, "a")).should be_true - File.exists?(File.join(path3, "b")).should be_true - ensure - path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/" - path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/" - path3 = "/tmp/crystal_rm_rftest_#{Process.pid + 2}/" - FileUtils.rm_rf([path1, path2, path3]) + File.exists?(File.join(target_path, "a")).should be_true + File.exists?(File.join(target_path, "b")).should be_true end end end it "tests mkdir and rmdir with a new path" do - path = "/tmp/crystal_mkdir_test_#{Process.pid}/" - FileUtils.mkdir(path, 0o700).should be_nil - Dir.exists?(path).should be_true - FileUtils.rmdir(path).should be_nil - Dir.exists?(path).should be_false + with_tempfile("mkdir-new") do |path| + FileUtils.mkdir(path, 0o700).should be_nil + Dir.exists?(path).should be_true + FileUtils.rmdir(path).should be_nil + Dir.exists?(path).should be_false + end end it "tests mkdir and rmdir with multiple new paths" do - path1 = "/tmp/crystal_mkdir_test_#{Process.pid}/" - path2 = "/tmp/crystal_mkdir_test_#{Process.pid + 1}/" - FileUtils.mkdir([path1, path2], 0o700).should be_nil - Dir.exists?(path1).should be_true - Dir.exists?(path2).should be_true - FileUtils.rmdir([path1, path2]).should be_nil - Dir.exists?(path1).should be_false - Dir.exists?(path2).should be_false + with_tempfile("mkdir-new1", "mkdir-new2") do |path1, path2| + FileUtils.mkdir([path1, path2], 0o700).should be_nil + Dir.exists?(path1).should be_true + Dir.exists?(path2).should be_true + FileUtils.rmdir([path1, path2]).should be_nil + Dir.exists?(path1).should be_false + Dir.exists?(path2).should be_false + end end it "tests mkdir with an existing path" do expect_raises Errno do - Dir.mkdir(__DIR__, 0o700) + Dir.mkdir(datapath, 0o700) end end it "tests mkdir with multiples existing paths" do - path = "/tmp/crystal_mkdir_test_#{Process.pid}/" - begin - expect_raises Errno do - FileUtils.mkdir([__DIR__, __DIR__], 0o700) - end + expect_raises Errno do + FileUtils.mkdir([datapath, datapath], 0o700) + end + + with_tempfile("mkdir-nonexisting") do |path| expect_raises Errno do - FileUtils.mkdir([path, __DIR__], 0o700) + FileUtils.mkdir([path, datapath], 0o700) end - ensure - FileUtils.rmdir(path) end end it "tests mkdir_p with a new path" do - path1 = "/tmp/crystal_mkdir_ptest_#{Process.pid}/" - begin + with_tempfile("mkdir_p-new") do |path1| FileUtils.mkdir_p(path1).should be_nil Dir.exists?(path1).should be_true path2 = File.join({path1, "a", "b", "c"}) FileUtils.mkdir_p(path2).should be_nil Dir.exists?(path2).should be_true - ensure - FileUtils.rm_rf(path1) end end it "tests mkdir_p with multiples new path" do - path1 = "/tmp/crystal_mkdir_ptest_#{Process.pid}/" - path2 = "/tmp/crystal_mkdir_ptest_#{Process.pid + 1}" - begin + with_tempfile("mkdir_p-multi1", "mkdir_p-multi2") do |path1, path2| FileUtils.mkdir_p([path1, path2]).should be_nil Dir.exists?(path1).should be_true Dir.exists?(path2).should be_true @@ -422,79 +359,87 @@ describe "FileUtils" do FileUtils.mkdir_p([path3, path4]).should be_nil Dir.exists?(path3).should be_true Dir.exists?(path4).should be_true - ensure - FileUtils.rm_rf([path1, path2]) end end it "tests mkdir_p with an existing path" do - FileUtils.mkdir_p(__DIR__).should be_nil + FileUtils.mkdir_p(datapath).should be_nil expect_raises Errno do - FileUtils.mkdir_p(__FILE__) + FileUtils.mkdir_p(datapath("test_file.txt")) end end it "tests mkdir_p with multiple existing path" do - FileUtils.mkdir_p([__DIR__, __DIR__]).should be_nil - expect_raises Errno do - FileUtils.mkdir_p([__FILE__, "/tmp/crystal_mkdir_ptest_#{Process.pid}/"]) + FileUtils.mkdir_p([datapath, datapath]).should be_nil + with_tempfile("mkdir_p-existing") do |path| + expect_raises Errno do + FileUtils.mkdir_p([datapath("test_file.txt"), path]) + end end end it "tests rmdir with an non existing path" do - expect_raises Errno do - FileUtils.rmdir("/tmp/crystal_mkdir_test_#{Process.pid}/tmp/") + with_tempfile("rmdir-nonexisting") do |path| + expect_raises Errno do + FileUtils.rmdir(path) + end end end it "tests rmdir with multiple non existing path" do - expect_raises Errno do - FileUtils.rmdir(["/tmp/crystal_mkdir_test_#{Process.pid}/tmp/", "/tmp/crystal_mkdir_test_#{Process.pid + 1}/tmp/"]) + with_tempfile("rmdir-nonexisting") do |path| + expect_raises Errno do + FileUtils.rmdir(["#{path}1", "#{path}2"]) + end end end it "tests rmdir with a path that cannot be removed" do expect_raises Errno do - FileUtils.rmdir(__DIR__) + FileUtils.rmdir(datapath) end end it "tests rmdir with multiple path that cannot be removed" do expect_raises Errno do - FileUtils.rmdir([__DIR__, __DIR__]) + FileUtils.rmdir([datapath, datapath]) end end it "tests rm with an existing path" do - path = "/tmp/crystal_rm_test_#{Process.pid}" - File.write(path, "") - FileUtils.rm(path).should be_nil - File.exists?(path).should be_false + with_tempfile("rm") do |path| + File.write(path, "") + FileUtils.rm(path).should be_nil + File.exists?(path).should be_false + end end it "tests rm with non existing path" do - expect_raises Errno do - FileUtils.rm("/tmp/crystal_rm_test_#{Process.pid}") + with_tempfile("rm-nonexistinent") do |path| + expect_raises Errno do + FileUtils.rm(path) + end end end it "tests rm with multiple existing paths" do - path1 = "/tmp/crystal_rm_test_#{Process.pid}" - path2 = "/tmp/crystal_rm_test_#{Process.pid + 1}" - File.write(path1, "") - File.write(path2, "") - FileUtils.rm([path1, path2]).should be_nil - File.exists?(path1).should be_false - File.exists?(path2).should be_false + with_tempfile("rm-multi1", "rm-multi2") do |path1, path2| + File.write(path1, "") + File.write(path2, "") + FileUtils.rm([path1, path2]).should be_nil + File.exists?(path1).should be_false + File.exists?(path2).should be_false + end end it "tests rm with some non existing paths" do - expect_raises Errno do - path1 = "/tmp/crystal_rm_test_#{Process.pid}" - path2 = "/tmp/crystal_rm_test_#{Process.pid + 1}" + with_tempfile("rm-nonexistent1", "rm-nonexistent2") do |path1, path2| File.write(path1, "") File.write(path2, "") - FileUtils.rm([path1, path2, path2]) + + expect_raises Errno do + FileUtils.rm([path1, path2, path2]) + end end end diff --git a/spec/std/http/server/handlers/static_file_handler_spec.cr b/spec/std/http/server/handlers/static_file_handler_spec.cr index 059da35735cc..0f5266afd721 100644 --- a/spec/std/http/server/handlers/static_file_handler_spec.cr +++ b/spec/std/http/server/handlers/static_file_handler_spec.cr @@ -1,11 +1,11 @@ -require "spec" +require "../../../spec_helper" require "http/server" private def handle(request, fallthrough = true, directory_listing = true, ignore_body = false) io = IO::Memory.new response = HTTP::Server::Response.new(io) context = HTTP::Server::Context.new(request, response) - handler = HTTP::StaticFileHandler.new "#{__DIR__}/static", fallthrough, directory_listing + handler = HTTP::StaticFileHandler.new datapath("static_file_handler"), fallthrough, directory_listing handler.call context response.close io.rewind @@ -13,12 +13,12 @@ private def handle(request, fallthrough = true, directory_listing = true, ignore end describe HTTP::StaticFileHandler do - file_text = File.read "#{__DIR__}/static/test.txt" + file_text = File.read datapath("static_file_handler", "test.txt") it "serves a file" do response = handle HTTP::Request.new("GET", "/test.txt"), ignore_body: false response.status_code.should eq(200) - response.body.should eq(File.read("#{__DIR__}/static/test.txt")) + response.body.should eq(File.read(datapath("static_file_handler", "test.txt"))) end it "adds Etag header" do @@ -28,7 +28,7 @@ describe HTTP::StaticFileHandler do it "adds Last-Modified header" do response = handle HTTP::Request.new("GET", "/test.txt") - response.headers["Last-Modified"].should eq(HTTP.format_time(File.info("#{__DIR__}/static/test.txt").modification_time)) + response.headers["Last-Modified"].should eq(HTTP.format_time(File.info(datapath("static_file_handler", "test.txt")).modification_time)) end context "with If-Modified-Since header" do @@ -47,7 +47,7 @@ describe HTTP::StaticFileHandler do it "returns 304 Not Modified if file mtime is older" do headers = HTTP::Headers.new - headers["If-Modified-Since"] = HTTP.format_time(File.info("#{__DIR__}/static/test.txt").modification_time + 1.hour) + headers["If-Modified-Since"] = HTTP.format_time(File.info(datapath("static_file_handler", "test.txt")).modification_time + 1.hour) response = handle HTTP::Request.new("GET", "/test.txt", headers), ignore_body: true response.status_code.should eq(304) @@ -55,11 +55,11 @@ describe HTTP::StaticFileHandler do it "serves file if file mtime is younger" do headers = HTTP::Headers.new - headers["If-Modified-Since"] = HTTP.format_time(File.info("#{__DIR__}/static/test.txt").modification_time - 1.hour) + headers["If-Modified-Since"] = HTTP.format_time(File.info(datapath("static_file_handler", "test.txt")).modification_time - 1.hour) response = handle HTTP::Request.new("GET", "/test.txt", headers), ignore_body: false response.status_code.should eq(200) - response.body.should eq(File.read("#{__DIR__}/static/test.txt")) + response.body.should eq(File.read(datapath("static_file_handler", "test.txt"))) end end @@ -79,7 +79,7 @@ describe HTTP::StaticFileHandler do response = handle HTTP::Request.new("GET", "/test.txt", headers), ignore_body: false response.status_code.should eq(200) - response.body.should eq(File.read("#{__DIR__}/static/test.txt")) + response.body.should eq(File.read(datapath("static_file_handler", "test.txt"))) end end @@ -88,7 +88,7 @@ describe HTTP::StaticFileHandler do initial_response = handle HTTP::Request.new("GET", "/test.txt") headers = HTTP::Headers.new - headers["If-Modified-Since"] = HTTP.format_time(File.info("#{__DIR__}/static/test.txt").modification_time - 1.hour) + headers["If-Modified-Since"] = HTTP.format_time(File.info(datapath("static_file_handler", "test.txt")).modification_time - 1.hour) headers["If-None-Match"] = initial_response.headers["Etag"] response = handle HTTP::Request.new("GET", "/test.txt", headers), ignore_body: true @@ -104,7 +104,7 @@ describe HTTP::StaticFileHandler do response = handle HTTP::Request.new("GET", "/test.txt", headers), ignore_body: false response.status_code.should eq(200) - response.body.should eq(File.read("#{__DIR__}/static/test.txt")) + response.body.should eq(File.read(datapath("static_file_handler", "test.txt"))) end end diff --git a/spec/std/http/web_socket_spec.cr b/spec/std/http/web_socket_spec.cr index 229a5477115e..5f09f8c4d38b 100644 --- a/spec/std/http/web_socket_spec.cr +++ b/spec/std/http/web_socket_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "../spec_helper" require "http/web_socket" require "random/secure" @@ -129,7 +129,7 @@ describe HTTP::WebSocket do end it "read long packet" do - data = File.read("#{__DIR__}/../data/websocket_longpacket.bin") + data = File.read(datapath("websocket_longpacket.bin")) io = IO::Memory.new(data) ws = HTTP::WebSocket::Protocol.new(io) @@ -352,8 +352,8 @@ describe HTTP::WebSocket do http_server = http_ref = HTTP::Server.new([ws_handler]) tls = http_server.tls = OpenSSL::SSL::Context::Server.new - tls.certificate_chain = File.join(__DIR__, "../openssl/ssl/openssl.crt") - tls.private_key = File.join(__DIR__, "../openssl/ssl/openssl.key") + tls.certificate_chain = datapath("openssl", "openssl.crt") + tls.private_key = datapath("openssl", "openssl.key") address = http_server.bind_unused_port address_chan.send(address) http_server.listen diff --git a/spec/std/ini_spec.cr b/spec/std/ini_spec.cr index f61105e97426..127d4d366503 100644 --- a/spec/std/ini_spec.cr +++ b/spec/std/ini_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "./spec_helper" require "ini" describe "INI" do @@ -55,7 +55,7 @@ describe "INI" do end it "parses a file" do - INI.parse(File.read "#{__DIR__}/data/test_file.ini").should eq({ + INI.parse(File.read datapath("test_file.ini")).should eq({ "general" => { "log_level" => "D", }, @@ -83,7 +83,7 @@ describe "INI" do "section2" => { "x.y.z" => "coco lala", }, - }, true).should eq(File.read "#{__DIR__}/data/test_file.ini") + }, true).should eq(File.read datapath("test_file.ini")) end it "build from a NamedTuple" do INI.build({ @@ -97,7 +97,7 @@ describe "INI" do "section2": { "x.y.z": "coco lala", }, - }, true).should eq(File.read "#{__DIR__}/data/test_file.ini") + }, true).should eq(File.read datapath("test_file.ini")) end it "build with no spaces around `=`" do INI.build({"foo" => {"a" => "1"}}, false).should eq("[foo]\na=1\n\n") diff --git a/spec/std/io/argf_spec.cr b/spec/std/io/argf_spec.cr index e2448096f410..92b8e0f63454 100644 --- a/spec/std/io/argf_spec.cr +++ b/spec/std/io/argf_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "../spec_helper" describe IO::ARGF do it "reads from STDIN if ARGV isn't specified" do @@ -12,8 +12,8 @@ describe IO::ARGF do end it "reads from ARGV if specified" do - path1 = "#{__DIR__}/../data/argf_test_file_1.txt" - path2 = "#{__DIR__}/../data/argf_test_file_2.txt" + path1 = datapath("argf_test_file_1.txt") + path2 = datapath("argf_test_file_2.txt") stdin = IO::Memory.new("") argv = [path1, path2] @@ -60,8 +60,8 @@ describe IO::ARGF do end it "reads from ARGV if specified" do - path1 = "#{__DIR__}/../data/argf_test_file_1.txt" - path2 = "#{__DIR__}/../data/argf_test_file_2.txt" + path1 = datapath("argf_test_file_1.txt") + path2 = datapath("argf_test_file_2.txt") stdin = IO::Memory.new("") argv = [path1, path2] @@ -94,8 +94,8 @@ describe IO::ARGF do end it "peeks from ARGV if specified" do - path1 = "#{__DIR__}/../data/argf_test_file_1.txt" - path2 = "#{__DIR__}/../data/argf_test_file_2.txt" + path1 = datapath("argf_test_file_1.txt") + path2 = datapath("argf_test_file_2.txt") stdin = IO::Memory.new("") argv = [path1, path2] diff --git a/spec/std/io/io_spec.cr b/spec/std/io/io_spec.cr index d28b4e152d4d..fe96e201f084 100644 --- a/spec/std/io/io_spec.cr +++ b/spec/std/io/io_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "../spec_helper" require "big" require "base64" @@ -170,8 +170,8 @@ describe IO do end it "reopens" do - File.open("#{__DIR__}/../data/test_file.txt") do |file1| - File.open("#{__DIR__}/../data/test_file.ini") do |file2| + File.open(datapath("test_file.txt")) do |file1| + File.open(datapath("test_file.ini")) do |file2| file2.reopen(file1) file2.gets.should eq("Hello World") end @@ -703,14 +703,14 @@ describe IO do end it "decodes incomplete multibyte sequence with skip (2) (#3285)" do - str = File.read("#{__DIR__}/../data/io_data_incomplete_multibyte_sequence.txt") + str = File.read(datapath("io_data_incomplete_multibyte_sequence.txt")) m = IO::Memory.new(Base64.decode_string str) m.set_encoding("UTF-8", invalid: :skip) m.gets_to_end.bytesize.should eq(4277) end it "decodes incomplete multibyte sequence with skip (3) (#3285)" do - str = File.read("#{__DIR__}/../data/io_data_incomplete_multibyte_sequence_2.txt") + str = File.read(datapath("io_data_incomplete_multibyte_sequence_2.txt")) m = IO::Memory.new(Base64.decode_string str) m.set_encoding("UTF-8", invalid: :skip) m.gets_to_end.bytesize.should eq(8977) diff --git a/spec/std/kernel_spec.cr b/spec/std/kernel_spec.cr index c761f40db31f..dbc317cd4451 100644 --- a/spec/std/kernel_spec.cr +++ b/spec/std/kernel_spec.cr @@ -1,6 +1,4 @@ require "spec" -require "tempfile" - require "../../spec_helper" describe "exit" do diff --git a/spec/std/openssl/cipher_spec.cr b/spec/std/openssl/cipher_spec.cr index e874182137e3..2eb4a2dc62cf 100644 --- a/spec/std/openssl/cipher_spec.cr +++ b/spec/std/openssl/cipher_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "../spec_helper" require "openssl/cipher" describe OpenSSL::Cipher do @@ -9,7 +9,7 @@ describe OpenSSL::Cipher do key = "\0" * 16 iv = "\0" * 16 data = "DATA" * 5 - ciphertext = File.read(File.join(__DIR__ + "/cipher_spec.ciphertext")) + ciphertext = File.read(datapath("cipher_spec.ciphertext")) c1.name.should eq(c2.name) diff --git a/spec/std/openssl/ssl/context_spec.cr b/spec/std/openssl/ssl/context_spec.cr index 227ee01c92bc..e62742a18924 100644 --- a/spec/std/openssl/ssl/context_spec.cr +++ b/spec/std/openssl/ssl/context_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "../../spec_helper" require "openssl" require "../../../support/finalize" @@ -70,24 +70,24 @@ describe OpenSSL::SSL::Context do it "sets certificate chain" do context = OpenSSL::SSL::Context::Client.new - context.certificate_chain = File.join(__DIR__, "openssl.crt") + context.certificate_chain = datapath("openssl", "openssl.crt") end it "fails to set certificate chain" do context = OpenSSL::SSL::Context::Client.new - expect_raises(OpenSSL::Error) { context.certificate_chain = File.join(__DIR__, "unknown.crt") } - expect_raises(OpenSSL::Error) { context.certificate_chain = __FILE__ } + expect_raises(OpenSSL::Error) { context.certificate_chain = datapath("nonexistent.crt") } + expect_raises(OpenSSL::Error) { context.certificate_chain = datapath("test_file.txt") } end it "sets private key" do context = OpenSSL::SSL::Context::Client.new - context.private_key = File.join(__DIR__, "openssl.key") + context.private_key = datapath("openssl", "openssl.key") end it "fails to set private key" do context = OpenSSL::SSL::Context::Client.new - expect_raises(OpenSSL::Error) { context.private_key = File.join(__DIR__, "unknown.key") } - expect_raises(OpenSSL::Error) { context.private_key = __FILE__ } + expect_raises(OpenSSL::Error) { context.private_key = datapath("nonexistent.key") } + expect_raises(OpenSSL::Error) { context.private_key = datapath("test_file.txt") } end it "sets ciphers" do diff --git a/spec/std/process_spec.cr b/spec/std/process_spec.cr index f3b82940a3d8..da665db1d983 100644 --- a/spec/std/process_spec.cr +++ b/spec/std/process_spec.cr @@ -1,7 +1,6 @@ require "spec" require "process" -require "tempfile" - +require "./spec_helper" require "../spec_helper" describe Process do @@ -190,20 +189,16 @@ describe Process do end it "executes the new process with exec" do - tmpfile = Tempfile.new("crystal-spec-exec") - tmpfile.close - tmpfile.delete - File.exists?(tmpfile.path).should be_false + with_tempfile("crystal-spec-exec") do |path| + File.exists?(path).should be_false - fork = Process.fork do - Process.exec("/usr/bin/env", {"touch", tmpfile.path}) - end - fork.wait + fork = Process.fork do + Process.exec("/usr/bin/env", {"touch", path}) + end + fork.wait - File.exists?(tmpfile.path).should be_true - tmpfile.delete - ensure - File.delete(tmpfile.path) if tmpfile && File.exists?(tmpfile.path) + File.exists?(path).should be_true + end end it "checks for existence" do diff --git a/spec/std/socket_spec.cr b/spec/std/socket_spec.cr index 90aee0963d64..ee64beff0118 100644 --- a/spec/std/socket_spec.cr +++ b/spec/std/socket_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "./spec_helper" require "socket" describe Socket do @@ -170,17 +170,22 @@ end describe Socket::UNIXAddress do it "transforms into a C struct and back" do - addr1 = Socket::UNIXAddress.new("/tmp/service.sock") + path = "unix_address.sock" + + addr1 = Socket::UNIXAddress.new(path) addr2 = Socket::UNIXAddress.from(addr1.to_unsafe, addr1.size) addr2.family.should eq(addr1.family) addr2.path.should eq(addr1.path) - addr2.to_s.should eq("/tmp/service.sock") + addr2.to_s.should eq(path) end it "raises when path is too long" do - path = "/tmp/crystal-test-too-long-unix-socket-#{("a" * 2048)}.sock" - expect_raises(ArgumentError, "Path size exceeds the maximum size") { Socket::UNIXAddress.new(path) } + path = "unix_address-too-long-#{("a" * 2048)}.sock" + + expect_raises(ArgumentError, "Path size exceeds the maximum size") do + Socket::UNIXAddress.new(path) + end end it "to_s" do @@ -190,170 +195,173 @@ end describe UNIXServer do it "raises when path is too long" do - path = "/tmp/crystal-test-too-long-unix-socket-#{("a" * 2048)}.sock" - expect_raises(ArgumentError, "Path size exceeds the maximum size") { UNIXServer.new(path) } - File.exists?(path).should be_false + with_tempfile("unix_server-too_long-#{("a" * 2048)}.sock") do |path| + expect_raises(ArgumentError, "Path size exceeds the maximum size") { UNIXServer.new(path) } + File.exists?(path).should be_false + end end it "creates the socket file" do - path = "/tmp/crystal-test-unix-sock" + with_tempfile("unix_server.sock") do |path| + UNIXServer.open(path) do + File.exists?(path).should be_true + end - UNIXServer.open(path) do - File.exists?(path).should be_true + File.exists?(path).should be_false end - - File.exists?(path).should be_false end it "deletes socket file on close" do - path = "/tmp/crystal-test-unix-sock" - - begin + with_tempfile("unix_server-close.sock") do |path| server = UNIXServer.new(path) server.close File.exists?(path).should be_false - rescue - File.delete(path) if File.exists?(path) end end it "raises when socket file already exists" do - path = "/tmp/crystal-test-unix-sock" - server = UNIXServer.new(path) + with_tempfile("unix_server-twice.sock") do |path| + server = UNIXServer.new(path) - begin - expect_raises(Errno) { UNIXServer.new(path) } - ensure - server.close + begin + expect_raises(Errno) { UNIXServer.new(path) } + ensure + server.close + end end end it "won't delete existing file on bind failure" do - path = "/tmp/crystal-test-unix.sock" - - File.write(path, "") - File.exists?(path).should be_true + with_tempfile("unix_server-existing.sock") do |path| + File.write(path, "") + File.exists?(path).should be_true - begin expect_raises Errno, /(already|Address) in use/ do UNIXServer.new(path) end File.exists?(path).should be_true - ensure - File.delete(path) if File.exists?(path) end end describe "accept" do it "returns the client UNIXSocket" do - UNIXServer.open("/tmp/crystal-test-unix-sock") do |server| - UNIXSocket.open("/tmp/crystal-test-unix-sock") do |_| - client = server.accept - client.should be_a(UNIXSocket) - client.close + with_tempfile("unix_server-accept.sock") do |path| + UNIXServer.open(path) do |server| + UNIXSocket.open(path) do |_| + client = server.accept + client.should be_a(UNIXSocket) + client.close + end end end end it "raises when server is closed" do - server = UNIXServer.new("/tmp/crystal-test-unix-sock") - exception = nil - - spawn do - begin - server.accept - rescue ex - exception = ex + with_tempfile("unix_server-accept-closed.sock") do |path| + server = UNIXServer.new(path) + exception = nil + + spawn do + begin + server.accept + rescue ex + exception = ex + end end - end - server.close - until exception - Fiber.yield - end + server.close + until exception + Fiber.yield + end - exception.should be_a(IO::Error) - exception.try(&.message).should eq("Closed stream") + exception.should be_a(IO::Error) + exception.try(&.message).should eq("Closed stream") + end end end describe "accept?" do it "returns the client UNIXSocket" do - UNIXServer.open("/tmp/crystal-test-unix-sock") do |server| - UNIXSocket.open("/tmp/crystal-test-unix-sock") do |_| - client = server.accept?.not_nil! - client.should be_a(UNIXSocket) - client.close + with_tempfile("unix_server-accept_.sock") do |path| + UNIXServer.open(path) do |server| + UNIXSocket.open(path) do |_| + client = server.accept?.not_nil! + client.should be_a(UNIXSocket) + client.close + end end end end it "returns nil when server is closed" do - server = UNIXServer.new("/tmp/crystal-test-unix-sock") - ret = :initial + with_tempfile("unix_server-accept2.sock") do |path| + server = UNIXServer.new(path) + ret = :initial - spawn { ret = server.accept? } - server.close + spawn { ret = server.accept? } + server.close - while ret == :initial - Fiber.yield - end + while ret == :initial + Fiber.yield + end - ret.should be_nil + ret.should be_nil + end end end end describe UNIXSocket do it "raises when path is too long" do - path = "/tmp/crystal-test-too-long-unix-socket-#{("a" * 2048)}.sock" - expect_raises(ArgumentError, "Path size exceeds the maximum size") { UNIXSocket.new(path) } - File.exists?(path).should be_false + with_tempfile("unix_socket-too_long-#{("a" * 2048)}.sock") do |path| + expect_raises(ArgumentError, "Path size exceeds the maximum size") { UNIXSocket.new(path) } + File.exists?(path).should be_false + end end it "sends and receives messages" do - path = "/tmp/crystal-test-unix-sock" - - UNIXServer.open(path) do |server| - server.local_address.family.should eq(Socket::Family::UNIX) - server.local_address.path.should eq(path) - - UNIXSocket.open(path) do |client| - client.local_address.family.should eq(Socket::Family::UNIX) - client.local_address.path.should eq(path) - - server.accept do |sock| - sock.local_address.family.should eq(Socket::Family::UNIX) - sock.local_address.path.should eq(path) - - sock.remote_address.family.should eq(Socket::Family::UNIX) - sock.remote_address.path.should eq(path) - - client << "ping" - sock.gets(4).should eq("ping") - sock << "pong" - client.gets(4).should eq("pong") + with_tempfile("unix_socket.sock") do |path| + UNIXServer.open(path) do |server| + server.local_address.family.should eq(Socket::Family::UNIX) + server.local_address.path.should eq(path) + + UNIXSocket.open(path) do |client| + client.local_address.family.should eq(Socket::Family::UNIX) + client.local_address.path.should eq(path) + + server.accept do |sock| + sock.local_address.family.should eq(Socket::Family::UNIX) + sock.local_address.path.should eq(path) + + sock.remote_address.family.should eq(Socket::Family::UNIX) + sock.remote_address.path.should eq(path) + + client << "ping" + sock.gets(4).should eq("ping") + sock << "pong" + client.gets(4).should eq("pong") + end end end end end it "sync flag after accept" do - path = "/tmp/crystal-test-unix-sock" - - UNIXServer.open(path) do |server| - UNIXSocket.open(path) do |client| - server.accept do |sock| - sock.sync?.should eq(server.sync?) + with_tempfile("unix_socket-accept.sock") do |path| + UNIXServer.open(path) do |server| + UNIXSocket.open(path) do |client| + server.accept do |sock| + sock.sync?.should eq(server.sync?) + end end - end - server.sync = !server.sync? + server.sync = !server.sync? - UNIXSocket.open(path) do |client| - server.accept do |sock| - sock.sync?.should eq(server.sync?) + UNIXSocket.open(path) do |client| + server.accept do |sock| + sock.sync?.should eq(server.sync?) + end end end end diff --git a/spec/std/time/location_spec.cr b/spec/std/time/location_spec.cr index 790fa688b032..203233c9d737 100644 --- a/spec/std/time/location_spec.cr +++ b/spec/std/time/location_spec.cr @@ -68,7 +68,7 @@ class Time::Location context "with ZONEINFO" do it "loads from custom directory" do - with_zoneinfo(File.join(__DIR__, "..", "data", "zoneinfo")) do + with_zoneinfo(datapath("zoneinfo")) do location = Location.load("Foo/Bar") location.name.should eq "Foo/Bar" end @@ -91,7 +91,7 @@ class Time::Location end it "does not fall back to default sources" do - with_zoneinfo(File.join(__DIR__, "..", "data", "zoneinfo")) do + with_zoneinfo(datapath("zoneinfo")) do expect_raises(InvalidLocationNameError) do Location.load("Europe/Berlin") end @@ -112,7 +112,7 @@ class Time::Location end it "loads new data if file was changed" do - zoneinfo_path = File.join(__DIR__, "..", "data", "zoneinfo") + zoneinfo_path = datapath("zoneinfo") with_zoneinfo(zoneinfo_path) do location1 = Location.load("Foo/Bar") File.touch(File.join(zoneinfo_path, "Foo/Bar")) diff --git a/spec/std/time/spec_helper.cr b/spec/std/time/spec_helper.cr index 14edb581568f..84572fbf5e1c 100644 --- a/spec/std/time/spec_helper.cr +++ b/spec/std/time/spec_helper.cr @@ -1,4 +1,4 @@ -require "spec" +require "../spec_helper" class Time::Location def __cached_range @@ -31,7 +31,7 @@ def with_env(name, value) end end -ZONEINFO_ZIP = File.join(__DIR__, "..", "data", "zoneinfo.zip") +ZONEINFO_ZIP = datapath("zoneinfo.zip") def with_zoneinfo(path = ZONEINFO_ZIP) with_env("ZONEINFO", path) do diff --git a/spec/std/zip/zip_file_spec.cr b/spec/std/zip/zip_file_spec.cr index ad7d353dffc7..7558d101479a 100644 --- a/spec/std/zip/zip_file_spec.cr +++ b/spec/std/zip/zip_file_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "../spec_helper" require "zip" describe Zip do @@ -36,7 +36,7 @@ describe Zip do end it "reads file from file system" do - filename = "#{__DIR__}/../data/file.zip" + filename = datapath("file.zip") begin File.open(filename, "w") do |file| @@ -106,7 +106,7 @@ describe Zip do end it "reads zip file with different extra in local file header and central directory header" do - Zip::File.open("#{__DIR__}/../data/test.zip") do |zip| + Zip::File.open(datapath("test.zip")) do |zip| zip.entries.size.should eq(2) zip["one.txt"].open(&.gets_to_end).should eq("One") zip["two.txt"].open(&.gets_to_end).should eq("Two") diff --git a/spec/std/zip/zip_spec.cr b/spec/std/zip/zip_spec.cr index 051c5cb12743..79ca1c7d3608 100644 --- a/spec/std/zip/zip_spec.cr +++ b/spec/std/zip/zip_spec.cr @@ -1,4 +1,4 @@ -require "spec" +require "../spec_helper" require "zip" describe Zip do @@ -169,7 +169,7 @@ describe Zip do it "writes file" do io = IO::Memory.new - filename = "#{__DIR__}/../data/test_file.txt" + filename = datapath("test_file.txt") Zip::Writer.open(io) do |zip| file = File.open(filename) From d7f0aa235f78da6c3c466f98a7dd33da5d6b8817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 16 Apr 2018 15:08:08 +0000 Subject: [PATCH 04/10] Use with_tempfile and datapath in spec/compiler --- spec/compiler/compiler_spec.cr | 30 ++++++++++-------------- spec/compiler/crystal/tools/init_spec.cr | 9 ++----- spec/compiler/spec_helper.cr | 6 +++++ 3 files changed, 20 insertions(+), 25 deletions(-) create mode 100644 spec/compiler/spec_helper.cr diff --git a/spec/compiler/compiler_spec.cr b/spec/compiler/compiler_spec.cr index ec7c8db19aac..7fdbca20db88 100644 --- a/spec/compiler/compiler_spec.cr +++ b/spec/compiler/compiler_spec.cr @@ -1,32 +1,26 @@ require "../spec_helper" -require "tempfile" +require "./spec_helper" describe "Compiler" do it "compiles a file" do - tempfile = Tempfile.new "compiler_spec_output" - tempfile.close + with_tempfile "compiler_spec_output" do |path| + Crystal::Command.run ["build", datapath("compiler_sample"), "-o", path] - Crystal::Command.run ["build", "#{__DIR__}/data/compiler_sample", "-o", tempfile.path] + File.exists?(path).should be_true - File.exists?(tempfile.path).should be_true - - `#{tempfile.path}`.should eq("Hello!") - ensure - File.delete(tempfile.path) if tempfile + `#{path}`.should eq("Hello!") + end end it "runs subcommand in preference to a filename " do - Dir.cd "#{__DIR__}/data/" do - tempfile = Tempfile.new "compiler_spec_output" - tempfile.close - - Crystal::Command.run ["build", "#{__DIR__}/data/compiler_sample", "-o", tempfile.path] + Dir.cd datapath do + with_tempfile "compiler_spec_output" do |path| + Crystal::Command.run ["build", "compiler_sample", "-o", path] - File.exists?(tempfile.path).should be_true + File.exists?(path).should be_true - `#{tempfile.path}`.should eq("Hello!") - ensure - File.delete(tempfile.path) if tempfile + `#{path}`.should eq("Hello!") + end end end end diff --git a/spec/compiler/crystal/tools/init_spec.cr b/spec/compiler/crystal/tools/init_spec.cr index 01e9c49e0be8..8ca59b44ccab 100644 --- a/spec/compiler/crystal/tools/init_spec.cr +++ b/spec/compiler/crystal/tools/init_spec.cr @@ -5,8 +5,6 @@ require "ini" require "spec" require "yaml" -PROJECT_ROOT_DIR = "#{__DIR__}/../../../.." - private def exec_init(project_name, project_dir = nil, type = "lib", force = false, skip_existing = false) args = [type, project_name] args << project_dir if project_dir @@ -21,14 +19,11 @@ end # Creates a temporary directory, cd to it and run the block inside it. # The directory and its content is deleted when the block return. private def within_temporary_directory - tmp_path = "#{PROJECT_ROOT_DIR}/tmp/init_spec_tmp_dir-#{Process.pid}" - Dir.mkdir_p(tmp_path) - begin + with_tempfile "init_spec_tmp" do |tmp_path| + Dir.mkdir_p(tmp_path) Dir.cd(tmp_path) do yield end - ensure - FileUtils.rm_rf(tmp_path) end end diff --git a/spec/compiler/spec_helper.cr b/spec/compiler/spec_helper.cr new file mode 100644 index 000000000000..536691a5adae --- /dev/null +++ b/spec/compiler/spec_helper.cr @@ -0,0 +1,6 @@ +require "../spec_helper" +require "../support/tempfile" + +def datapath(*components) + File.join("spec", "compiler", "data", *components) +end From f321e0ce91cc605f8d5b8827b730c5b86d5eb76a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 16 Apr 2018 18:35:21 +0000 Subject: [PATCH 05/10] Use with_tempfile in spec/spec_helper.cr --- spec/spec_helper.cr | 60 ++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 5ea235ae0cc6..d615fcb8f40f 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -5,6 +5,7 @@ ENV["CRYSTAL_PATH"] = "#{__DIR__}/../src" require "spec" require "../src/compiler/crystal/**" require "./support/syntax" +require "./support/tempfile" class Crystal::Program def union_of(type1, type2, type3) @@ -153,7 +154,7 @@ class Crystal::SpecRunOutput end end -def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug::None) +def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug::None, *, file = __FILE__) code = inject_primitives(code) if inject_primitives # Code that requires the prelude doesn't run in LLVM's MCJIT @@ -170,60 +171,47 @@ def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug:: ast.expressions[-1] = exps code = ast.to_s - output_filename = Crystal.tempfile("crystal-spec-output") + with_tempfile("crystal-spec-output", file: file) do |output_filename| + compiler = Compiler.new + compiler.debug = debug + compiler.compile Compiler::Source.new("spec", code), output_filename - compiler = Compiler.new - compiler.debug = debug - compiler.compile Compiler::Source.new("spec", code), output_filename + output = `#{output_filename}` - output = `#{output_filename}` - File.delete(output_filename) - - SpecRunOutput.new(output) + SpecRunOutput.new(output) + end else Program.new.run(code, filename: filename, debug: debug) end end -def build_and_run(code) - code_file = Tempfile.new("build_and_run_code") - code_file.close - - # write code to the temp file - File.write(code_file.path, code) +def build_and_run(code, *, file = __FILE__) + with_tempfile("build_and_run_code", "build_and_run_bin", file: file) do |code_path, binary_path| + # write code to the temp file + File.write(code_path, code) - binary_file = Tempfile.new("build_and_run_bin") - binary_file.close + `bin/crystal build #{code_path.inspect} -o #{binary_path.inspect}` + File.exists?(binary_path).should be_true - `bin/crystal build #{code_file.path.inspect} -o #{binary_file.path.inspect}` - File.exists?(binary_file.path).should be_true + out_io, err_io = IO::Memory.new, IO::Memory.new + status = Process.run(binary_path, output: out_io, error: err_io) - out_io, err_io = IO::Memory.new, IO::Memory.new - status = Process.run(binary_file.path, output: out_io, error: err_io) - - {status, out_io.to_s, err_io.to_s} -ensure - File.delete(code_file.path) if code_file - File.delete(binary_file.path) if binary_file + {status, out_io.to_s, err_io.to_s} + end end -def test_c(c_code, crystal_code) - c_filename = "#{__DIR__}/temp_abi.c" - o_filename = "#{__DIR__}/temp_abi.o" - begin - File.write(c_filename, c_code) +def test_c(c_code, crystal_code, *, file = __FILE__) + with_tempfile("abi.c", "abi.o", file: file) do |c_path, o_path| + File.write(c_path, c_code) - `#{Crystal::Compiler::CC} #{c_filename} -c -o #{o_filename}`.should be_truthy + `#{Crystal::Compiler::CC} #{c_path} -c -o #{o_path}`.should be_truthy yield run(%( require "prelude" - @[Link(ldflags: "#{o_filename}")] + @[Link(ldflags: "#{o_path}")] #{crystal_code} )) - ensure - File.delete(c_filename) - File.delete(o_filename) end end From bfbf43dec341aef65da350c1d120fbf37eae32f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 12 Jun 2018 19:31:59 +0200 Subject: [PATCH 06/10] fixup! Add spec helper `with_tempfile` --- spec/support/tempfile.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/support/tempfile.cr b/spec/support/tempfile.cr index 5499993cd899..6eb38cc28d50 100644 --- a/spec/support/tempfile.cr +++ b/spec/support/tempfile.cr @@ -21,7 +21,7 @@ SPEC_TEMPFILE_CLEANUP = ENV["SPEC_TEMPFILE_CLEANUP"]? != "0" # If the environment variable `SPEC_TEMPFILE_CLEANUP` is set to `0`, no paths # will be cleaned up, enabling easier debugging. def with_tempfile(*paths, file = __FILE__) - calling_spec = File.basename(file).gsub("_spec.cr", "") + calling_spec = File.basename(file).rchop("_spec.cr") paths = paths.map { |path| File.join(SPEC_TEMPFILE_PATH, calling_spec, path) } FileUtils.mkdir_p(File.join(SPEC_TEMPFILE_PATH, calling_spec)) From 67e6780e165b9438515ed310318e9cdfac288a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Thu, 14 Jun 2018 20:30:33 +0200 Subject: [PATCH 07/10] fixup! Add spec helper `with_tempfile` --- spec/support/tempfile.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/support/tempfile.cr b/spec/support/tempfile.cr index 6eb38cc28d50..ef1fad145a7d 100644 --- a/spec/support/tempfile.cr +++ b/spec/support/tempfile.cr @@ -1,7 +1,7 @@ require "tempfile" require "file_utils" -SPEC_TEMPFILE_PATH = File.join(Tempfile.dirname, "crystal-spec-#{Random.new.hex(8)}") +SPEC_TEMPFILE_PATH = File.join(Tempfile.dirname, "cr-spec-#{Random.new.hex(4)}") SPEC_TEMPFILE_CLEANUP = ENV["SPEC_TEMPFILE_CLEANUP"]? != "0" From 5ae1347f15d2efa7a16bbcf964b83abc8f19a0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Thu, 14 Jun 2018 21:23:21 +0200 Subject: [PATCH 08/10] fixup! Use with_tempfile and datapath in spec/std --- spec/std/socket_spec.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/std/socket_spec.cr b/spec/std/socket_spec.cr index ee64beff0118..5255a76f5bcd 100644 --- a/spec/std/socket_spec.cr +++ b/spec/std/socket_spec.cr @@ -258,7 +258,7 @@ describe UNIXServer do end it "raises when server is closed" do - with_tempfile("unix_server-accept-closed.sock") do |path| + with_tempfile("unix_server-closed.sock") do |path| server = UNIXServer.new(path) exception = nil From bc64183a3cc0a1384704b28d01e94d04aa4227f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Fri, 15 Jun 2018 17:26:20 +0200 Subject: [PATCH 09/10] fixup! Use with_tempfile and datapath in spec/std --- spec/std/file_spec.cr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/std/file_spec.cr b/spec/std/file_spec.cr index c93039be9a81..dfb95a45f203 100644 --- a/spec/std/file_spec.cr +++ b/spec/std/file_spec.cr @@ -189,8 +189,8 @@ describe "File" do File.file?(datapath("test_file.txt")).should be_true end - it "gives false" do - File.file?(datapath("nonexistent_dir")).should be_false + it "gives false with dir" do + File.file?(datapath("dir")).should be_false end it "gives false when the file doesn't exist" do @@ -578,7 +578,7 @@ describe "File" do it "converts a pathname to an absolute pathname, using ~ (home) as base (trailing /)" do prev_home = home begin - ENV["HOME"] = File.expand_path(datapath("", "")) + ENV["HOME"] = File.expand_path(datapath) File.expand_path("~/").should eq(home) File.expand_path("~/..badfilename").should eq(File.join(home, "..badfilename")) File.expand_path("..").should eq("/#{base.split('/')[0...-1].join('/')}".gsub(%r{\A//}, "/")) From 1667e4992666e46a3c94ac069a48f0fb8b22ed65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 18 Jun 2018 11:54:48 +0200 Subject: [PATCH 10/10] fixup! Use with_tempfile in spec/spec_helper.cr --- spec/spec_helper.cr | 60 +++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index d615fcb8f40f..5ea235ae0cc6 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -5,7 +5,6 @@ ENV["CRYSTAL_PATH"] = "#{__DIR__}/../src" require "spec" require "../src/compiler/crystal/**" require "./support/syntax" -require "./support/tempfile" class Crystal::Program def union_of(type1, type2, type3) @@ -154,7 +153,7 @@ class Crystal::SpecRunOutput end end -def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug::None, *, file = __FILE__) +def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug::None) code = inject_primitives(code) if inject_primitives # Code that requires the prelude doesn't run in LLVM's MCJIT @@ -171,47 +170,60 @@ def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug:: ast.expressions[-1] = exps code = ast.to_s - with_tempfile("crystal-spec-output", file: file) do |output_filename| - compiler = Compiler.new - compiler.debug = debug - compiler.compile Compiler::Source.new("spec", code), output_filename + output_filename = Crystal.tempfile("crystal-spec-output") - output = `#{output_filename}` + compiler = Compiler.new + compiler.debug = debug + compiler.compile Compiler::Source.new("spec", code), output_filename - SpecRunOutput.new(output) - end + output = `#{output_filename}` + File.delete(output_filename) + + SpecRunOutput.new(output) else Program.new.run(code, filename: filename, debug: debug) end end -def build_and_run(code, *, file = __FILE__) - with_tempfile("build_and_run_code", "build_and_run_bin", file: file) do |code_path, binary_path| - # write code to the temp file - File.write(code_path, code) +def build_and_run(code) + code_file = Tempfile.new("build_and_run_code") + code_file.close - `bin/crystal build #{code_path.inspect} -o #{binary_path.inspect}` - File.exists?(binary_path).should be_true + # write code to the temp file + File.write(code_file.path, code) - out_io, err_io = IO::Memory.new, IO::Memory.new - status = Process.run(binary_path, output: out_io, error: err_io) + binary_file = Tempfile.new("build_and_run_bin") + binary_file.close - {status, out_io.to_s, err_io.to_s} - end + `bin/crystal build #{code_file.path.inspect} -o #{binary_file.path.inspect}` + File.exists?(binary_file.path).should be_true + + out_io, err_io = IO::Memory.new, IO::Memory.new + status = Process.run(binary_file.path, output: out_io, error: err_io) + + {status, out_io.to_s, err_io.to_s} +ensure + File.delete(code_file.path) if code_file + File.delete(binary_file.path) if binary_file end -def test_c(c_code, crystal_code, *, file = __FILE__) - with_tempfile("abi.c", "abi.o", file: file) do |c_path, o_path| - File.write(c_path, c_code) +def test_c(c_code, crystal_code) + c_filename = "#{__DIR__}/temp_abi.c" + o_filename = "#{__DIR__}/temp_abi.o" + begin + File.write(c_filename, c_code) - `#{Crystal::Compiler::CC} #{c_path} -c -o #{o_path}`.should be_truthy + `#{Crystal::Compiler::CC} #{c_filename} -c -o #{o_filename}`.should be_truthy yield run(%( require "prelude" - @[Link(ldflags: "#{o_path}")] + @[Link(ldflags: "#{o_filename}")] #{crystal_code} )) + ensure + File.delete(c_filename) + File.delete(o_filename) end end