/
cache_test.rb
189 lines (164 loc) · 7.4 KB
/
cache_test.rb
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# frozen_string_literal: true
require('test_helper')
module Bootsnap
module LoadPathCache
class CacheTest < MiniTest::Test
def setup
@dir1 = File.realpath(Dir.mktmpdir)
@dir2 = File.realpath(Dir.mktmpdir)
FileUtils.touch("#{@dir1}/a.rb")
FileUtils.mkdir_p("#{@dir1}/foo/bar")
FileUtils.touch("#{@dir1}/foo/bar/baz.rb")
FileUtils.touch("#{@dir2}/b.rb")
FileUtils.touch("#{@dir1}/conflict.rb")
FileUtils.touch("#{@dir2}/conflict.rb")
FileUtils.touch("#{@dir1}/dl#{DLEXT}")
FileUtils.touch("#{@dir1}/both.rb")
FileUtils.touch("#{@dir1}/both#{DLEXT}")
FileUtils.touch("#{@dir1}/béé.rb")
end
def teardown
FileUtils.rm_rf(@dir1)
FileUtils.rm_rf(@dir2)
end
# dev.yml specifies 2.3.3 and this test assumes it. Failures on other
# versions aren't a big deal, but feel free to fix the test.
def test_builtin_features
cache = Cache.new(NullCache, [])
assert_raises(ReturnFalse) { cache.find('thread') }
assert_raises(ReturnFalse) { cache.find('thread.rb') }
assert_raises(ReturnFalse) { cache.find('enumerator') }
assert_raises(ReturnFalse) { cache.find('enumerator.so') }
if RUBY_PLATFORM =~ /darwin/
assert_raises(ReturnFalse) { cache.find('enumerator.bundle') }
else
assert_raises(FallbackScan) { cache.find('enumerator.bundle') }
end
bundle = RUBY_PLATFORM =~ /darwin/ ? 'bundle' : 'so'
refute(cache.find('thread.' + bundle))
refute(cache.find('enumerator.rb'))
refute(cache.find('encdb.' + bundle))
end
def test_simple
po = [@dir1]
cache = Cache.new(NullCache, po)
assert_equal("#{@dir1}/a.rb", cache.find('a'))
refute(cache.find('a', try_extensions: false))
cache.push_paths(po, @dir2)
assert_equal("#{@dir2}/b.rb", cache.find('b'))
refute(cache.find('b', try_extensions: false))
end
def test_extension_append_for_relative_paths
po = [@dir1]
cache = Cache.new(NullCache, po)
dir1_basename = File.basename(@dir1)
Dir.chdir(@dir1) do
assert_equal("#{@dir1}/a.rb", cache.find('./a'))
assert_equal("#{@dir1}/a", cache.find('./a', try_extensions: false))
assert_equal("#{@dir1}/a.rb", cache.find("../#{dir1_basename}/a"))
assert_equal("#{@dir1}/a", cache.find("../#{dir1_basename}/a", try_extensions: false))
assert_equal("#{@dir1}/dl#{DLEXT}", cache.find('./dl'))
assert_equal("#{@dir1}/dl", cache.find('./dl', try_extensions: false))
assert_equal("#{@dir1}/enoent", cache.find('./enoent'))
assert_equal("#{@dir1}/enoent", cache.find('./enoent', try_extensions: false))
end
end
def test_unshifted_paths_have_higher_precedence
po = [@dir1]
cache = Cache.new(NullCache, po)
assert_equal("#{@dir1}/conflict.rb", cache.find('conflict'))
assert_equal("#{@dir1}/conflict.rb", cache.find('conflict.rb', try_extensions: false))
cache.unshift_paths(po, @dir2)
assert_equal("#{@dir2}/conflict.rb", cache.find('conflict'))
assert_equal("#{@dir2}/conflict.rb", cache.find('conflict.rb', try_extensions: false))
end
def test_pushed_paths_have_lower_precedence
po = [@dir1]
cache = Cache.new(NullCache, po)
assert_equal("#{@dir1}/conflict.rb", cache.find('conflict'))
assert_equal("#{@dir1}/conflict.rb", cache.find('conflict.rb', try_extensions: false))
cache.push_paths(po, @dir2)
assert_equal("#{@dir1}/conflict.rb", cache.find('conflict'))
assert_equal("#{@dir1}/conflict.rb", cache.find('conflict.rb', try_extensions: false))
end
def test_directory_caching
cache = Cache.new(NullCache, [@dir1])
assert_equal(@dir1, cache.load_dir("foo"))
assert_equal(@dir1, cache.load_dir("foo/bar"))
assert_nil(cache.load_dir("bar"))
end
def test_extension_permutations
cache = Cache.new(NullCache, [@dir1])
assert_equal("#{@dir1}/dl#{DLEXT}", cache.find('dl'))
refute(cache.find('dl', try_extensions: false))
assert_equal("#{@dir1}/dl#{DLEXT}", cache.find("dl#{DLEXT}"))
assert_equal("#{@dir1}/both.rb", cache.find("both"))
refute(cache.find("both", try_extensions: false))
assert_equal("#{@dir1}/both.rb", cache.find("both.rb"))
assert_equal("#{@dir1}/both.rb", cache.find("both.rb", try_extensions: false))
assert_equal("#{@dir1}/both#{DLEXT}", cache.find("both#{DLEXT}"))
assert_equal("#{@dir1}/both#{DLEXT}", cache.find("both#{DLEXT}", try_extensions: false))
end
def test_relative_paths_rescanned
Dir.chdir(@dir2) do
cache = Cache.new(NullCache, %w(foo))
refute(cache.find('bar/baz'))
Dir.chdir(@dir1) do
# one caveat here is that you get the actual path back when
# resolving relative paths. On darwin, this means that
# /var/folders/... comes back as /private/var/folders/... -- In
# production, this should be fine, but for this test to pass, we
# have to resolve it.
assert_equal(File.realpath("#{@dir1}/foo/bar/baz.rb"), cache.find('bar/baz'))
end
end
end
def test_development_mode
time = Process.clock_gettime(Process::CLOCK_MONOTONIC).to_i
# without development_mode, no refresh
dev_no_cache = Cache.new(NullCache, [@dir1], development_mode: false)
dev_yes_cache = Cache.new(NullCache, [@dir1], development_mode: true)
FileUtils.touch("#{@dir1}/new.rb")
dev_no_cache.stubs(:now).returns(time + 31)
refute(dev_no_cache.find('new'))
dev_yes_cache.stubs(:now).returns(time + 28)
assert_raises(Bootsnap::LoadPathCache::FallbackScan) do
dev_yes_cache.find('new')
end
dev_yes_cache.stubs(:now).returns(time + 31)
assert(dev_yes_cache.find('new'))
end
def test_path_obj_equal?
path_obj = []
cache = Cache.new(NullCache, path_obj)
path_obj.unshift(@dir1)
assert_equal("#{@dir1}/a.rb", cache.find('a'))
end
if RUBY_VERSION >= '2.5' && !(RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
# https://github.com/ruby/ruby/pull/4061
# https://bugs.ruby-lang.org/issues/17517
OS_ASCII_PATH_ENCODING = RUBY_VERSION >= '3.1' ? Encoding::UTF_8 : Encoding::US_ASCII
def test_path_encoding
po = [@dir1]
cache = Cache.new(NullCache, po)
path = cache.find('a')
assert_equal("#{@dir1}/a.rb", path)
require path
internal_path = $LOADED_FEATURES.last
assert_equal(OS_ASCII_PATH_ENCODING, internal_path.encoding)
assert_equal(OS_ASCII_PATH_ENCODING, path.encoding)
File.write(path, '')
assert_same path, internal_path
utf8_path = cache.find('béé')
require utf8_path
internal_utf8_path = $LOADED_FEATURES.last
assert_equal("#{@dir1}/béé.rb", utf8_path)
assert_equal(Encoding::UTF_8, internal_utf8_path.encoding)
assert_equal(Encoding::UTF_8, utf8_path.encoding)
File.write(utf8_path, '')
assert_same utf8_path, internal_utf8_path
end
end
end
end
end