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
41 def test_self_cache_refreshes
42 Gem.configuration.update_sources = true #true by default
43 si = Gem::SourceIndex.new
46 @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump
48 Gem.sources.replace %W[#{@gem_repo}]
51 assert_not_nil Gem::SourceInfoCache.cache
52 assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
53 assert_equal Gem::SourceInfoCache.cache.object_id,
54 Gem::SourceInfoCache.cache.object_id
55 assert_match %r|Bulk updating|, @ui.output
59 def test_self_cache_skips_refresh_based_on_configuration
60 Gem.configuration.update_sources = false
61 si = Gem::SourceIndex.new
64 @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump
66 Gem.sources.replace %w[#{@gem_repo}]
69 assert_not_nil Gem::SourceInfoCache.cache
70 assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
71 assert_equal Gem::SourceInfoCache.cache.object_id,
72 Gem::SourceInfoCache.cache.object_id
73 assert_no_match %r|Bulk updating|, @ui.output
77 def test_self_cache_data
78 si = Gem::SourceIndex.new
81 @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump
83 Gem::SourceInfoCache.instance_variable_set :@cache, nil
84 sice = Gem::SourceInfoCacheEntry.new si, 0
87 gems = Gem::SourceInfoCache.cache_data[@gem_repo].source_index.gems
88 gem_names = gems.map { |_, spec| spec.full_name }
90 assert_equal si.gems.map { |_,spec| spec.full_name }, gem_names
95 assert_equal [[@gem_repo, @usr_sice]], @sic.cache_data.to_a.sort
98 def test_cache_data_dirty
99 def @sic.dirty() @dirty; end
100 assert_equal false, @sic.dirty, 'clean on init'
102 assert_equal false, @sic.dirty, 'clean on fetch'
105 assert_equal true, @sic.dirty, 'still dirty'
108 def test_cache_data_irreparable
109 @fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = @source_index.dump
111 data = { @gem_repo => { 'totally' => 'borked' } }
114 @sic.system_cache_file,
115 @sic.latest_system_cache_file,
116 @sic.user_cache_file,
117 @sic.latest_user_cache_file
120 cache_files.each do |fn|
121 FileUtils.mkdir_p File.dirname(fn)
122 open(fn, "wb") { |f| f.write Marshal.dump(data) }
125 @sic.instance_eval { @cache_data = nil }
127 fetched = use_ui @ui do @sic.cache_data end
129 fetched_si = fetched["#{@gem_repo}"].source_index
131 assert_equal @source_index.index_signature, fetched_si.index_signature
134 def test_cache_data_none_readable
135 FileUtils.chmod 0222, @sic.system_cache_file
136 FileUtils.chmod 0222, @sic.latest_system_cache_file
137 FileUtils.chmod 0222, @sic.user_cache_file
138 FileUtils.chmod 0222, @sic.latest_user_cache_file
139 return if (File.stat(@sic.system_cache_file).mode & 0222) != 0222
140 return if (File.stat(@sic.user_cache_file).mode & 0222) != 0222
141 # HACK for systems that don't support chmod
142 assert_equal({}, @sic.cache_data)
145 def test_cache_data_none_writable
146 FileUtils.chmod 0444, @sic.system_cache_file
147 FileUtils.chmod 0444, @sic.user_cache_file
148 e = assert_raise RuntimeError do
151 assert_equal 'unable to locate a writable cache file', e.message
154 def test_cache_data_nonexistent
155 FileUtils.rm @sic.system_cache_file
156 FileUtils.rm @sic.latest_system_cache_file
157 FileUtils.rm @sic.user_cache_file
158 FileUtils.rm @sic.latest_user_cache_file
160 # TODO test verbose output
161 assert_equal [], @sic.cache_data.to_a.sort
164 def test_cache_data_repair
167 'cache' => Gem::SourceIndex.new,
171 [@sic.system_cache_file, @sic.user_cache_file].each do |fn|
172 FileUtils.mkdir_p File.dirname(fn)
173 open(fn, "wb") { |f| f.write Marshal.dump(data) }
176 @sic.instance_eval { @cache_data = nil }
180 Gem::SourceInfoCacheEntry.new(Gem::SourceIndex.new, 0)
182 assert_equal expected, @sic.cache_data
185 def test_cache_data_user_fallback
186 FileUtils.chmod 0444, @sic.system_cache_file
188 assert_equal [[@gem_repo, @usr_sice]], @sic.cache_data.to_a.sort
192 assert_equal @gemcache, @sic.cache_file
195 def test_cache_file_user_fallback
196 FileUtils.chmod 0444, @sic.system_cache_file
197 assert_equal @usrcache, @sic.cache_file
200 def test_cache_file_none_writable
201 FileUtils.chmod 0444, @sic.system_cache_file
202 FileUtils.chmod 0444, @sic.user_cache_file
203 e = assert_raise RuntimeError do
206 assert_equal 'unable to locate a writable cache file', e.message
210 @sic.cache_data[@gem_repo] = @sice_new
214 assert_equal [[@gem_repo, @sice_new]],
215 read_cache(@sic.system_cache_file).to_a.sort
218 def test_latest_cache_data
221 sice = Gem::SourceInfoCacheEntry.new @source_index, 0
223 @sic.set_cache_data @gem_repo => sice
224 latest = @sic.latest_cache_data
225 gems = latest[@gem_repo].source_index.search('a').map { |s| s.full_name }
227 assert_equal %w[a-2 a_evil-9], gems
230 def test_latest_cache_file
231 latest_cache_file = File.join File.dirname(@gemcache),
232 "latest_#{File.basename @gemcache}"
233 assert_equal latest_cache_file, @sic.latest_cache_file
236 def test_latest_system_cache_file
237 assert_equal File.join(Gem.dir, "latest_source_cache"),
238 @sic.latest_system_cache_file
241 def test_latest_user_cache_file
242 assert_equal @latest_usrcache, @sic.latest_user_cache_file
245 def test_read_system_cache
246 assert_equal [[@gem_repo, @sys_sice]], @sic.cache_data.to_a.sort
249 def test_read_user_cache
250 FileUtils.chmod 0444, @sic.user_cache_file
251 FileUtils.chmod 0444, @sic.latest_user_cache_file
253 @si = Gem::SourceIndex.new
254 @si.add_specs @a1, @a2
256 @sice = Gem::SourceInfoCacheEntry.new @si, 0
258 @sic.set_cache_data({ @gem_repo => @sice })
261 @sic.reset_cache_data
263 user_cache_data = @sic.cache_data.to_a.sort
265 assert_equal 1, user_cache_data.length
266 user_cache_data = user_cache_data.first
268 assert_equal @gem_repo, user_cache_data.first
270 gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
271 assert_equal [@a2.full_name], gems
275 si = Gem::SourceIndex.new
277 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
278 @sic.instance_variable_set :@cache_data, cache_data
280 assert_equal [@a1], @sic.search(//)
286 sice = Gem::SourceInfoCacheEntry.new @source_index, 0
288 @sic.set_cache_data @gem_repo => sice
290 @sic.instance_variable_set :@only_latest, false
292 @sic.reset_cache_data
294 gem_names = @sic.search(//, false, true).map { |spec| spec.full_name }
296 assert_equal %w[a-1 a-2 a_evil-9 c-1.2], gem_names
299 def test_search_dependency
300 si = Gem::SourceIndex.new
302 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
303 @sic.instance_variable_set :@cache_data, cache_data
305 dep = Gem::Dependency.new @a1.name, @a1.version
307 assert_equal [@a1], @sic.search(dep)
310 def test_search_no_matches
311 si = Gem::SourceIndex.new
313 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
314 @sic.instance_variable_set :@cache_data, cache_data
316 assert_equal [], @sic.search(/nonexistent/)
319 def test_search_no_matches_in_source
320 si = Gem::SourceIndex.new
322 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
323 @sic.instance_variable_set :@cache_data, cache_data
324 Gem.sources.replace %w[more-gems.example.com]
326 assert_equal [], @sic.search(/nonexistent/)
329 def test_search_with_source
330 si = Gem::SourceIndex.new
332 cache_data = { @gem_repo => Gem::SourceInfoCacheEntry.new(si, nil) }
333 @sic.instance_variable_set :@cache_data, cache_data
335 assert_equal [[@a1, @gem_repo]],
336 @sic.search_with_source(//)
339 def test_system_cache_file
340 assert_equal File.join(Gem.dir, "source_cache"), @sic.system_cache_file
343 def test_user_cache_file
344 assert_equal @usrcache, @sic.user_cache_file
348 @sic.cache_data[@gem_repo] = @sice_new
351 assert_equal [[@gem_repo, @sice_new]],
352 read_cache(@sic.system_cache_file).to_a.sort
353 assert_equal [[@gem_repo, @usr_sice]],
354 read_cache(@sic.user_cache_file).to_a.sort
357 def test_write_cache_user
358 FileUtils.chmod 0444, @sic.system_cache_file
359 @sic.set_cache_data({@gem_repo => @sice_new})
362 @sic.instance_variable_set :@only_latest, false
364 assert File.exist?(@sic.user_cache_file), 'user_cache_file'
365 assert File.exist?(@sic.latest_user_cache_file),
366 'latest_user_cache_file exists'
368 assert_equal [[@gem_repo, @sys_sice]],
369 read_cache(@sic.system_cache_file).to_a.sort
370 assert_equal [[@gem_repo, @sice_new]],
371 read_cache(@sic.user_cache_file).to_a.sort
374 def test_write_cache_user_from_scratch
375 FileUtils.rm_rf @sic.user_cache_file
376 FileUtils.rm_rf @sic.latest_user_cache_file
378 FileUtils.chmod 0444, @sic.system_cache_file
379 FileUtils.chmod 0444, @sic.latest_system_cache_file
381 @si = Gem::SourceIndex.new
382 @si.add_specs @a1, @a2
384 @sice = Gem::SourceInfoCacheEntry.new @si, 0
386 @sic.set_cache_data({ @gem_repo => @sice })
391 assert File.exist?(@sic.user_cache_file), 'system_cache_file'
392 assert File.exist?(@sic.latest_user_cache_file),
393 'latest_system_cache_file'
395 user_cache_data = read_cache(@sic.user_cache_file).to_a.sort
396 assert_equal 1, user_cache_data.length, 'user_cache_data length'
397 user_cache_data = user_cache_data.first
399 assert_equal @gem_repo, user_cache_data.first
401 gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
402 assert_equal [@a1.full_name, @a2.full_name], gems
404 user_cache_data = read_cache(@sic.latest_user_cache_file).to_a.sort
405 assert_equal 1, user_cache_data.length
406 user_cache_data = user_cache_data.first
408 assert_equal @gem_repo, user_cache_data.first
410 gems = user_cache_data.last.source_index.map { |_,spec| spec.full_name }
411 assert_equal [@a2.full_name], gems
414 def test_write_cache_user_no_directory
415 FileUtils.rm_rf File.dirname(@sic.user_cache_file)
416 FileUtils.chmod 0444, @sic.system_cache_file
417 @sic.set_cache_data({ @gem_repo => @sice_new })
421 assert_equal [[@gem_repo, @sys_sice]],
422 read_cache(@sic.system_cache_file).to_a.sort
423 assert_equal [[@gem_repo, @sys_sice]],
424 read_cache(@sic.user_cache_file).to_a.sort
425 assert_equal [[@gem_repo, @sice_new]],
426 read_cache(@sic.latest_user_cache_file).to_a.sort
429 def test_write_cache_user_only_latest
430 FileUtils.chmod 0444, @sic.system_cache_file
431 @sic.set_cache_data({@gem_repo => @sice_new})
435 assert File.exist?(@sic.user_cache_file), 'user_cache_file'
436 assert File.exist?(@sic.latest_user_cache_file),
437 'latest_user_cache_file exists'
439 assert_equal [[@gem_repo, @sys_sice]],
440 read_cache(@sic.system_cache_file).to_a.sort
441 assert_equal [[@gem_repo, @sice_new]],
442 read_cache(@sic.user_cache_file).to_a.sort