Update CHANGELOG.md
[rack.git] / test / spec_headers.rb
blobaf96315c3e502e2d3f6f8d7df9c9525506092d08
1 # frozen_string_literal: true
3 require_relative 'helper'
5 separate_testing do
6   require_relative '../lib/rack/headers'
7 end
9 class RackHeadersTest < Minitest::Spec
10   before do
11     @h = Rack::Headers.new
12     @fh = Rack::Headers['AB'=>'1', 'cd'=>'2', '3'=>'4']
13   end
15   def test_public_interface
16     headers_methods = Rack::Headers.public_instance_methods.sort
17     hash_methods = Hash.public_instance_methods.sort
18     assert_empty(headers_methods - hash_methods)
19     assert_empty(hash_methods - headers_methods)
20   end
22   def test_class_aref
23     assert_equal Hash[], Rack::Headers[]
24     assert_equal Hash['a'=>'2'], Rack::Headers['A'=>'2']
25     assert_equal Hash['a'=>'2', 'b'=>'4'], Rack::Headers['A'=>'2', 'B'=>'4']
26     assert_equal Hash['a','2','b','4'], Rack::Headers['A','2','B','4']
27     assert_raises(ArgumentError){Rack::Headers['A']}
28     assert_raises(ArgumentError){Rack::Headers['A',2,'B']}
29   end
31   def test_default_values
32     h, ch = Hash.new, Rack::Headers.new
33     assert_equal h, ch
34     h, ch = Hash.new('1'), Rack::Headers.new('1')
35     assert_equal h, ch
36     assert_equal h['3'], ch['3']
37     h['a'], ch['A'] = ['2', '2']
38     assert_equal h['a'], ch['a']
39     h, ch = Hash.new{|h,k| k*2}, Rack::Headers.new{|h,k| k*2}
40     assert_equal h['3'], ch['3']
41     h['c'], ch['C'] = ['2', '2']
42     assert_equal h['c'], ch['c']
43     assert_raises(ArgumentError){Rack::Headers.new('1'){|hash,k| key}}
45     assert_nil @fh.default
46     assert_nil @fh.default_proc
47     assert_nil @fh['55']
48     assert_equal '3', Rack::Headers.new('3').default
49     assert_nil Rack::Headers.new('3').default_proc
50     assert_equal '3', Rack::Headers.new('3')['1']
52     @fh.default = '4'
53     assert_equal '4', @fh.default
54     assert_nil  @fh.default_proc
55     assert_equal '4', @fh['55']
57     h = Rack::Headers.new('5')
58     assert_equal '5', h.default
59     assert_nil  h.default_proc
60     assert_equal '5', h['55']
62     h = Rack::Headers.new{|hash, key| '1234'}
63     assert_nil  h.default
64     refute_equal nil, h.default_proc
65     assert_equal '1234', h['55']
67     h = Rack::Headers.new{|hash, key| hash[key] = '1234'; nil}
68     assert_nil  h.default
69     refute_equal nil, h.default_proc
70     assert_nil  h['Ac']
71     assert_equal '1234', h['aC']
72   end
74   def test_store_and_retrieve
75     assert_nil  @h['a']
76     @h['A'] = '2'
77     assert_equal '2', @h['a']
78     assert_equal '2', @h['A']
79     @h['a'] = '3'
80     assert_equal '3', @h['a']
81     assert_equal '3', @h['A']
82     @h['AB'] = '5'
83     assert_equal '5', @h['ab']
84     assert_equal '5', @h['AB']
85     assert_equal '5', @h['aB']
86     assert_equal '5', @h['Ab']
87     @h.store('C', '8')
88     assert_equal '8', @h['c']
89     assert_equal '8', @h['C']
90   end
92   def test_clear
93     assert_equal 3, @fh.length
94     @fh.clear
95     assert_equal Hash[], @fh
96     assert_equal 0, @fh.length
97   end
99   def test_delete
100     assert_equal 3, @fh.length
101     assert_equal '1', @fh.delete('aB')
102     assert_equal 2, @fh.length
103     assert_nil @fh.delete('Ab')
104     assert_equal 2, @fh.length
105   end
107   def test_delete_if_and_reject
108     assert_equal 3, @fh.length
109     hash = @fh.reject{|key, value| key == 'ab' || key == 'cd'}
110     assert_equal 1, hash.length
111     assert_equal Hash['3'=>'4'], hash
112     assert_equal 3, @fh.length
113     hash = @fh.delete_if{|key, value| key == 'ab' || key == 'cd'}
114     assert_equal 1, hash.length
115     assert_equal Hash['3'=>'4'], hash
116     assert_equal 1, @fh.length
117     assert_equal Hash['3'=>'4'], @fh
118     assert_nil  @fh.reject!{|key, value| key == 'ab' || key == 'cd'}
119     hash = @fh.reject!{|key, value| key == '3'}
120     assert_equal 0, hash.length
121     assert_equal Hash[], hash
122     assert_equal 0, @fh.length
123     assert_equal Hash[], @fh
124   end
126   def test_dup_and_clone
127     def @h.foo; 1; end
128     h2 = @h.dup
129     h3 = @h.clone
130     h2['A'] = '2'
131     h3['B'] = '3'
132     assert_equal Rack::Headers[], @h
133     assert_raises NoMethodError do h2.foo end
134     assert_equal 1, h3.foo
135     assert_equal '2', h2['a']
136     assert_equal '3', h3['b']
137   end
139   def test_each
140     i = 0
141     @h.each{i+=1}
142     assert_equal 0, i
143     items = [['ab','1'], ['cd','2'], ['3','4']]
144     @fh.each do |k,v|
145       assert items.include?([k,v])
146       items -= [[k,v]]
147     end
148     assert_equal [], items
149   end
151   def test_each_key
152     i = 0
153     @h.each{i+=1}
154     assert_equal 0, i
155     keys = ['ab', 'cd', '3']
156     @fh.each_key do |k|
157       assert keys.include?(k)
158       assert k.frozen?
159       keys -= [k]
160     end
161     assert_equal [], keys
162   end
164   def test_each_value
165     i = 0
166     @h.each{i+=1}
167     assert_equal 0, i
168     values = ['1', '2', '4']
169     @fh.each_value do |v|
170       assert values.include?(v)
171       values -= [v]
172     end
173     assert_equal [], values
174   end
176   def test_empty
177     assert @h.empty?
178     assert !@fh.empty?
179   end
181   def test_fetch
182     assert_raises(ArgumentError){@h.fetch(1,2,3)}
183     assert_raises(ArgumentError){@h.fetch(1,2,3){4}}
184     assert_raises(IndexError){@h.fetch(1)}
185     @h.default = '33'
186     assert_raises(IndexError){@h.fetch(1)}
187     @h['1'] = '8'
188     assert_equal '8', @h.fetch('1')
189     assert_equal '3', @h.fetch(2, '3')
190     assert_equal '222', @h.fetch('2'){|k| k*3}
191     assert_equal '1', @fh.fetch('Ab')
192     assert_equal '2', @fh.fetch('cD', '3')
193     assert_equal '4', @fh.fetch("3", 3)
194     assert_equal '4', @fh.fetch("3"){|k| k*3}
195     assert_raises(IndexError){Rack::Headers.new{34}.fetch(1)}
196   end
198   def test_has_key
199     %i'include? has_key? key? member?'.each do |meth|
200       assert !@h.send(meth,1)
201       assert @fh.send(meth,'Ab')
202       assert @fh.send(meth,'cD')
203       assert @fh.send(meth,'3')
204       assert @fh.send(meth,'ab')
205       assert @fh.send(meth,'CD')
206       assert @fh.send(meth,'3')
207       assert !@fh.send(meth,1)
208     end
209   end
211   def test_has_value
212     %i'value? has_value?'.each do |meth|
213       assert !@h.send(meth,'1')
214       assert @fh.send(meth,'1')
215       assert @fh.send(meth,'2')
216       assert @fh.send(meth,'4')
217       assert !@fh.send(meth,'3')
218     end
219   end
221   def test_inspect
222     %i'inspect to_s'.each do |meth|
223       assert_equal({}.inspect, @h.send(meth))
224       assert_equal({"ab"=>"1", "cd"=>"2", "3"=>"4"}.inspect, @fh.send(meth))
225     end
226   end
228   def test_invert
229     assert_kind_of(Rack::Headers, @h.invert)
230     assert_equal({}, @h.invert)
231     assert_equal({"1"=>"ab", "2"=>"cd", "4"=>"3"}, @fh.invert)
232     assert_equal({'cd'=>'ab'}, Rack::Headers['AB'=>'CD'].invert)
233     assert_equal({'cd'=>'xy'}, Rack::Headers['AB'=>'Cd', 'xY'=>'cD'].invert)
234   end
236   def test_keys
237     assert_equal [], @h.keys
238     assert_equal %w'ab cd 3', @fh.keys
239   end
241   def test_length
242     %i'length size'.each do |meth|
243       assert_equal 0, @h.send(meth)
244       assert_equal 3, @fh.send(meth)
245     end
246   end
248   def test_merge_and_update
249     assert_equal @h, @h.merge({})
250     assert_equal @fh, @fh.merge({})
251     assert_equal Rack::Headers['ab'=>'55'], @h.merge({'ab'=>'55'})
252     assert_equal Rack::Headers[], @h
253     assert_equal Rack::Headers['ab'=>'55'], @h.update({'ab'=>'55'})
254     assert_equal Rack::Headers['ab'=>'55'], @h
255     assert_equal Rack::Headers['ab'=>'55', 'cd'=>'2', '3'=>'4'], @fh.merge({'ab'=>'55'})
256     assert_equal Rack::Headers['ab'=>'1', 'cd'=>'2', '3'=>'4'], @fh
257     assert_equal Rack::Headers['ab'=>'55', 'cd'=>'2', '3'=>'4'], @fh.merge!({'ab'=>'55'})
258     assert_equal Rack::Headers['ab'=>'55', 'cd'=>'2', '3'=>'4'], @fh
259     assert_equal Rack::Headers['ab'=>'abss55', 'cd'=>'2', '3'=>'4'], @fh.merge({'ab'=>'ss'}){|k,ov,nv| [k,nv,ov].join}
260     assert_equal Rack::Headers['ab'=>'55', 'cd'=>'2', '3'=>'4'], @fh
261     assert_equal Rack::Headers['ab'=>'abss55', 'cd'=>'2', '3'=>'4'], @fh.update({'ab'=>'ss'}){|k,ov,nv| [k,nv,ov].join}
262     assert_equal Rack::Headers['ab'=>'abss55', 'cd'=>'2', '3'=>'4'], @fh
263     assert_equal Rack::Headers['ab'=>'abssabss55', 'cd'=>'2', '3'=>'4'], @fh.merge!({'ab'=>'ss'}){|k,ov,nv| [k,nv,ov].join}
264     assert_equal Rack::Headers['ab'=>'abssabss55', 'cd'=>'2', '3'=>'4'], @fh
265   end
267   def test_replace
268     h = @h.dup
269     fh = @fh.dup
270     h1 = fh.replace(@h)
271     assert_equal @h, h1
272     assert_same fh, h1
274     h2 = h.replace(@fh)
275     assert_equal @fh, h2
276     assert_same h, h2
278     assert_equal @h, fh.replace({})
279     assert_equal @fh, h.replace('AB'=>'1', 'cd'=>'2', '3'=>'4')
280   end
282   def test_select
283     assert_equal({}, @h.select{true})
284     assert_equal({}, @h.select{false})
285     assert_equal({'3' => '4', "ab" => '1', 'cd' => '2'}, @fh.select{true})
286     assert_equal({}, @fh.select{false})
287     assert_equal({'cd' => '2'}, @fh.select{|k,v| k.start_with?('c')})
288     assert_equal({'3' => '4'}, @fh.select{|k,v| v == '4'})
289   end
291   def test_shift
292     assert_nil @h.shift
293     array = @fh.to_a
294     i = 3
295     while true
296       assert i >= 0
297       kv = @fh.shift
298       if kv.nil?
299         assert_equal [], array
300         break
301       else
302         i -= 1
303         assert array.include?(kv)
304         array -= [kv]
305       end
306     end
307     assert_equal [], array
308     assert_equal 0, i
309   end
311   def test_sort
312     assert_equal [], @h.sort
313     assert_equal [], @h.sort{|a,b| a.to_s<=>b.to_s}
314     assert_equal [['ab', '1'], ['cd', '4'], ['ef', '2']], Rack::Headers['CD','4','AB','1','EF','2'].sort
315     assert_equal [['3', '4'], ['ab', '1'], ['cd', '2']], @fh.sort{|(ak,av),(bk,bv)| ak.to_s<=>bk.to_s}
316   end
318   def test_to_a
319     assert_equal [], @h.to_a
320     assert_equal [['ab', '1'], ['cd', '2'], ['3', '4']], @fh.to_a
321   end
323   def test_to_hash
324     assert_equal Hash[], @h.to_hash
325     assert_equal Hash['3','4','ab','1','cd','2'], @fh.to_hash
326   end
328   def test_values
329     assert_equal [], @h.values
330     assert_equal ['f', 'c'], Rack::Headers['aB','f','1','c'].values
331   end
333   def test_values_at
334     assert_equal [], @h.values_at()
335     assert_equal [nil], @h.values_at(1)
336     assert_equal [nil, nil], @h.values_at(1, 1)
337     assert_equal [], @fh.values_at()
338     assert_equal ['1'], @fh.values_at('AB')
339     assert_equal ['2', '1'], @fh.values_at('CD', 'Ab')
340     assert_equal ['2', nil, '1'], @fh.values_at('CD', 32, 'aB')
341     assert_equal ['4', '2', nil, '1'], @fh.values_at('3', 'CD', 32, 'ab')
342   end
344   def test_assoc
345     assert_nil  @h.assoc(1)
346     assert_equal ['ab', '1'], @fh.assoc('Ab')
347     assert_equal ['cd', '2'], @fh.assoc('CD')
348     assert_nil  @fh.assoc('4')
349     assert_equal ['3', '4'], @fh.assoc('3')
350   end
352   def test_default_proc=
353     @h.default_proc = proc{|h, k| k * 2}
354     assert_equal 'aa', @h['A']
355     @h['Ab'] = '2'
356     assert_equal '2', @h['aB']
357   end
359   def test_flatten
360     assert_equal [], @h.flatten
361     assert_equal ['ab', '1', 'cd', '2', '3', '4'], @fh.flatten
362     @fh['X'] = '56'
363     assert_equal ['ab', '1', 'cd', '2', '3', '4', 'x', '56'], @fh.flatten
364     assert_equal ['ab', '1', 'cd', '2', '3', '4', 'x', '56'], @fh.flatten(2)
365   end
367   def test_keep_if
368     assert_equal @h, @h.keep_if{|k, v| true}
369     assert_equal @fh, @fh.keep_if{|k, v| true}
370     assert_equal @h, @fh.dup.keep_if{|k, v| false}
371     assert_equal Rack::Headers["AB"=>'1'], @fh.keep_if{|k, v| k == "ab"}
372   end
374   def test_key
375     assert_nil @h.key('1')
376     assert_nil @fh.key(1)
377     assert_equal 'ab', @fh.key('1')
378     assert_equal 'cd', @fh.key('2')
379     assert_nil @fh.key('3')
380     assert_equal '3', @fh.key('4')
381   end
383   def test_rassoc
384     assert_nil @h.rassoc('1')
385     assert_equal ['ab', '1'], @fh.rassoc('1')
386     assert_equal ['cd', '2'], @fh.rassoc('2')
387     assert_nil @fh.rassoc('3')
388     assert_equal ['3', '4'], @fh.rassoc('4')
389   end
391   def test_select!
392     assert_nil @h.select!{|k, v| true}
393     assert_nil @fh.select!{|k, v| true}
394     assert_equal @h, @fh.dup.select!{|k, v| false}
395     assert_equal Rack::Headers["AB"=>'1'], @fh.select!{|k, v| k == "ab"}
396   end
398   def test_compare_by_identity
399     assert_raises(TypeError){@fh.compare_by_identity}
400   end
402   def test_compare_by_identity?
403     assert_equal(false, @fh.compare_by_identity?)
404   end
406   def test_to_h
407     assert_equal Hash[], @h.to_h
408     assert_equal Hash['3','4','ab','1','cd','2'], @fh.to_h
409   end
411   def test_dig
412     assert_equal('1', @fh.dig('AB'))
413     assert_equal('2', @fh.dig('Cd'))
414     assert_equal('4', @fh.dig('3'))
415     assert_nil(@fh.dig('4'))
417     assert_raises(TypeError){@fh.dig('AB', 1)}
418     assert_raises(TypeError){@fh.dig('cd', 2)}
419     assert_raises(TypeError){@fh.dig('3', 3)}
420     assert_nil(@fh.dig('4', 5))
421   end
423   def test_fetch_values
424     assert_equal(['1'], @fh.fetch_values('AB'))
425     assert_equal(['1', '2', '4'], @fh.fetch_values('AB', 'Cd', '3'))
426     assert_raises(KeyError){@fh.fetch_values('AB', 'cD', '4')}
427   end
429   def test_to_proc
430     pr = @fh.to_proc
431     assert_equal('1', pr['AB'])
432     assert_equal('2', pr['cD'])
433     assert_equal('4', pr['3'])
434     assert_nil(pr['4'])
435   end
437   def test_compact
438     assert_equal(false, @fh.compact.equal?(@fh))
439     assert_equal(@fh, @fh.compact)
440     assert_equal(Rack::Headers['Ab'=>1], Rack::Headers['aB'=>1, 'cd'=>nil].compact)
441   end
443   def test_compact!
444     fh = @fh.dup
445     assert_nil(@fh.compact!)
446     assert_equal(fh, @fh)
448     h = Rack::Headers['Ab'=>1, 'cd'=>nil]
449     assert_equal(Rack::Headers['aB'=>1], h.compact!)
450     assert_equal(Rack::Headers['AB'=>1], h)
451   end
453   def test_transform_values
454     fh = @fh.transform_values{|v| v.to_s*2}
455     assert_equal('1', @fh['aB'])
456     assert_equal(Rack::Headers['AB'=>'11', 'cD'=>'22', '3'=>'44'], fh)
457     assert_equal('11', fh['Ab'])
458   end
460   def test_transform_values!
461     @fh.transform_values!{|v| v.to_s*2}
462     assert_equal('11', @fh['AB'])
463     assert_equal(Rack::Headers['Ab'=>'11', 'CD'=>'22', '3'=>'44'], @fh)
464     assert_equal('11', @fh['aB'])
465   end
467   if RUBY_VERSION >= '2.5'
468     def test_slice
469       assert_equal(Rack::Headers['Ab'=>'1', 'cD'=>'2', '3'=>'4'], @fh.slice('aB', 'Cd', '3'))
470       assert_equal(Rack::Headers['AB'=>'1', 'CD'=>'2'], @fh.slice('Ab', 'CD'))
471       assert_equal(Rack::Headers[], @fh.slice('ad'))
472       assert_equal('1', @fh.slice('AB', 'cd')['Ab'])
473     end
475     def test_transform_keys
476       map = {'ab'=>'Xy', 'cd'=>'dC', '3'=>'5'}
477       dh = @fh.dup
478       fh = @fh.transform_keys{|k| map[k]}
479       assert_equal(dh, @fh)
480       assert_equal('1', fh['xY'])
481       assert_equal('2', fh['Dc'])
482       assert_equal('4', fh['5'])
483     end
485     def test_transform_keys!
486       map = {'ab'=>'Xy', 'cd'=>'dC', '3'=>'5'}
487       dh = @fh.dup
488       @fh.transform_keys!{|k| map[k]}
489       assert_equal(false, dh == @fh)
490       assert_equal('1', @fh['xY'])
491       assert_equal('2', @fh['DC'])
492       assert_equal('4', @fh['5'])
493     end
494   end
496   if RUBY_VERSION >= '2.6'
497     def test_filter!
498       assert_nil @h.filter!{|k, v| true}
499       assert_nil @fh.filter!{|k, v| true}
500       assert_equal @h, @fh.dup.filter!{|k, v| false}
501       assert_equal Rack::Headers["AB"=>'1'], @fh.filter!{|k, v| k == "ab"}
502     end
503   end
505   if RUBY_VERSION >= '2.7'
506     def test_deconstruct_keys
507       assert_equal(@fh.to_hash, @fh.deconstruct_keys([]))
508       assert_equal(Rack::Headers, @fh.deconstruct_keys([]).class)
509     end
510   end
512   if RUBY_VERSION >= '3.0'
513     def test_except
514       @fh = Rack::Headers['AB'=>'1', 'Cd'=>'2', '3'=>'4']
515       assert_equal(@fh, @fh.except)
516       assert_equal(Rack::Headers['cD'=>'2', '3'=>'4'], @fh.except('AB', 5))
517       assert_equal(Rack::Headers['AB'=>'1'], @fh.except('cD', '3'))
518     end
519   end