aboutsummaryrefslogtreecommitdiffstats
path: root/test/test_tmpdir.rb
blob: 054ca15d7a7634345e1f9e99b598ad448536991c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# frozen_string_literal: true
require 'test/unit'
require 'tmpdir'

class TestTmpdir < Test::Unit::TestCase
  def test_tmpdir_modifiable
    tmpdir = Dir.tmpdir
    assert_not_predicate(tmpdir, :frozen?)
    tmpdir_org = tmpdir.dup
    tmpdir << "foo"
    assert_equal(tmpdir_org, Dir.tmpdir)
  end

  def test_world_writable
    omit "no meaning on this platform" if /mswin|mingw/ =~ RUBY_PLATFORM
    Dir.mktmpdir do |tmpdir|
      # ToDo: fix for parallel test
      envs = %w[TMPDIR TMP TEMP]
      oldenv = envs.each_with_object({}) {|v, h| h[v] = ENV.delete(v)}
      begin
        envs.each do |e|
          tmpdirx = File.join(tmpdir, e)
          ENV[e] = tmpdirx
          assert_not_equal(tmpdirx, assert_warn('') {Dir.tmpdir})
          File.write(tmpdirx, "")
          assert_not_equal(tmpdirx, assert_warn(/\A#{e} is not a directory/) {Dir.tmpdir})
          File.unlink(tmpdirx)
          ENV[e] = tmpdir
          assert_equal(tmpdir, Dir.tmpdir)
          File.chmod(0555, tmpdir)
          assert_not_equal(tmpdir, assert_warn(/\A#{e} is not writable/) {Dir.tmpdir})
          File.chmod(0777, tmpdir)
          assert_not_equal(tmpdir, assert_warn(/\A#{e} is world-writable/) {Dir.tmpdir})
          newdir = Dir.mktmpdir("d", tmpdir) do |dir|
            assert_file.directory? dir
            assert_equal(tmpdir, File.dirname(dir))
            dir
          end
          assert_file.not_exist?(newdir)
          File.chmod(01777, tmpdir)
          assert_equal(tmpdir, Dir.tmpdir)
          ENV[e] = nil
        end
      ensure
        ENV.update(oldenv)
      end
    end
  end

  def test_tmpdir_not_empty_parent
    Dir.mktmpdir do |tmpdir|
      envs = %w[TMPDIR TMP TEMP]
      oldenv = envs.each_with_object({}) {|v, h| h[v] = ENV.delete(v)}
      ENV[envs[0]] = ""
      ENV[envs[1]] = tmpdir
      assert_equal(tmpdir, Dir.tmpdir)
    ensure
      ENV.update(oldenv)
    end
  end

  def test_no_homedir
    bug7547 = '[ruby-core:50793]'
    home, ENV["HOME"] = ENV["HOME"], nil
    dir = assert_nothing_raised(bug7547) do
      break Dir.mktmpdir("~")
    end
    assert_match(/\A~/, File.basename(dir), bug7547)
  ensure
    ENV["HOME"] = home
    Dir.rmdir(dir) if dir
  end

  def test_mktmpdir_nil
    Dir.mktmpdir(nil) {|d|
      assert_kind_of(String, d)
    }
  end

  def test_mktmpdir_mutate
    bug16918 = '[ruby-core:98563]'
    assert_nothing_raised(bug16918) do
      assert_mktmpdir_traversal do |traversal_path|
        Dir.mktmpdir(traversal_path + 'foo') do |actual|
          actual << "foo"
        end
      end
    end
  end

  def test_mktmpdir_traversal
    assert_mktmpdir_traversal do |traversal_path|
      Dir.mktmpdir(traversal_path + 'foo') do |actual|
        actual
      end
    end
  end

  def test_mktmpdir_traversal_array
    assert_mktmpdir_traversal do |traversal_path|
      Dir.mktmpdir([traversal_path, 'foo']) do |actual|
        actual
      end
    end
  end

  def assert_mktmpdir_traversal
    Dir.mktmpdir do |target|
      target = target.chomp('/') + '/'
      traversal_path = target.sub(/\A\w:/, '') # for DOSISH
      traversal_path = Array.new(target.count('/')-2, '..').join('/') + traversal_path
      [File::SEPARATOR, File::ALT_SEPARATOR].compact.each do |separator|
        actual = yield traversal_path.tr('/', separator)
        assert_not_send([File.absolute_path(actual), :start_with?, target])
      end
    end
  end

  def test_ractor
    assert_ractor(<<~'end;', require: "tmpdir")
      r = Ractor.new do
        Dir.mktmpdir() do |d|
          Ractor.yield d
          Ractor.receive
        end
      end
      dir = r.take
      assert_file.directory? dir
      r.send true
      r.take
      assert_file.not_exist? dir
    end;
  end
end