3 # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
5 # See LICENSE.txt for permissions.
9 require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
10 require 'rubygems/source_info_cache'
12 class Gem::SourceIndex
16 class TestGemSourceInfoCache < RubyGemTestCase
19 @original_sources = Gem.sources
23 util_setup_fake_fetcher
25 @sic = Gem::SourceInfoCache.new
26 @sic.instance_variable_set :@fetcher, @fetcher
28 @si_new = Gem::SourceIndex.new
29 @sice_new = Gem::SourceInfoCacheEntry.new @si_new, 0
38 Gem.sources.replace @original_sources
39 Gem::SourceInfoCache.instance_variable_set :@cache, nil
42 def test_self_cache_refreshes
43 Gem.configuration.update_sources = true #true by default
44 si = Gem::SourceIndex.new
47 @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
49 Gem.sources.replace %W[#{@gem_repo}]
52 assert_not_nil Gem::SourceInfoCache.cache
53 assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
54 assert_equal Gem::SourceInfoCache.cache.object_id,
55 Gem::SourceInfoCache.cache.object_id
58 assert_match %r|Bulk updating|, @ui.output
61 def test_self_cache_skips_refresh_based_on_configuration
62 Gem.configuration.update_sources = false
63 si = Gem::SourceIndex.new
66 @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
68 Gem.sources.replace %w[#{@gem_repo}]
71 assert_not_nil Gem::SourceInfoCache.cache
72 assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
73 assert_equal Gem::SourceInfoCache.cache.object_id,
74 Gem::SourceInfoCache.cache.object_id
75 assert_no_match %r|Bulk updating|, @ui.output
79 def test_self_cache_data
80 si = Gem::SourceIndex.new
83 @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
85 Gem::SourceInfoCache.instance_variable_set :@cache, nil
86 sice = Gem::SourceInfoCacheEntry.new si, 0
89 gems = Gem::SourceInfoCache.cache_data[@gem_repo].source_index.gems
90 gem_names = gems.map { |_, spec| spec.full_name }
92 assert_equal si.gems.map { |_,spec| spec.full_name }, gem_names
97 assert_equal [[@gem_repo, @usr_sice]], @sic.cache_data.to_a.sort
100 def test_cache_data_dirty
101 def @sic.dirty() @dirty; end
102 assert_equal false, @sic.dirty, 'clean on init'
104 assert_equal false, @sic.dirty, 'clean on fetch'
107 assert_equal true, @sic.dirty, 'still dirty'
110 def test_cache_data_irreparable
111 @fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = @source_index.dump
113 data = { @gem_repo => { 'totally' => 'borked' } }
116 @sic.system_cache_file,
117 @sic.latest_system_cache_file,
118 @sic.user_cache_file,
119 @sic.latest_user_cache_file
122 cache_files.each do |fn|
123 FileUtils.mkdir_p File.dirname(fn)
124 open(fn, "wb") { |f| f.write Marshal.dump(data) }
127 @sic.instance_eval { @cache_data = nil }
129 fetched = use_ui @ui do @sic.cache_data end
131 fetched_si = fetched["#{@gem_repo}"].source_index
133 assert_equal @source_index.index_signature, fetched_si.index_signature
136 def test_cache_data_none_readable
137 FileUtils.chmod 0222, @sic.system_cache_file
138 FileUtils.chmod 0222, @sic.latest_system_cache_file
139 FileUtils.chmod 0222, @sic.user_cache_file
140 FileUtils.chmod 0222, @sic.latest_user_cache_file
141 return if (File.stat(@sic.system_cache_file).mode & 0222) != 0222
142 return if (File.stat(@sic.user_cache_file).mode & 0222) != 0222
143 # HACK for systems that don't support chmod
144 assert_equal({}, @sic.cache_data)
147 def test_cache_data_none_writable
148 FileUtils.chmod 0444, @sic.system_cache_file
149 FileUtils.chmod 0444, @sic.user_cache_file
150 e = assert_raise RuntimeError do
153 assert_equal 'unable to locate a writable cache file', e.message
156 def test_cache_data_nonexistent
157 FileUtils.rm @sic.system_cache_file
158 FileUtils.rm @sic.latest_system_cache_file
159 FileUtils.rm @sic.user_cache_file
160 FileUtils.rm @sic.latest_user_cache_file
162 # TODO test verbose output
163 assert_equal [], @sic.cache_data.to_a.sort
166 def test_cache_data_repair
169 'cache' => Gem::SourceIndex.new,
173 [@sic.system_cache_file, @sic.user_cache_file].each do |fn|
174 FileUtils.mkdir_p File.dirname(fn)
175 open(fn, "wb") { |f| f.write Marshal.dump(data) }
178 @sic.instance_eval { @cache_data = nil }
182 Gem::SourceInfoCacheEntry.new(Gem::SourceIndex.new, 0)
184 assert_equal expected, @sic.cache_data
187 def test_cache_data_user_fallback
188 FileUtils.chmod 0444, @sic.system_cache_file
190 assert_equal [[@gem_repo, @usr_sice]], @sic.cache_data.to_a.sort
194 assert_equal @gemcache, @sic.cache_file
197 def test_cache_file_user_fallback
198 FileUtils.chmod 0444, @sic.system_cache_file
199 assert_equal @usrcache, @sic.cache_file
202 def test_cache_file_none_writable
203 FileUtils.chmod 0444, @sic.system_cache_file
204 FileUtils.chmod 0444, @sic.user_cache_file
205 e = assert_raise RuntimeError do
208 assert_equal 'unable to locate a writable cache file', e.message
212 @sic.cache_data[@gem_repo] = @sice_new
216 assert_equal [[@gem_repo, @sice_new]],
217 read_cache(@sic.system_cache_file).to_a.sort
220 def test_latest_cache_data
223 sice = Gem::SourceInfoCacheEntry.new @source_index, 0
225 @sic.set_cache_data @gem_repo => sice
226 latest = @sic.latest_cache_data
227 gems = latest[@gem_repo].source_index.search('a').map { |s| s.full_name }
229 assert_equal %w[a-2 a_evil-9], gems
232 def test_latest_cache_file
233 latest_cache_file = File.join File.dirname(@gemcache),
234 "latest_#{File.basename @gemcache}"
235 assert_equal latest_cache_file, @sic.latest_cache_file
238 def test_latest_system_cache_file
239 assert_equal File.join(Gem.dir, "latest_source_cache"),
240 @sic.latest_system_cache_file
243 def test_latest_user_cache_file
244 assert_equal @latest_usrcache, @sic.latest_user_cache_file
247 def test_read_system_cache
248 assert_equal [[@gem_repo, @sys_sice]], @sic.cache_data.to_a.sort
251 def test_read_user_cache
252 FileUtils.chmod 0444, @sic.user_cache_file
253 FileUtils.chmod 0444, @sic.latest_user_cache_file
255 @si = Gem::SourceIndex.new
256 @si.add_specs @a1, @a2
258 @sice = Gem::SourceInfoCacheEntry.new @si, 0
260 @sic.set_cache_data({ @gem_repo => @sice })
263 @sic.reset_cache_data
265 user_cache_data = @sic.cache_data.to_a.sort
267 assert_equal 1, user_cache_data.length
268 user_cache_data = user_cache_data.first
270 assert_equal @gem_repo, user_cache_data.first
272 gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
273 assert_equal [@a2.full_name], gems
277 si = Gem::SourceIndex.new
279 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
280 @sic.instance_variable_set :@cache_data, cache_data
282 assert_equal [@a1], @sic.search(//)
288 sice = Gem::SourceInfoCacheEntry.new @source_index, 0
290 @sic.set_cache_data @gem_repo => sice
292 @sic.instance_variable_set :@only_latest, false
294 @sic.reset_cache_data
296 gem_names = @sic.search(//, false, true).map { |spec| spec.full_name }
298 assert_equal %w[a-1 a-2 a_evil-9 c-1.2], gem_names
301 def test_search_dependency
302 si = Gem::SourceIndex.new
304 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
305 @sic.instance_variable_set :@cache_data, cache_data
307 dep = Gem::Dependency.new @a1.name, @a1.version
309 assert_equal [@a1], @sic.search(dep)
312 def test_search_no_matches
313 si = Gem::SourceIndex.new
315 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
316 @sic.instance_variable_set :@cache_data, cache_data
318 assert_equal [], @sic.search(/nonexistent/)
321 def test_search_no_matches_in_source
322 si = Gem::SourceIndex.new
324 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
325 @sic.instance_variable_set :@cache_data, cache_data
326 Gem.sources.replace %w[more-gems.example.com]
328 assert_equal [], @sic.search(/nonexistent/)
331 def test_search_with_source
332 si = Gem::SourceIndex.new
334 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
335 @sic.instance_variable_set :@cache_data, cache_data
337 assert_equal [[@a1, @gem_repo]],
338 @sic.search_with_source(//)
341 def test_system_cache_file
342 assert_equal File.join(Gem.dir, "source_cache"), @sic.system_cache_file
345 def test_user_cache_file
346 assert_equal @usrcache, @sic.user_cache_file
350 @sic.cache_data[@gem_repo] = @sice_new
353 assert_equal [[@gem_repo, @sice_new]],
354 read_cache(@sic.system_cache_file).to_a.sort
355 assert_equal [[@gem_repo, @usr_sice]],
356 read_cache(@sic.user_cache_file).to_a.sort
359 def test_write_cache_user
360 FileUtils.chmod 0444, @sic.system_cache_file
361 @sic.set_cache_data({@gem_repo => @sice_new})
364 @sic.instance_variable_set :@only_latest, false
366 assert File.exist?(@sic.user_cache_file), 'user_cache_file'
367 assert File.exist?(@sic.latest_user_cache_file),
368 'latest_user_cache_file exists'
370 assert_equal [[@gem_repo, @sys_sice]],
371 read_cache(@sic.system_cache_file).to_a.sort
372 assert_equal [[@gem_repo, @sice_new]],
373 read_cache(@sic.user_cache_file).to_a.sort
376 def test_write_cache_user_from_scratch
377 FileUtils.rm_rf @sic.user_cache_file
378 FileUtils.rm_rf @sic.latest_user_cache_file
380 FileUtils.chmod 0444, @sic.system_cache_file
381 FileUtils.chmod 0444, @sic.latest_system_cache_file
383 @si = Gem::SourceIndex.new
384 @si.add_specs @a1, @a2
386 @sice = Gem::SourceInfoCacheEntry.new @si, 0
388 @sic.set_cache_data({ @gem_repo => @sice })
393 assert File.exist?(@sic.user_cache_file), 'system_cache_file'
394 assert File.exist?(@sic.latest_user_cache_file),
395 'latest_system_cache_file'
397 user_cache_data = read_cache(@sic.user_cache_file).to_a.sort
398 assert_equal 1, user_cache_data.length, 'user_cache_data length'
399 user_cache_data = user_cache_data.first
401 assert_equal @gem_repo, user_cache_data.first
403 gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
404 assert_equal [@a1.full_name, @a2.full_name], gems
406 user_cache_data = read_cache(@sic.latest_user_cache_file).to_a.sort
407 assert_equal 1, user_cache_data.length
408 user_cache_data = user_cache_data.first
410 assert_equal @gem_repo, user_cache_data.first
412 gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
413 assert_equal [@a2.full_name], gems
416 def test_write_cache_user_no_directory
417 FileUtils.rm_rf File.dirname(@sic.user_cache_file)
418 FileUtils.chmod 0444, @sic.system_cache_file
419 @sic.set_cache_data({ @gem_repo => @sice_new })
423 assert_equal [[@gem_repo, @sys_sice]],
424 read_cache(@sic.system_cache_file).to_a.sort
425 assert_equal [[@gem_repo, @sys_sice]],
426 read_cache(@sic.user_cache_file).to_a.sort
427 assert_equal [[@gem_repo, @sice_new]],
428 read_cache(@sic.latest_user_cache_file).to_a.sort
431 def test_write_cache_user_only_latest
432 FileUtils.chmod 0444, @sic.system_cache_file
433 @sic.set_cache_data({@gem_repo => @sice_new})
437 assert File.exist?(@sic.user_cache_file), 'user_cache_file'
438 assert File.exist?(@sic.latest_user_cache_file),
439 'latest_user_cache_file exists'
441 assert_equal [[@gem_repo, @sys_sice]],
442 read_cache(@sic.system_cache_file).to_a.sort
443 assert_equal [[@gem_repo, @sice_new]],
444 read_cache(@sic.user_cache_file).to_a.sort