1require 'rubygems/test_case'
2require 'rubygems/indexer'
3
4unless defined?(Builder::XChar) then
5  warn "Gem::Indexer tests are being skipped.  Install builder gem." if $VERBOSE
6end
7
8class TestGemIndexer < Gem::TestCase
9
10  def setup
11    super
12
13    util_clear_gems
14    util_make_gems
15
16    @d2_0 = quick_spec 'd', '2.0' do |s|
17      s.date = Gem::Specification::TODAY - 86400 * 3
18    end
19    util_build_gem @d2_0
20
21    @d2_0_a = quick_spec 'd', '2.0.a'
22    util_build_gem @d2_0_a
23
24    @d2_0_b = quick_spec 'd', '2.0.b'
25    util_build_gem @d2_0_b
26
27    @tempdir = File.join(@tempdir, 'indexer')
28
29    gems = File.join(@tempdir, 'gems')
30    FileUtils.mkdir_p gems
31    FileUtils.mv Dir[File.join(@gemhome, "cache", '*.gem')], gems
32
33    @indexer = Gem::Indexer.new(@tempdir)
34  end
35
36  def test_initialize
37    assert_equal @tempdir, @indexer.dest_directory
38    assert_equal File.join(Dir.tmpdir, "gem_generate_index_#{$$}"),
39                 @indexer.directory
40
41    indexer = Gem::Indexer.new @tempdir
42    assert indexer.build_modern
43
44    indexer = Gem::Indexer.new @tempdir, :build_modern => true
45    assert indexer.build_modern
46  end
47
48  def test_build_indicies
49    @indexer.make_temp_directories
50
51    use_ui @ui do
52      @indexer.build_indicies
53    end
54
55    specs_path = File.join @indexer.directory, "specs.#{@marshal_version}"
56    specs_dump = Gem.read_binary specs_path
57    specs = Marshal.load specs_dump
58
59    expected = [["a",      Gem::Version.new("1"),   "ruby"],
60                ["a",      Gem::Version.new("2"),   "ruby"],
61                ["a_evil", Gem::Version.new("9"),   "ruby"],
62                ["b",      Gem::Version.new("2"),   "ruby"],
63                ["c",      Gem::Version.new("1.2"), "ruby"],
64                ["d",      Gem::Version.new("2.0"), "ruby"],
65                ["dep_x",  Gem::Version.new("1"),   "ruby"],
66                ["pl",     Gem::Version.new("1"),   "i386-linux"],
67                ["x",      Gem::Version.new("1"),   "ruby"]]
68
69    assert_equal expected, specs
70
71    latest_specs_path = File.join(@indexer.directory,
72                                  "latest_specs.#{@marshal_version}")
73    latest_specs_dump = Gem.read_binary latest_specs_path
74    latest_specs = Marshal.load latest_specs_dump
75
76    expected = [["a",      Gem::Version.new("2"),   "ruby"],
77                ["a_evil", Gem::Version.new("9"),   "ruby"],
78                ["b",      Gem::Version.new("2"),   "ruby"],
79                ["c",      Gem::Version.new("1.2"), "ruby"],
80                ["d",      Gem::Version.new("2.0"), "ruby"],
81                ["dep_x",  Gem::Version.new("1"),   "ruby"],
82                ["pl",     Gem::Version.new("1"),   "i386-linux"],
83                ["x",      Gem::Version.new("1"),   "ruby"]]
84
85    assert_equal expected, latest_specs, 'latest_specs'
86  end
87
88  def test_generate_index
89    use_ui @ui do
90      @indexer.generate_index
91    end
92
93    quickdir = File.join @tempdir, 'quick'
94    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
95
96    assert File.directory?(quickdir)
97    assert File.directory?(marshal_quickdir)
98
99    assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz"
100    assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz"
101
102    refute_indexed marshal_quickdir, File.basename(@c1_2.spec_file)
103
104    assert_indexed @tempdir, "specs.#{@marshal_version}"
105    assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
106
107    assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
108    assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
109  end
110
111  def test_generate_index_modern
112    @indexer.build_modern = true
113
114    use_ui @ui do
115      @indexer.generate_index
116    end
117
118    refute_indexed @tempdir, 'yaml'
119    refute_indexed @tempdir, 'yaml.Z'
120    refute_indexed @tempdir, "Marshal.#{@marshal_version}"
121    refute_indexed @tempdir, "Marshal.#{@marshal_version}.Z"
122
123    quickdir = File.join @tempdir, 'quick'
124    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
125
126    assert File.directory?(quickdir), 'quickdir should be directory'
127    assert File.directory?(marshal_quickdir)
128
129    refute_indexed quickdir, "index"
130    refute_indexed quickdir, "index.rz"
131
132    refute_indexed quickdir, "latest_index"
133    refute_indexed quickdir, "latest_index.rz"
134
135    refute_indexed quickdir, "#{File.basename(@a1.spec_file)}.rz"
136    refute_indexed quickdir, "#{File.basename(@a2.spec_file)}.rz"
137    refute_indexed quickdir, "#{File.basename(@b2.spec_file)}.rz"
138    refute_indexed quickdir, "#{File.basename(@c1_2.spec_file)}.rz"
139
140    refute_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
141    refute_indexed quickdir, "#{File.basename(@pl1.spec_file)}.rz"
142
143    assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz"
144    assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz"
145
146    refute_indexed quickdir, "#{File.basename(@c1_2.spec_file)}"
147    refute_indexed marshal_quickdir, "#{File.basename(@c1_2.spec_file)}"
148
149    assert_indexed @tempdir, "specs.#{@marshal_version}"
150    assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
151
152    assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
153    assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
154  end
155
156  def test_generate_index_modern_back_to_back
157    @indexer.build_modern = true
158
159    use_ui @ui do
160      @indexer.generate_index
161    end
162
163    @indexer = Gem::Indexer.new @tempdir
164    @indexer.build_modern = true
165
166    use_ui @ui do
167      @indexer.generate_index
168    end
169    quickdir = File.join @tempdir, 'quick'
170    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
171
172    assert File.directory?(quickdir)
173    assert File.directory?(marshal_quickdir)
174
175    assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz"
176    assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz"
177
178    assert_indexed @tempdir, "specs.#{@marshal_version}"
179    assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
180
181    assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
182    assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
183  end
184
185  def test_generate_index_ui
186    use_ui @ui do
187      @indexer.generate_index
188    end
189
190    assert_match %r%^\.\.\.\.\.\.\.\.\.\.\.\.$%, @ui.output
191    assert_match %r%^Generating Marshal quick index gemspecs for 12 gems$%,
192                 @ui.output
193    assert_match %r%^Complete$%, @ui.output
194    assert_match %r%^Generating specs index$%, @ui.output
195    assert_match %r%^Generating latest specs index$%, @ui.output
196    assert_match %r%^Generating prerelease specs index$%, @ui.output
197    assert_match %r%^Complete$%, @ui.output
198    assert_match %r%^Compressing indicies$%, @ui.output
199
200    assert_equal '', @ui.error
201  end
202
203  def test_generate_index_specs
204    use_ui @ui do
205      @indexer.generate_index
206    end
207
208    specs_path = File.join @tempdir, "specs.#{@marshal_version}"
209
210    specs_dump = Gem.read_binary specs_path
211    specs = Marshal.load specs_dump
212
213    expected = [
214      ['a',      Gem::Version.new(1),     'ruby'],
215      ['a',      Gem::Version.new(2),     'ruby'],
216      ['a_evil', Gem::Version.new(9),     'ruby'],
217      ['b',      Gem::Version.new(2),     'ruby'],
218      ['c',      Gem::Version.new('1.2'), 'ruby'],
219      ['d',      Gem::Version.new('2.0'), 'ruby'],
220      ['dep_x',  Gem::Version.new(1),     'ruby'],
221      ['pl',     Gem::Version.new(1),     'i386-linux'],
222      ['x',      Gem::Version.new(1),     'ruby'],
223    ]
224
225    assert_equal expected, specs
226
227    assert_same specs[0].first, specs[1].first,
228                'identical names not identical'
229
230    assert_same specs[0][1],    specs[-1][1],
231                'identical versions not identical'
232
233    assert_same specs[0].last, specs[1].last,
234                'identical platforms not identical'
235
236    refute_same specs[1][1], specs[5][1],
237                'different versions not different'
238  end
239
240  def test_generate_index_latest_specs
241    use_ui @ui do
242      @indexer.generate_index
243    end
244
245    latest_specs_path = File.join @tempdir, "latest_specs.#{@marshal_version}"
246
247    latest_specs_dump = Gem.read_binary latest_specs_path
248    latest_specs = Marshal.load latest_specs_dump
249
250    expected = [
251      ['a',      Gem::Version.new(2),     'ruby'],
252      ['a_evil', Gem::Version.new(9),     'ruby'],
253      ['b',      Gem::Version.new(2),     'ruby'],
254      ['c',      Gem::Version.new('1.2'), 'ruby'],
255      ['d',      Gem::Version.new('2.0'), 'ruby'],
256      ['dep_x',  Gem::Version.new(1),     'ruby'],
257      ['pl',     Gem::Version.new(1),     'i386-linux'],
258      ['x',      Gem::Version.new(1),     'ruby'],
259    ]
260
261    assert_equal expected, latest_specs
262
263    assert_same latest_specs[0][1],   latest_specs[2][1],
264                'identical versions not identical'
265
266    assert_same latest_specs[0].last, latest_specs[1].last,
267                'identical platforms not identical'
268  end
269
270  def test_generate_index_prerelease_specs
271    use_ui @ui do
272      @indexer.generate_index
273    end
274
275    prerelease_specs_path = File.join @tempdir, "prerelease_specs.#{@marshal_version}"
276
277    prerelease_specs_dump = Gem.read_binary prerelease_specs_path
278    prerelease_specs = Marshal.load prerelease_specs_dump
279
280    assert_equal [['a', Gem::Version.new('3.a'),   'ruby'],
281                  ['d', Gem::Version.new('2.0.a'), 'ruby'],
282                  ['d', Gem::Version.new('2.0.b'), 'ruby']],
283                 prerelease_specs
284  end
285
286  ##
287  # Emulate the starting state of Gem::Specification in a live environment,
288  # where it will carry the list of system gems
289  def with_system_gems
290    Gem::Specification.reset
291
292    sys_gem = quick_spec 'systemgem', '1.0'
293    util_build_gem sys_gem
294    Gem::Specification.add_spec sys_gem
295    yield
296    util_remove_gem sys_gem
297  end
298
299
300  def test_update_index
301    use_ui @ui do
302      @indexer.generate_index
303    end
304
305    quickdir = File.join @tempdir, 'quick'
306    marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
307
308    assert File.directory?(quickdir)
309    assert File.directory?(marshal_quickdir)
310
311    @d2_1 = quick_spec 'd', '2.1'
312    util_build_gem @d2_1
313    @d2_1_tuple = [@d2_1.name, @d2_1.version, @d2_1.original_platform]
314
315    @d2_1_a = quick_spec 'd', '2.2.a'
316    util_build_gem @d2_1_a
317    @d2_1_a_tuple = [@d2_1_a.name, @d2_1_a.version, @d2_1_a.original_platform]
318
319    gems = File.join @tempdir, 'gems'
320
321    FileUtils.mv @d2_1.cache_file, gems
322    FileUtils.mv @d2_1_a.cache_file, gems
323
324    with_system_gems do
325      use_ui @ui do
326        @indexer.update_index
327      end
328
329      assert_indexed marshal_quickdir, "#{File.basename(@d2_1.spec_file)}.rz"
330
331      specs_index = Marshal.load Gem.read_binary(@indexer.dest_specs_index)
332
333      assert_includes specs_index, @d2_1_tuple
334      refute_includes specs_index, @d2_1_a_tuple
335
336      latest_specs_index = Marshal.load \
337        Gem.read_binary(@indexer.dest_latest_specs_index)
338
339      assert_includes latest_specs_index, @d2_1_tuple
340      assert_includes latest_specs_index,
341                      [@d2_0.name, @d2_0.version, @d2_0.original_platform]
342      refute_includes latest_specs_index, @d2_1_a_tuple
343
344      pre_specs_index = Marshal.load \
345        Gem.read_binary(@indexer.dest_prerelease_specs_index)
346
347      assert_includes pre_specs_index, @d2_1_a_tuple
348      refute_includes pre_specs_index, @d2_1_tuple
349    end
350  end
351
352  def assert_indexed(dir, name)
353    file = File.join dir, name
354    assert File.exist?(file), "#{file} does not exist"
355  end
356
357  def refute_indexed(dir, name)
358    file = File.join dir, name
359    refute File.exist?(file), "#{file} exists"
360  end
361
362end if defined?(Builder::XChar)
363
364