Skip to content

Commit bb5dfd1

Browse files
Tolerate temporary directory cleanup failures
1 parent 9540e78 commit bb5dfd1

2 files changed

Lines changed: 68 additions & 2 deletions

File tree

lib/sus/fixtures/temporary_directory_context.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# Copyright, 2025-2026, by Samuel Williams.
55

66
require "tmpdir"
7+
require "fileutils"
78

89
module Sus
910
module Fixtures
@@ -12,16 +13,34 @@ module TemporaryDirectoryContext
1213
# Set up a temporary directory before the test and clean it up after.
1314
# @yields {|&block| ...} The test block to execute.
1415
def around(&block)
15-
Dir.mktmpdir do |root|
16+
root = Dir.mktmpdir
17+
18+
begin
1619
@root = root
20+
1721
super(&block)
22+
ensure
1823
@root = nil
24+
25+
remove_temporary_directory(root)
1926
end
2027
end
2128

2229
# @attribute [String] The path to the temporary directory root.
2330
attr :root
31+
32+
private
33+
34+
# Remove the temporary directory on a best-effort basis.
35+
def remove_temporary_directory(root)
36+
remove_entry(root)
37+
rescue
38+
end
39+
40+
# Remove an entry recursively.
41+
def remove_entry(root)
42+
FileUtils.rm_rf(root)
43+
end
2444
end
2545
end
2646
end
27-

test/sus/fixtures/temporary_directory_context.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
describe Sus::Fixtures::TemporaryDirectoryContext do
99
include Sus::Fixtures::TemporaryDirectoryContext
1010

11+
let(:assertions) {Sus::Assertions.new(output: Sus::Output.buffered)}
12+
1113
it "creates a temporary directory" do
1214
expect(root).not.to be(:nil?)
1315
expect(root).to be_a(String)
@@ -26,4 +28,49 @@
2628
expect(File.exist?(test_file)).to be == true
2729
expect(File.read(test_file)).to be == "test content"
2830
end
31+
32+
it "removes the temporary directory after use" do
33+
context = Sus.base("temporary directory")
34+
context.include(Sus::Fixtures::TemporaryDirectoryContext)
35+
instance = context.new(assertions)
36+
37+
root = nil
38+
39+
instance.around do
40+
root = instance.root
41+
42+
expect(File.directory?(root)).to be == true
43+
end
44+
45+
expect(File.exist?(root)).to be == false
46+
end
47+
48+
it "tolerates already removed temporary directories" do
49+
context = Sus.base("temporary directory")
50+
context.include(Sus::Fixtures::TemporaryDirectoryContext)
51+
instance = context.new(assertions)
52+
53+
root = Dir.mktmpdir
54+
FileUtils.rm_rf(root)
55+
56+
expect do
57+
instance.send(:remove_temporary_directory, root)
58+
end.not.to raise_exception
59+
end
60+
61+
it "ignores cleanup failures" do
62+
context = Sus.base("temporary directory")
63+
context.include(Sus::Fixtures::TemporaryDirectoryContext)
64+
instance = context.new(assertions)
65+
66+
root = Dir.mktmpdir
67+
68+
expect(instance).to receive(:remove_entry).and_raise(Errno::ENOENT, root)
69+
70+
expect do
71+
instance.send(:remove_temporary_directory, root)
72+
end.not.to raise_exception
73+
ensure
74+
FileUtils.remove_entry(root) if root && File.exist?(root)
75+
end
2976
end

0 commit comments

Comments
 (0)