# frozen_string_literal: true require_relative 'helper' separate_testing do require_relative '../lib/rack/headers' end class RackHeadersTest < Minitest::Spec before do @h = Rack::Headers.new @fh = Rack::Headers['AB'=>'1', 'cd'=>'2', '3'=>'4'] end def test_public_interface headers_methods = Rack::Headers.public_instance_methods.sort hash_methods = Hash.public_instance_methods.sort assert_empty(headers_methods - hash_methods) assert_empty(hash_methods - headers_methods) end def test_class_aref assert_equal Hash[], Rack::Headers[] assert_equal Hash['a'=>'2'], Rack::Headers['A'=>'2'] assert_equal Hash['a'=>'2', 'b'=>'4'], Rack::Headers['A'=>'2', 'B'=>'4'] assert_equal Hash['a','2','b','4'], Rack::Headers['A','2','B','4'] assert_raises(ArgumentError){Rack::Headers['A']} assert_raises(ArgumentError){Rack::Headers['A',2,'B']} end def test_default_values h, ch = Hash.new, Rack::Headers.new assert_equal h, ch h, ch = Hash.new('1'), Rack::Headers.new('1') assert_equal h, ch assert_equal h['3'], ch['3'] h['a'], ch['A'] = ['2', '2'] assert_equal h['a'], ch['a'] h, ch = Hash.new{|h,k| k*2}, Rack::Headers.new{|h,k| k*2} assert_equal h['3'], ch['3'] h['c'], ch['C'] = ['2', '2'] assert_equal h['c'], ch['c'] assert_raises(ArgumentError){Rack::Headers.new('1'){|hash,k| key}} assert_nil @fh.default assert_nil @fh.default_proc assert_nil @fh['55'] assert_equal '3', Rack::Headers.new('3').default assert_nil Rack::Headers.new('3').default_proc assert_equal '3', Rack::Headers.new('3')['1'] @fh.default = '4' assert_equal '4', @fh.default assert_nil @fh.default_proc assert_equal '4', @fh['55'] h = Rack::Headers.new('5') assert_equal '5', h.default assert_nil h.default_proc assert_equal '5', h['55'] h = Rack::Headers.new{|hash, key| '1234'} assert_nil h.default refute_equal nil, h.default_proc assert_equal '1234', h['55'] h = Rack::Headers.new{|hash, key| hash[key] = '1234'; nil} assert_nil h.default refute_equal nil, h.default_proc assert_nil h['Ac'] assert_equal '1234', h['aC'] end def test_store_and_retrieve assert_nil @h['a'] @h['A'] = '2' assert_equal '2', @h['a'] assert_equal '2', @h['A'] @h['a'] = '3' assert_equal '3', @h['a'] assert_equal '3', @h['A'] @h['AB'] = '5' assert_equal '5', @h['ab'] assert_equal '5', @h['AB'] assert_equal '5', @h['aB'] assert_equal '5', @h['Ab'] @h.store('C', '8') assert_equal '8', @h['c'] assert_equal '8', @h['C'] end def test_clear assert_equal 3, @fh.length @fh.clear assert_equal Hash[], @fh assert_equal 0, @fh.length end def test_delete assert_equal 3, @fh.length assert_equal '1', @fh.delete('aB') assert_equal 2, @fh.length assert_nil @fh.delete('Ab') assert_equal 2, @fh.length end def test_delete_if_and_reject assert_equal 3, @fh.length hash = @fh.reject{|key, value| key == 'ab' || key == 'cd'} assert_equal 1, hash.length assert_equal Hash['3'=>'4'], hash assert_equal 3, @fh.length hash = @fh.delete_if{|key, value| key == 'ab' || key == 'cd'} assert_equal 1, hash.length assert_equal Hash['3'=>'4'], hash assert_equal 1, @fh.length assert_equal Hash['3'=>'4'], @fh assert_nil @fh.reject!{|key, value| key == 'ab' || key == 'cd'} hash = @fh.reject!{|key, value| key == '3'} assert_equal 0, hash.length assert_equal Hash[], hash assert_equal 0, @fh.length assert_equal Hash[], @fh end def test_dup_and_clone def @h.foo; 1; end h2 = @h.dup h3 = @h.clone h2['A'] = '2' h3['B'] = '3' assert_equal Rack::Headers[], @h assert_raises NoMethodError do h2.foo end assert_equal 1, h3.foo assert_equal '2', h2['a'] assert_equal '3', h3['b'] end def test_each i = 0 @h.each{i+=1} assert_equal 0, i items = [['ab','1'], ['cd','2'], ['3','4']] @fh.each do |k,v| assert items.include?([k,v]) items -= [[k,v]] end assert_equal [], items end def test_each_key i = 0 @h.each{i+=1} assert_equal 0, i keys = ['ab', 'cd', '3'] @fh.each_key do |k| assert keys.include?(k) assert k.frozen? keys -= [k] end assert_equal [], keys end def test_each_value i = 0 @h.each{i+=1} assert_equal 0, i values = ['1', '2', '4'] @fh.each_value do |v| assert values.include?(v) values -= [v] end assert_equal [], values end def test_empty assert @h.empty? assert !@fh.empty? end def test_fetch assert_raises(ArgumentError){@h.fetch(1,2,3)} assert_raises(ArgumentError){@h.fetch(1,2,3){4}} assert_raises(IndexError){@h.fetch(1)} @h.default = '33' assert_raises(IndexError){@h.fetch(1)} @h['1'] = '8' assert_equal '8', @h.fetch('1') assert_equal '3', @h.fetch(2, '3') assert_equal '222', @h.fetch('2'){|k| k*3} assert_equal '1', @fh.fetch('Ab') assert_equal '2', @fh.fetch('cD', '3') assert_equal '4', @fh.fetch("3", 3) assert_equal '4', @fh.fetch("3"){|k| k*3} assert_raises(IndexError){Rack::Headers.new{34}.fetch(1)} end def test_has_key %i'include? has_key? key? member?'.each do |meth| assert !@h.send(meth,1) assert @fh.send(meth,'Ab') assert @fh.send(meth,'cD') assert @fh.send(meth,'3') assert @fh.send(meth,'ab') assert @fh.send(meth,'CD') assert @fh.send(meth,'3') assert !@fh.send(meth,1) end end def test_has_value %i'value? has_value?'.each do |meth| assert !@h.send(meth,'1') assert @fh.send(meth,'1') assert @fh.send(meth,'2') assert @fh.send(meth,'4') assert !@fh.send(meth,'3') end end def test_inspect %i'inspect to_s'.each do |meth| assert_equal '{}', @h.send(meth) assert_equal '{"ab"=>"1", "cd"=>"2", "3"=>"4"}', @fh.send(meth) end end def test_invert assert_kind_of(Rack::Headers, @h.invert) assert_equal({}, @h.invert) assert_equal({"1"=>"ab", "2"=>"cd", "4"=>"3"}, @fh.invert) assert_equal({'cd'=>'ab'}, Rack::Headers['AB'=>'CD'].invert) assert_equal({'cd'=>'xy'}, Rack::Headers['AB'=>'Cd', 'xY'=>'cD'].invert) end def test_keys assert_equal [], @h.keys assert_equal %w'ab cd 3', @fh.keys end def test_length %i'length size'.each do |meth| assert_equal 0, @h.send(meth) assert_equal 3, @fh.send(meth) end end def test_merge_and_update assert_equal @h, @h.merge({}) assert_equal @fh, @fh.merge({}) assert_equal Rack::Headers['ab'=>'55'], @h.merge({'ab'=>'55'}) assert_equal Rack::Headers[], @h assert_equal Rack::Headers['ab'=>'55'], @h.update({'ab'=>'55'}) assert_equal Rack::Headers['ab'=>'55'], @h assert_equal Rack::Headers['ab'=>'55', 'cd'=>'2', '3'=>'4'], @fh.merge({'ab'=>'55'}) assert_equal Rack::Headers['ab'=>'1', 'cd'=>'2', '3'=>'4'], @fh assert_equal Rack::Headers['ab'=>'55', 'cd'=>'2', '3'=>'4'], @fh.merge!({'ab'=>'55'}) assert_equal Rack::Headers['ab'=>'55', 'cd'=>'2', '3'=>'4'], @fh assert_equal Rack::Headers['ab'=>'abss55', 'cd'=>'2', '3'=>'4'], @fh.merge({'ab'=>'ss'}){|k,ov,nv| [k,nv,ov].join} assert_equal Rack::Headers['ab'=>'55', 'cd'=>'2', '3'=>'4'], @fh assert_equal Rack::Headers['ab'=>'abss55', 'cd'=>'2', '3'=>'4'], @fh.update({'ab'=>'ss'}){|k,ov,nv| [k,nv,ov].join} assert_equal Rack::Headers['ab'=>'abss55', 'cd'=>'2', '3'=>'4'], @fh assert_equal Rack::Headers['ab'=>'abssabss55', 'cd'=>'2', '3'=>'4'], @fh.merge!({'ab'=>'ss'}){|k,ov,nv| [k,nv,ov].join} assert_equal Rack::Headers['ab'=>'abssabss55', 'cd'=>'2', '3'=>'4'], @fh end def test_replace h = @h.dup fh = @fh.dup h1 = fh.replace(@h) assert_equal @h, h1 assert_same fh, h1 h2 = h.replace(@fh) assert_equal @fh, h2 assert_same h, h2 assert_equal @h, fh.replace({}) assert_equal @fh, h.replace('AB'=>'1', 'cd'=>'2', '3'=>'4') end def test_select assert_equal({}, @h.select{true}) assert_equal({}, @h.select{false}) assert_equal({'3' => '4', "ab" => '1', 'cd' => '2'}, @fh.select{true}) assert_equal({}, @fh.select{false}) assert_equal({'cd' => '2'}, @fh.select{|k,v| k.start_with?('c')}) assert_equal({'3' => '4'}, @fh.select{|k,v| v == '4'}) end def test_shift assert_nil @h.shift array = @fh.to_a i = 3 while true assert i >= 0 kv = @fh.shift if kv.nil? assert_equal [], array break else i -= 1 assert array.include?(kv) array -= [kv] end end assert_equal [], array assert_equal 0, i end def test_sort assert_equal [], @h.sort assert_equal [], @h.sort{|a,b| a.to_s<=>b.to_s} assert_equal [['ab', '1'], ['cd', '4'], ['ef', '2']], Rack::Headers['CD','4','AB','1','EF','2'].sort assert_equal [['3', '4'], ['ab', '1'], ['cd', '2']], @fh.sort{|(ak,av),(bk,bv)| ak.to_s<=>bk.to_s} end def test_to_a assert_equal [], @h.to_a assert_equal [['ab', '1'], ['cd', '2'], ['3', '4']], @fh.to_a end def test_to_hash assert_equal Hash[], @h.to_hash assert_equal Hash['3','4','ab','1','cd','2'], @fh.to_hash end def test_values assert_equal [], @h.values assert_equal ['f', 'c'], Rack::Headers['aB','f','1','c'].values end def test_values_at assert_equal [], @h.values_at() assert_equal [nil], @h.values_at(1) assert_equal [nil, nil], @h.values_at(1, 1) assert_equal [], @fh.values_at() assert_equal ['1'], @fh.values_at('AB') assert_equal ['2', '1'], @fh.values_at('CD', 'Ab') assert_equal ['2', nil, '1'], @fh.values_at('CD', 32, 'aB') assert_equal ['4', '2', nil, '1'], @fh.values_at('3', 'CD', 32, 'ab') end def test_assoc assert_nil @h.assoc(1) assert_equal ['ab', '1'], @fh.assoc('Ab') assert_equal ['cd', '2'], @fh.assoc('CD') assert_nil @fh.assoc('4') assert_equal ['3', '4'], @fh.assoc('3') end def test_default_proc= @h.default_proc = proc{|h, k| k * 2} assert_equal 'aa', @h['A'] @h['Ab'] = '2' assert_equal '2', @h['aB'] end def test_flatten assert_equal [], @h.flatten assert_equal ['ab', '1', 'cd', '2', '3', '4'], @fh.flatten @fh['X'] = '56' assert_equal ['ab', '1', 'cd', '2', '3', '4', 'x', '56'], @fh.flatten assert_equal ['ab', '1', 'cd', '2', '3', '4', 'x', '56'], @fh.flatten(2) end def test_keep_if assert_equal @h, @h.keep_if{|k, v| true} assert_equal @fh, @fh.keep_if{|k, v| true} assert_equal @h, @fh.dup.keep_if{|k, v| false} assert_equal Rack::Headers["AB"=>'1'], @fh.keep_if{|k, v| k == "ab"} end def test_key assert_nil @h.key('1') assert_nil @fh.key(1) assert_equal 'ab', @fh.key('1') assert_equal 'cd', @fh.key('2') assert_nil @fh.key('3') assert_equal '3', @fh.key('4') end def test_rassoc assert_nil @h.rassoc('1') assert_equal ['ab', '1'], @fh.rassoc('1') assert_equal ['cd', '2'], @fh.rassoc('2') assert_nil @fh.rassoc('3') assert_equal ['3', '4'], @fh.rassoc('4') end def test_select! assert_nil @h.select!{|k, v| true} assert_nil @fh.select!{|k, v| true} assert_equal @h, @fh.dup.select!{|k, v| false} assert_equal Rack::Headers["AB"=>'1'], @fh.select!{|k, v| k == "ab"} end def test_compare_by_identity assert_raises(TypeError){@fh.compare_by_identity} end def test_compare_by_identity? assert_equal(false, @fh.compare_by_identity?) end def test_to_h assert_equal Hash[], @h.to_h assert_equal Hash['3','4','ab','1','cd','2'], @fh.to_h end def test_dig assert_equal('1', @fh.dig('AB')) assert_equal('2', @fh.dig('Cd')) assert_equal('4', @fh.dig('3')) assert_nil(@fh.dig('4')) assert_raises(TypeError){@fh.dig('AB', 1)} assert_raises(TypeError){@fh.dig('cd', 2)} assert_raises(TypeError){@fh.dig('3', 3)} assert_nil(@fh.dig('4', 5)) end def test_fetch_values assert_equal(['1'], @fh.fetch_values('AB')) assert_equal(['1', '2', '4'], @fh.fetch_values('AB', 'Cd', '3')) assert_raises(KeyError){@fh.fetch_values('AB', 'cD', '4')} end def test_to_proc pr = @fh.to_proc assert_equal('1', pr['AB']) assert_equal('2', pr['cD']) assert_equal('4', pr['3']) assert_nil(pr['4']) end def test_compact assert_equal(false, @fh.compact.equal?(@fh)) assert_equal(@fh, @fh.compact) assert_equal(Rack::Headers['Ab'=>1], Rack::Headers['aB'=>1, 'cd'=>nil].compact) end def test_compact! fh = @fh.dup assert_nil(@fh.compact!) assert_equal(fh, @fh) h = Rack::Headers['Ab'=>1, 'cd'=>nil] assert_equal(Rack::Headers['aB'=>1], h.compact!) assert_equal(Rack::Headers['AB'=>1], h) end def test_transform_values fh = @fh.transform_values{|v| v.to_s*2} assert_equal('1', @fh['aB']) assert_equal(Rack::Headers['AB'=>'11', 'cD'=>'22', '3'=>'44'], fh) assert_equal('11', fh['Ab']) end def test_transform_values! @fh.transform_values!{|v| v.to_s*2} assert_equal('11', @fh['AB']) assert_equal(Rack::Headers['Ab'=>'11', 'CD'=>'22', '3'=>'44'], @fh) assert_equal('11', @fh['aB']) end if RUBY_VERSION >= '2.5' def test_slice assert_equal(Rack::Headers['Ab'=>'1', 'cD'=>'2', '3'=>'4'], @fh.slice('aB', 'Cd', '3')) assert_equal(Rack::Headers['AB'=>'1', 'CD'=>'2'], @fh.slice('Ab', 'CD')) assert_equal(Rack::Headers[], @fh.slice('ad')) assert_equal('1', @fh.slice('AB', 'cd')['Ab']) end def test_transform_keys map = {'ab'=>'Xy', 'cd'=>'dC', '3'=>'5'} dh = @fh.dup fh = @fh.transform_keys{|k| map[k]} assert_equal(dh, @fh) assert_equal('1', fh['xY']) assert_equal('2', fh['Dc']) assert_equal('4', fh['5']) end def test_transform_keys! map = {'ab'=>'Xy', 'cd'=>'dC', '3'=>'5'} dh = @fh.dup @fh.transform_keys!{|k| map[k]} assert_equal(false, dh == @fh) assert_equal('1', @fh['xY']) assert_equal('2', @fh['DC']) assert_equal('4', @fh['5']) end end if RUBY_VERSION >= '2.6' def test_filter! assert_nil @h.filter!{|k, v| true} assert_nil @fh.filter!{|k, v| true} assert_equal @h, @fh.dup.filter!{|k, v| false} assert_equal Rack::Headers["AB"=>'1'], @fh.filter!{|k, v| k == "ab"} end end if RUBY_VERSION >= '2.7' def test_deconstruct_keys assert_equal(@fh.to_hash, @fh.deconstruct_keys([])) assert_equal(Rack::Headers, @fh.deconstruct_keys([]).class) end end if RUBY_VERSION >= '3.0' def test_except @fh = Rack::Headers['AB'=>'1', 'Cd'=>'2', '3'=>'4'] assert_equal(@fh, @fh.except) assert_equal(Rack::Headers['cD'=>'2', '3'=>'4'], @fh.except('AB', 5)) assert_equal(Rack::Headers['AB'=>'1'], @fh.except('cD', '3')) end end end