ATTRIBUTE_VALUE_TESTS = %w(
  &
  <
  >
  "
  '
  &amp; 
  &lt; 
  &gt; 
  &quot; 
  &apos; 
  &#38;
  &#60;
  &#62;
  &#34;
  &#39;
  &#x26;
  &#x3c;
  &#x3E;
  &#x22;
  &#x27;
  &amp;amp; 
  &amp;lt; 
  &amp;gt; 
  &amp;quot; 
  &amp;apos; 
  &#38;amp; 
  &#38;lt; 
  &#38;gt; 
  &#38;quot; 
  &#38;apos; 
  &#x26;amp; 
  &#x26;lt; 
  &#x26;gt; 
  &#x26;quot; 
  &#x26;apos;
)

require 'rexml/document'

if REXML::Document.new("<e a='&amp;'/>").to_s.index('&amp;amp;')
  # http://www.germane-software.com/projects/rexml/ticket/122
  unless ARGV.include?("mp")
    module REXML
      class Text
        ENT_OR_NUM_REF = /&(?!#?#{Entity::NAME};)/
        def Text::normalize( input, doctype=nil, entity_filter=nil )
          copy = input
          # Doing it like this rather than in a loop improves the speed
          copy = copy.gsub( ENT_OR_NUM_REF, '&amp;' )
          # copy = copy.gsub( "&", "&amp;" )
          if doctype
            # Replace all ampersands that aren't part of an entity
            doctype.entities.each_value do |entity|
              copy = copy.gsub( entity.value, 
                "&#{entity.name};" ) if entity.value and 
                  not( entity_filter and entity_filter.include?(entity) )
            end
          else
            # Replace all ampersands that aren't part of an entity
            DocType::DEFAULT_ENTITIES.each_value do |entity|
              copy = copy.gsub(entity.value, "&#{entity.name};" )
            end
          end
          copy
        end
      end
    end
  end
end

require 'test/unit'
class RoundTripAttributeValueTests < Test::Unit::TestCase
  ATTRIBUTE_VALUE_TESTS.each_with_index do |attr, index|
    define_method "test_serializer_#{index}" do
      doc = REXML::Document.new("<e/>")
      doc.root.attributes['a'] = attr
      assert_equal attr, REXML::Document.new(doc.to_s).root.attributes['a']
    end unless ARGV.include?("nots")

    next if %w{< &}.include? attr # illegal inside attributes

    define_method "test_parser_#{index}" do
      element = "<e a='#{attr}'/>"
      element = "<e a=\"#{attr}\"/>" if attr == "'"
      doc = REXML::Document.new(element)
      if attr.length == 1
        # special characters are replaced with an entity reference
        assert_match /<e a='&\w+;'\/>/, doc.to_s
      else
        # everything else should be left as is
        assert_equal element, doc.to_s
      end
    end unless ARGV.include?("notp")
  end
end
