From f267b34ae5241e384878f5fede99964f8db9887a Mon Sep 17 00:00:00 2001 From: Viliam Pucik Date: Sat, 22 Dec 2012 22:27:20 +0100 Subject: [PATCH 1/5] quick and dirty update against gem code https://rubygems.org/downloads/blankslate-3.1.2.gem --- CHANGES | 101 ++++++ MIT-LICENSE | 2 +- README.rdoc | 225 +++++++++++++ Rakefile | 189 +++++++++++ doc/releases/builder-1.2.4.rdoc | 31 ++ doc/releases/builder-2.0.0.rdoc | 46 +++ doc/releases/builder-2.1.1.rdoc | 58 ++++ lib/blankslate.rb | 35 +- spec/blankslate_spec.rb | 38 --- spec/spec_helper.rb | 2 - test/test_blankslate.rb | 217 ++++++++++++ test/test_eventbuilder.rb | 150 +++++++++ test/test_markupbuilder.rb | 573 ++++++++++++++++++++++++++++++++ test/test_method_caching.rb | 62 ++++ test/test_namecollision.rb | 39 +++ test/test_xchar.rb | 77 +++++ 16 files changed, 1798 insertions(+), 47 deletions(-) create mode 100644 CHANGES create mode 100644 README.rdoc create mode 100644 Rakefile create mode 100644 doc/releases/builder-1.2.4.rdoc create mode 100644 doc/releases/builder-2.0.0.rdoc create mode 100755 doc/releases/builder-2.1.1.rdoc delete mode 100644 spec/blankslate_spec.rb delete mode 100644 spec/spec_helper.rb create mode 100644 test/test_blankslate.rb create mode 100644 test/test_eventbuilder.rb create mode 100644 test/test_markupbuilder.rb create mode 100644 test/test_method_caching.rb create mode 100644 test/test_namecollision.rb create mode 100644 test/test_xchar.rb diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..2aa163d --- /dev/null +++ b/CHANGES @@ -0,0 +1,101 @@ += Change Log + +== Version 3.1.0 + +* Included the to_xs arity patch needed for weird Rails compatibility + issue. + +* Escaping newlines in attributes now. + +* Allow method caching + +== Version 3.0.0 + +* Ruby 1.9 compatiblity issues. + +== Version 2.2.0 + +* Applied patch from Thijs van der Vossen to allow UTF-8 encoded + output when the encoding is UTF-8 and $KCODE is UTF8. + +== Version 2.1.2 + +* Fixed bug where private methods in kernel could leak through using + tag!(). Thanks to Hagen Overdick for finding and diagnosing this + bug. + +== Version 2.1.1 + +* Fixed typo in XmlMarkup class docs (ident => indent). (from Martin + Fowler). +* Removed extra directory indirection from legacy CVS to SVN move. +* Removed some extraneous tabs from source. +* Fixed test on private methods in blankslate to differentiate between + targetted and untargetted private methods. +* Removed legacy capture of @self in XmlBase (@self was used back when + we used instance eval). +* Added additional tests for global functions (both direct and included). + +== Version 2.1.0 + +* Fixed bug in BlankSlate where including a module into Object could + cause methods to leak into BlankSlate. +* Made BlankSlate available as its own gem. Currently the builder gem + still directly includes the BlankSlate code. +* Added reveal capability to BlankSlate. + +== Version 2.0.0 + +* Added doc directory +* Added unit tests for XmlEvents. +* Added XChar module and used it in the _escape method. +* Attributes are now quoted by default when strings. Use Symbol + attribute values for unquoted behavior. + +== Version 1.2.4 + +* Added a cdata! command to an XML Builder (from Josh Knowles). + +== Version 1.2.3 + +The attributes in the instruction will be ordered: +version, encoding, standalone. + +== Version 1.2.2 + +Another fix for BlankSlate. The Kernal/Object traps added in 1.2.1 +failed when a method was defined late more than once. Since the +method was already marked as removed, another attempt to undefine it +raised an error. The fix was to check the list of instance methods +before attempting the undef operation. Thanks to Florian Gross and +David Heinemeier Hansson for the patch. + +== Version 1.2.1 + +BlankSlate now traps method definitions in Kernel and Object to avoid +late method definitions inadvertently becoming part of the definition +of BlankSlate as well. + +== Version 1.2.0 + +Improved support for entity declarations by allowing nested +declarations and removal of the attribute processing. + +Added namespace support. + +== Version 1.1.0 + +Added support for comments, entity declarations and processing instructions. + +== Version 1.0.0 + +Removed use of instace_eval making the use of XmlMarkup much +less prone to error. + +== Version 0.1.1 + +Bug fix. + +== Version 0.1.0 + +Initial version release. diff --git a/MIT-LICENSE b/MIT-LICENSE index c00d4c0..7d9be51 100644 --- a/MIT-LICENSE +++ b/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright 2011 Jim Weirich (jim@weirichhouse.org) +Copyright (c) 2003-2012 Jim Weirich (jim.weirich@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.rdoc b/README.rdoc new file mode 100644 index 0000000..1e340bc --- /dev/null +++ b/README.rdoc @@ -0,0 +1,225 @@ +# coding: UTF-8 += Project: Builder + +== Goal + +Provide a simple way to create XML markup and data structures. + +== Classes + +Builder::XmlMarkup:: Generate XML markup notiation +Builder::XmlEvents:: Generate XML events (i.e. SAX-like) + +Notes:: + +* An Builder::XmlTree class to generate XML tree + (i.e. DOM-like) structures is also planned, but not yet implemented. + Also, the events builder is currently lagging the markup builder in + features. + +== Usage + + require 'rubygems' + require_gem 'builder', '~> 2.0' + + builder = Builder::XmlMarkup.new + xml = builder.person { |b| b.name("Jim"); b.phone("555-1234") } + xml #=> Jim555-1234 + +or + + require 'rubygems' + require_gem 'builder' + + builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) + builder.person { |b| b.name("Jim"); b.phone("555-1234") } + # + # Prints: + # + # Jim + # 555-1234 + # + +== Compatibility + +=== Version 2.0.0 Compatibility Changes + +Version 2.0.0 introduces automatically escaped attribute values for +the first time. Versions prior to 2.0.0 did not insert escape +characters into attribute values in the XML markup. This allowed +attribute values to explicitly reference entities, which was +occasionally used by a small number of developers. Since strings +could always be explicitly escaped by hand, this was not a major +restriction in functionality. + +However, it did suprise most users of builder. Since the body text is +normally escaped, everybody expected the attribute values to be +escaped as well. Escaped attribute values were the number one support +request on the 1.x Builder series. + +Starting with Builder version 2.0.0, all attribute values expressed as +strings will be processed and the appropriate characters will be +escaped (e.g. "&" will be tranlated to "&"). Attribute values +that are expressed as Symbol values will not be processed for escaped +characters and will be unchanged in output. (Yes, this probably counts +as Symbol abuse, but the convention is convenient and flexible). + +Example: + + xml = Builder::XmlMarkup.new + xml.sample(:escaped=>"This&That", :unescaped=>:"Here&There") + xml.target! => + + +=== Version 1.0.0 Compatibility Changes + +Version 1.0.0 introduces some changes that are not backwards +compatible with earlier releases of builder. The main areas of +incompatibility are: + +* Keyword based arguments to +new+ (rather than positional based). It + was found that a developer would often like to specify indentation + without providing an explicit target, or specify a target without + indentation. Keyword based arguments handle this situation nicely. + +* Builder must now be an explicit target for markup tags. Instead of + writing + + xml_markup = Builder::XmlMarkup.new + xml_markup.div { strong("text") } + + you need to write + + xml_markup = Builder::XmlMarkup.new + xml_markup.div { xml_markup.strong("text") } + +* The builder object is passed as a parameter to all nested markup + blocks. This allows you to create a short alias for the builder + object that can be used within the block. For example, the previous + example can be written as: + + xml_markup = Builder::XmlMarkup.new + xml_markup.div { |xml| xml.strong("text") } + +* If you have both a pre-1.0 and a post-1.0 gem of builder installed, + you can choose which version to use through the RubyGems + +require_gem+ facility. + + require_gem 'builder', "~> 0.0" # Gets the old version + require_gem 'builder', "~> 1.0" # Gets the new version + +== Features + +* XML Comments are supported ... + + xml_markup.comment! "This is a comment" + #=> + +* XML processing instructions are supported ... + + xml_markup.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8" + #=> + + If the processing instruction is omitted, it defaults to "xml". + When the processing instruction is "xml", the defaults attributes + are: + + version:: 1.0 + encoding:: "UTF-8" + + (NOTE: if the encoding is set to "UTF-8" and $KCODE is set to + "UTF8", then Builder will emit UTF-8 encoded strings rather than + encoding non-ASCII characters as entities.) + +* XML entity declarations are now supported to a small degree. + + xml_markup.declare! :DOCTYPE, :chapter, :SYSTEM, "../dtds/chapter.dtd" + #=> + + The parameters to a declare! method must be either symbols or + strings. Symbols are inserted without quotes, and strings are + inserted with double quotes. Attribute-like arguments in hashes are + not allowed. + + If you need to have an argument to declare! be inserted without + quotes, but the arguement does not conform to the typical Ruby + syntax for symbols, then use the :"string" form to specify a symbol. + + For example: + + xml_markup.declare! :ELEMENT, :chapter, :"(title,para+)" + #=> + + Nested entity declarations are allowed. For example: + + @xml_markup.declare! :DOCTYPE, :chapter do |x| + x.declare! :ELEMENT, :chapter, :"(title,para+)" + x.declare! :ELEMENT, :title, :"(#PCDATA)" + x.declare! :ELEMENT, :para, :"(#PCDATA)" + end + + #=> + + + + + ]> + +* Some support for XML namespaces is now available. If the first + argument to a tag call is a symbol, it will be joined to the tag to + produce a namespace:tag combination. It is easier to show this than + describe it. + + xml.SOAP :Envelope do ... end + + Just put a space before the colon in a namespace to produce the + right form for builder (e.g. "SOAP:Envelope" => + "xml.SOAP :Envelope") + +* String attribute values are now escaped by default by + Builder (NOTE: this is _new_ behavior as of version 2.0). + + However, occasionally you need to use entities in attribute values. + Using a symbols (rather than a string) for an attribute value will + cause Builder to not run its quoting/escaping algorithm on that + particular value. + + (Note: The +escape_attrs+ option for builder is now + obsolete). + + Example: + + xml = Builder::XmlMarkup.new + xml.sample(:escaped=>"This&That", :unescaped=>:"Here&There") + xml.target! => + + +* UTF-8 Support + + Builder correctly translates UTF-8 characters into valid XML. (New + in version 2.0.0). Thanks to Sam Ruby for the translation code. + + You can get UTF-8 encoded output by making sure that the XML + encoding is set to "UTF-8" and that the $KCODE variable is set to + "UTF8". + + $KCODE = 'UTF8' + xml = Builder::Markup.new + xml.instruct!(:xml, :encoding => "UTF-8") + xml.sample("Iñtërnâtiônàl") + xml.target! => + "Iñtërnâtiônàl" + +== Links + +Documents :: http://builder.rubyforge.org/ +Github Clone :: git://github.com/jimweirich/builder.git +Issue / Bug Reports :: https://github.com/jimweirich/builder/issues?state=open + +== Contact + +Author:: Jim Weirich +Email:: jim.weirich@gmail.com +Home Page:: http://onestepback.org +License:: MIT Licence (http://www.opensource.org/licenses/mit-license.html) diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..5d77763 --- /dev/null +++ b/Rakefile @@ -0,0 +1,189 @@ +# Rakefile for rake -*- ruby -*- + +# Copyright 2004, 2005, 2006 by Jim Weirich (jim@weirichhouse.org). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. + +require 'rake/clean' +require 'rake/testtask' +require 'rdoc/task' +begin + require 'rubygems' + require 'rubygems/package_task' +rescue Exception + nil +end + +require './lib/builder/version' + +# Determine the current version of the software + +CLOBBER.include('pkg') +CLEAN.include('pkg/builder-*').include('pkg/blankslate-*').exclude('pkg/*.gem') + +PKG_VERSION = Builder::VERSION + +SRC_RB = FileList['lib/**/*.rb'] + +# The default task is run if rake is given no explicit arguments. + +desc "Default Task" +task :default => :test_all + +# Test Tasks --------------------------------------------------------- + +desc "Run all tests" +task :test_all => [:test_units] +task :ta => [:test_all] + +task :tu => [:test_units] + +Rake::TestTask.new("test_units") do |t| + t.test_files = FileList['test/test*.rb'] + t.libs << "." + t.verbose = false +end + +# Create a task to build the RDOC documentation tree. + +rd = RDoc::Task.new("rdoc") { |rdoc| + rdoc.rdoc_dir = 'html' + rdoc.title = "Builder for Markup" + rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README.rdoc' + rdoc.rdoc_files.include('lib/**/*.rb', '[A-Z]*', 'doc/**/*.rdoc').exclude("TAGS") + rdoc.template = 'doc/jamis.rb' +} + +# ==================================================================== +# Create a task that will package the Rake software into distributable +# gem files. + +PKG_FILES = FileList[ + 'lib/**/*.rb', + 'test/**/*.rb', + 'scripts/**/*.rb' +] +PKG_FILES.exclude('test/test_cssbuilder.rb') +PKG_FILES.exclude('lib/builder/css.rb') +PKG_FILES.exclude('TAGS') + +BLANKSLATE_FILES = FileList[ + 'lib/blankslate.rb', + 'test/test_blankslate.rb' +] + +if ! defined?(Gem) + puts "Package Target requires RubyGEMs" +else + spec = Gem::Specification.new do |s| + + #### Basic information. + + s.name = 'builder' + s.version = PKG_VERSION + s.summary = "Builders for MarkUp." + s.description = %{\ +Builder provides a number of builder objects that make creating structured data +simple to do. Currently the following builder objects are supported: + +* XML Markup +* XML Events +} + + s.files = PKG_FILES.to_a + s.require_path = 'lib' + + s.test_files = PKG_FILES.select { |fn| fn =~ /^test\/test/ } + + s.has_rdoc = true + s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a + s.rdoc_options << + '--title' << 'Builder -- Easy XML Building' << + '--main' << 'README.rdoc' << + '--line-numbers' + + s.author = "Jim Weirich" + s.email = "jim.weirich@gmail.com" + s.homepage = "http://onestepback.org" + s.license = 'MIT' + end + + blankslate_spec = Gem::Specification.new do |s| + + #### Basic information. + + s.name = 'blankslate' + s.version = PKG_VERSION + s.summary = "Blank Slate base class." + s.description = %{\ +BlankSlate provides a base class where almost all of the methods from Object and +Kernel have been removed. This is useful when providing proxy object and other +classes that make heavy use of method_missing. +} + + s.files = BLANKSLATE_FILES.to_a + s.require_path = 'lib' + + s.test_files = PKG_FILES.select { |fn| fn =~ /^test\/test/ } + + s.has_rdoc = true + s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a + s.rdoc_options << + '--title' << 'BlankSlate -- Base Class for building proxies.' << + '--main' << 'README.rdoc' << + '--line-numbers' + + s.author = "Jim Weirich" + s.email = "jim.weirich@gmail.com" + s.homepage = "http://onestepback.org" + s.license = 'MIT' + end + + namespace 'builder' do + Gem::PackageTask.new(spec) do |t| + t.need_tar = false + end + end + + namespace 'blankslate' do + Gem::PackageTask.new(blankslate_spec) do |t| + t.need_tar = false + end + end + + task :package => [:remove_tags, 'builder:package', 'blankslate:package'] +end + +task :remove_tags do + rm "TAGS" rescue nil +end + +# RCov --------------------------------------------------------------- +begin + require 'rcov/rcovtask' + + Rcov::RcovTask.new do |t| + t.libs << "test" + t.rcov_opts = [ + '-xRakefile', '--text-report' + ] + t.test_files = FileList[ + 'test/test*.rb' + ] + t.output_dir = 'coverage' + t.verbose = true + end +rescue LoadError + # No rcov available +end + +desc "Install the jamis RDoc template" +task :install_jamis_template do + require 'rbconfig' + dest_dir = File.join(Config::CONFIG['rubylibdir'], "rdoc/generators/template/html") + fail "Unabled to write to #{dest_dir}" unless File.writable?(dest_dir) + install "doc/jamis.rb", dest_dir, :verbose => true +end diff --git a/doc/releases/builder-1.2.4.rdoc b/doc/releases/builder-1.2.4.rdoc new file mode 100644 index 0000000..a1cf54f --- /dev/null +++ b/doc/releases/builder-1.2.4.rdoc @@ -0,0 +1,31 @@ += Builder 1.2.4 Released. + +Added a "CDATA" method to the XML Markup builder (from Josh Knowles). + +== What is Builder? + +Builder::XmlMarkup allows easy programmatic creation of XML markup. +For example: + + builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) + builder.person { |b| b.name("Jim"); b.phone("555-1234") } + puts builder.target! + +will generate: + + + Jim + 555-1234 + + +== Availability + +The easiest way to get and install builder is via RubyGems ... + + gem install builder (you may need root/admin privileges) + +== Thanks + +* Josh Knowles for the cdata! patch. + +-- Jim Weirich diff --git a/doc/releases/builder-2.0.0.rdoc b/doc/releases/builder-2.0.0.rdoc new file mode 100644 index 0000000..ed9e086 --- /dev/null +++ b/doc/releases/builder-2.0.0.rdoc @@ -0,0 +1,46 @@ += Builder 2.0.0 Released. + +== Changes in 2.0.0 + +* UTF-8 characters in data are now correctly translated to their XML + equivalents. (Thanks to Sam Ruby) + +* Attribute values are now escaped by default. See the README + file for details. + +NOTE: The escaping attribute values by default is different +than in previous releases of Builder. This makes version 2.0.0 +somewhat incompatible with the 1.x series of Builder. If you use "&", +"<", or ">" in attributes values, you may have to change your +code. (Essentially you remove the manual escaping. The new way is +easier, believe me). + +== What is Builder? + +Builder::XmlMarkup is a library that allows easy programmatic creation +of XML markup. For example: + + builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) + builder.person { |b| b.name("Jim"); b.phone("555-1234") } + +will generate: + + + Jim + 555-1234 + + +== Availability + +The easiest way to get and install builder is via RubyGems ... + + gem install builder (you may need root/admin privileges) + +== Thanks + +* Sam Ruby for the XChar module and the related UTF-8 translation + tools. +* Also to Sam Ruby for gently persuading me to start quoting attribute + values. + +-- Jim Weirich diff --git a/doc/releases/builder-2.1.1.rdoc b/doc/releases/builder-2.1.1.rdoc new file mode 100755 index 0000000..dbbf121 --- /dev/null +++ b/doc/releases/builder-2.1.1.rdoc @@ -0,0 +1,58 @@ += Builder 2.1.1 Released. + +Release 2.1.1 of Builder is mainly a bug fix release. + +== Changes in 2.1.1 + +* Added reveal capability to BlankSlate. + +* Fixed a bug in BlankSlate where including a module into Object could + cause methods to leak into BlankSlate. + +* Fixed typo in XmlMarkup class docs (from Martin Fowler). + +* Fixed test on private methods to differentiate between targetted and + untargetted private methods. + +* Removed legacy capture of @self in XmlBase (@self was used back when + we used instance eval). + +* Added additional tests for global functions (both direct and + included). + +* Several misc internal cleanups, including rearranging the source + code tree. + +NOTE: The escaping attribute values by default is different +than in previous releases of Builder. This makes version 2.0.x +somewhat incompatible with the 1.x series of Builder. If you use "&", +"<", or ">" in attributes values, you may have to change your +code. (Essentially you remove the manual escaping. The new way is +easier, believe me). + +== What is Builder? + +Builder::XmlMarkup is a library that allows easy programmatic creation +of XML markup. For example: + + builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) + builder.person { |b| b.name("Jim"); b.phone("555-1234") } + +will generate: + + + Jim + 555-1234 + + +== Availability + +The easiest way to get and install builder is via RubyGems ... + + gem install builder (you may need root/admin privileges) + +== Thanks + +* Martin Fowler for spotting some typos in the documentation. + +-- Jim Weirich diff --git a/lib/blankslate.rb b/lib/blankslate.rb index b6e9bf7..e947376 100644 --- a/lib/blankslate.rb +++ b/lib/blankslate.rb @@ -8,6 +8,30 @@ # above copyright notice is included. #++ +class String + if instance_methods.first.is_a?(Symbol) + def _blankslate_as_name + to_sym + end + else + def _blankslate_as_name + self + end + end +end + +class Symbol + if instance_methods.first.is_a?(Symbol) + def _blankslate_as_name + self + end + else + def _blankslate_as_name + to_s + end + end +end + ###################################################################### # BlankSlate provides an abstract base class with no predefined # methods (except for \_\_send__ and \_\_id__). @@ -16,13 +40,12 @@ # class BlankSlate class << self - + # Hide the method named +name+ in the BlankSlate class. Don't # hide +instance_eval+ or any method beginning with "__". def hide(name) - methods = instance_methods.map(&:to_sym) - if methods.include?(name.to_sym) and - name !~ /^(__|instance_eval)/ + if instance_methods.include?(name._blankslate_as_name) and + name !~ /^(__|instance_eval$)/ @hidden_methods ||= {} @hidden_methods[name.to_sym] = instance_method(name) undef_method name @@ -42,7 +65,7 @@ def reveal(name) define_method(name, hidden_method) end end - + instance_methods.each { |m| hide(m) } end @@ -107,4 +130,4 @@ def append_features(mod) end result end -end \ No newline at end of file +end diff --git a/spec/blankslate_spec.rb b/spec/blankslate_spec.rb deleted file mode 100644 index 9526445..0000000 --- a/spec/blankslate_spec.rb +++ /dev/null @@ -1,38 +0,0 @@ -require 'spec_helper' - -describe BlankSlate do - let(:blank_slate) { BlankSlate.new } - - def call(obj, meth, *args) - BlankSlate.find_hidden_method(meth).bind(obj).call(*args) - end - - describe "cleanliness" do - it "should not have many methods" do - BlankSlate.instance_methods. - map(&:to_s).sort. - should == ["__id__", "__send__", "instance_eval"] - end - end - - context "when methods are added to Object" do - after(:each) { - class Object - undef :foo - end - } - - it "should still be blank" do - class Object - def foo - end - end - Object.new.foo - - lambda { - BlankSlate.new.foo - }.should raise_error(NoMethodError) - end - - end -end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index f2b029d..0000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ - -require 'blankslate' \ No newline at end of file diff --git a/test/test_blankslate.rb b/test/test_blankslate.rb new file mode 100644 index 0000000..ea38ced --- /dev/null +++ b/test/test_blankslate.rb @@ -0,0 +1,217 @@ +#!/usr/bin/env ruby + +#-- +# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +require 'test/unit' +require 'test/preload' +require 'blankslate' +require 'stringio' + +# Methods to be introduced into the Object class late. +module LateObject + def late_object + 33 + end + def LateObject.included(mod) + # Modules defining an included method should not prevent blank + # slate erasure! + end +end + +# Methods to be introduced into the Kernel module late. +module LateKernel + def late_kernel + 44 + end + def LateKernel.included(mod) + # Modules defining an included method should not prevent blank + # slate erasure! + end +end + +# Introduce some late methods (both module and direct) into the Kernel +# module. +module Kernel + include LateKernel + + def late_addition + 1234 + end + + def double_late_addition + 11 + end + + def double_late_addition + 22 + end +end + + +# Introduce some late methods (both module and direct) into the Object +# class. +class Object + include LateObject + def another_late_addition + 4321 + end +end + +# Introduce some late methods by inclusion. +module GlobalModule + def global_inclusion + 42 + end +end +include GlobalModule + +def direct_global + 43 +end + +###################################################################### +# Test case for blank slate. +# +class TestBlankSlate < Test::Unit::TestCase + def setup + @bs = BlankSlate.new + end + + def test_undefined_methods_remain_undefined + assert_raise(NoMethodError) { @bs.no_such_method } + assert_raise(NoMethodError) { @bs.nil? } + end + + + # NOTE: NameError is acceptable because the lack of a '.' means that + # Ruby can't tell if it is a method or a local variable. + def test_undefined_methods_remain_undefined_during_instance_eval + assert_raise(NoMethodError, NameError) do + @bs.instance_eval do nil? end + end + assert_raise(NoMethodError, NameError) do + @bs.instance_eval do no_such_method end + end + end + + def test_private_methods_are_undefined + assert_raise(NoMethodError) do + @bs.puts "HI" + end + end + + def test_targetted_private_methods_are_undefined_during_instance_eval + assert_raise(NoMethodError, NameError) do + @bs.instance_eval do self.puts "HI" end + end + end + + def test_untargetted_private_methods_are_defined_during_instance_eval + oldstdout = $stdout + $stdout = StringIO.new + @bs.instance_eval do + puts "HI" + end + ensure + $stdout = oldstdout + end + + def test_methods_added_late_to_kernel_remain_undefined + assert_equal 1234, nil.late_addition + assert_raise(NoMethodError) { @bs.late_addition } + end + + def test_methods_added_late_to_object_remain_undefined + assert_equal 4321, nil.another_late_addition + assert_raise(NoMethodError) { @bs.another_late_addition } + end + + def test_methods_added_late_to_global_remain_undefined + assert_equal 42, global_inclusion + assert_raise(NoMethodError) { @bs.global_inclusion } + end + + def test_preload_method_added + assert Kernel.k_added_names.include?(:late_addition) + assert Object.o_added_names.include?(:another_late_addition) + end + + def test_method_defined_late_multiple_times_remain_undefined + assert_equal 22, nil.double_late_addition + assert_raise(NoMethodError) { @bs.double_late_addition } + end + + def test_late_included_module_in_object_is_ok + assert_equal 33, 1.late_object + assert_raise(NoMethodError) { @bs.late_object } + end + + def test_late_included_module_in_kernel_is_ok + assert_raise(NoMethodError) { @bs.late_kernel } + end + + def test_revealing_previously_hidden_methods_are_callable + with_to_s = Class.new(BlankSlate) do + reveal :to_s + end + assert_match(/^#<.*>$/, with_to_s.new.to_s) + end + + def test_revealing_previously_hidden_methods_are_callable_with_block + Object.class_eval <<-EOS + def given_block(&block) + block + end + EOS + + with_given_block = Class.new(BlankSlate) do + reveal :given_block + end + assert_not_nil with_given_block.new.given_block {} + end + + def test_revealing_a_hidden_method_twice_is_ok + with_to_s = Class.new(BlankSlate) do + reveal :to_s + reveal :to_s + end + assert_match(/^#<.*>$/, with_to_s.new.to_s) + end + + def test_revealing_unknown_hidden_method_is_an_error + assert_raises(RuntimeError) do + Class.new(BlankSlate) do + reveal :xyz + end + end + end + + def test_global_includes_still_work + assert_nothing_raised do + assert_equal 42, global_inclusion + assert_equal 42, Object.new.global_inclusion + assert_equal 42, "magic number".global_inclusion + assert_equal 43, direct_global + end + end + + def test_reveal_should_not_bind_to_an_instance + with_object_id = Class.new(BlankSlate) do + reveal(:object_id) + end + + obj1 = with_object_id.new + obj2 = with_object_id.new + + assert obj1.object_id != obj2.object_id, + "Revealed methods should not be bound to a particular instance" + end +end diff --git a/test/test_eventbuilder.rb b/test/test_eventbuilder.rb new file mode 100644 index 0000000..f434470 --- /dev/null +++ b/test/test_eventbuilder.rb @@ -0,0 +1,150 @@ +#!/usr/bin/env ruby + +#-- +# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +require 'test/unit' +require 'test/preload' +require 'builder' +require 'builder/xmlevents' + +class TestEvents < Test::Unit::TestCase + + class Target + attr_reader :events + + def initialize + @events = [] + end + + def start_tag(tag, attrs) + @events << [:start_tag, tag, attrs] + end + + def end_tag(tag) + @events << [:end_tag, tag] + end + + def text(string) + @events << [:text, string] + end + + end + + + def setup + @target = Target.new + @xml = Builder::XmlEvents.new(:target=>@target) + end + + def test_simple + @xml.one + expect [:start_tag, :one, nil] + expect [:end_tag, :one] + expect_done + end + + def test_nested + @xml.one { @xml.two } + expect [:start_tag, :one, nil] + expect [:start_tag, :two, nil] + expect [:end_tag, :two] + expect [:end_tag, :one] + expect_done + end + + def test_text + @xml.one("a") + expect [:start_tag, :one, nil] + expect [:text, "a"] + expect [:end_tag, :one] + expect_done + end + + def test_special_text + @xml.one("H&R") + expect [:start_tag, :one, nil] + expect [:text, "H&R"] + expect [:end_tag, :one] + expect_done + end + + def test_text_with_entity + @xml.one("H&R") + expect [:start_tag, :one, nil] + expect [:text, "H&R"] + expect [:end_tag, :one] + expect_done + end + + def test_attributes + @xml.a(:b=>"c", :x=>"y") + expect [:start_tag, :a, {:x => "y", :b => "c"}] + expect [:end_tag, :a] + expect_done + end + + def test_moderately_complex + @xml.tag! "address-book" do |x| + x.entry :id=>"1" do + x.name { + x.first "Bill" + x.last "Smith" + } + x.address "Cincinnati" + end + x.entry :id=>"2" do + x.name { + x.first "John" + x.last "Doe" + } + x.address "Columbus" + end + end + expect [:start_tag, "address-book".intern, nil] + expect [:start_tag, :entry, {:id => "1"}] + expect [:start_tag, :name, nil] + expect [:start_tag, :first, nil] + expect [:text, "Bill"] + expect [:end_tag, :first] + expect [:start_tag, :last, nil] + expect [:text, "Smith"] + expect [:end_tag, :last] + expect [:end_tag, :name] + expect [:start_tag, :address, nil] + expect [:text, "Cincinnati"] + expect [:end_tag, :address] + expect [:end_tag, :entry] + expect [:start_tag, :entry, {:id => "2"}] + expect [:start_tag, :name, nil] + expect [:start_tag, :first, nil] + expect [:text, "John"] + expect [:end_tag, :first] + expect [:start_tag, :last, nil] + expect [:text, "Doe"] + expect [:end_tag, :last] + expect [:end_tag, :name] + expect [:start_tag, :address, nil] + expect [:text, "Columbus"] + expect [:end_tag, :address] + expect [:end_tag, :entry] + expect [:end_tag, "address-book".intern] + expect_done + end + + def expect(value) + assert_equal value, @target.events.shift + end + + def expect_done + assert_nil @target.events.shift + end + +end diff --git a/test/test_markupbuilder.rb b/test/test_markupbuilder.rb new file mode 100644 index 0000000..b9cee65 --- /dev/null +++ b/test/test_markupbuilder.rb @@ -0,0 +1,573 @@ +#!/usr/bin/env ruby + +#-- +# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +require 'test/unit' +require 'test/preload' +require 'builder' +require 'builder/xmlmarkup' + +class TestMarkup < Test::Unit::TestCase + def setup + @xml = Builder::XmlMarkup.new + end + + def test_create + assert_not_nil @xml + end + + def test_simple + @xml.simple + assert_equal "", @xml.target! + end + + def test_value + @xml.value("hi") + assert_equal "hi", @xml.target! + end + + def test_empty_value + @xml.value("") + assert_equal "", @xml.target! + end + + def test_nil_value + @xml.value(nil) + assert_equal "", @xml.target! + end + + def test_nested + @xml.outer { |x| x.inner("x") } + assert_equal "x", @xml.target! + end + + def test_attributes + @xml.ref(:id => 12) + assert_equal %{}, @xml.target! + end + + def test_string_attributes_are_quoted_by_default + @xml.ref(:id => "H&R") + assert_equal %{}, @xml.target! + end + + def test_symbol_attributes_are_unquoted_by_default + @xml.ref(:id => :"H&R") + assert_equal %{}, @xml.target! + end + + def test_attributes_quoted_can_be_turned_on + @xml = Builder::XmlMarkup.new + @xml.ref(:id => "") + assert_equal %{}, @xml.target! + end + + def test_mixed_attribute_quoting_with_nested_builders + x = Builder::XmlMarkup.new(:target=>@xml) + @xml.ref(:id=>:"H&R") { + x.element(:tag=>"Long&Short") + } + assert_equal "", + @xml.target! + end + + def test_multiple_attributes + @xml.ref(:id => 12, :name => "bill") + assert_match %r{^$}, @xml.target! + end + + def test_attributes_with_text + @xml.a("link", :href=>"http://onestepback.org") + assert_equal %{link}, @xml.target! + end + + def test_attributes_with_newlines + @xml.abbr("W3C", :title=>"World\nWide\rWeb\r\nConsortium") + assert_equal %{W3C}, + @xml.target! + end + + def test_complex + @xml.body(:bg=>"#ffffff") { |x| + x.title("T", :style=>"red") + } + assert_equal %{T}, @xml.target! + end + + def test_funky_symbol + @xml.tag!("non-ruby-token", :id=>1) { |x| x.ok } + assert_equal %{}, @xml.target! + end + + def test_tag_can_handle_private_method + @xml.tag!("loop", :id=>1) { |x| x.ok } + assert_equal %{}, @xml.target! + end + + def test_no_explicit_marker + @xml.p { |x| x.b("HI") } + assert_equal "

HI

", @xml.target! + end + + def test_reference_local_vars + n = 3 + @xml.ol { |x| n.times { x.li(n) } } + assert_equal "
  1. 3
  2. 3
  3. 3
", @xml.target! + end + + def test_reference_methods + @xml.title { |x| x.a { x.b(name) } } + assert_equal "<a><b>bob</b></a>", @xml.target! + end + + def test_append_text + @xml.p { |x| x.br; x.text! "HI" } + assert_equal "


HI

", @xml.target! + end + + def test_ambiguous_markup + ex = assert_raise(ArgumentError) { + @xml.h1("data1") { b } + } + assert_match(/\btext\b/, ex.message) + assert_match(/\bblock\b/, ex.message) + end + + def test_capitalized_method + @xml.P { |x| x.B("hi"); x.BR(); x.EM { x.text! "world" } } + assert_equal "

hi
world

", @xml.target! + end + + def test_escaping + @xml.div { |x| x.text! ""; x.em("H&R Block") } + assert_equal %{
<hi>H&R Block
}, @xml.target! + end + + def test_non_escaping + @xml.div("ns:xml"=>:"&xml;") { |x| x << ""; x.em("H&R Block") } + assert_equal %{
H&R Block
}, @xml.target! + end + + def test_return_value + str = @xml.x("men") + assert_equal @xml.target!, str + end + + def test_stacked_builders + b = Builder::XmlMarkup.new( :target => @xml ) + b.div { @xml.span { @xml.a("text", :href=>"ref") } } + assert_equal "", @xml.target! + end + + def name + "bob" + end +end + +class TestAttributeEscaping < Test::Unit::TestCase + + def setup + @xml = Builder::XmlMarkup.new + end + + def test_element_gt + @xml.title('1<2') + assert_equal '1<2', @xml.target! + end + + def test_element_amp + @xml.title('AT&T') + assert_equal 'AT&T', @xml.target! + end + + def test_element_amp2 + @xml.title('&') + assert_equal '&amp;', @xml.target! + end + + def test_attr_less + @xml.a(:title => '2>1') + assert_equal '', @xml.target! + end + + def test_attr_amp + @xml.a(:title => 'AT&T') + assert_equal '', @xml.target! + end + + def test_attr_quot + @xml.a(:title => '"x"') + assert_equal '', @xml.target! + end + +end + +class TestNameSpaces < Test::Unit::TestCase + def setup + @xml = Builder::XmlMarkup.new(:indent=>2) + end + + def test_simple_name_spaces + @xml.rdf :RDF + assert_equal "\n", @xml.target! + end + + def test_long + xml = Builder::XmlMarkup.new(:indent=>2) + xml.instruct! + xml.rdf :RDF, + "xmlns:rdf" => :"&rdf;", + "xmlns:rdfs" => :"&rdfs;", + "xmlns:xsd" => :"&xsd;", + "xmlns:owl" => :"&owl;" do + xml.owl :Class, :'rdf:ID'=>'Bird' do + xml.rdfs :label, 'bird' + xml.rdfs :subClassOf do + xml.owl :Restriction do + xml.owl :onProperty, 'rdf:resource'=>'#wingspan' + xml.owl :maxCardinality,1,'rdf:datatype'=>'&xsd;nonNegativeInteger' + end + end + end + end + assert_match(/^<\?xml/, xml.target!) + assert_match(/\n/m, xml.target!) + end + + def test_ensure + xml = Builder::XmlMarkup.new + xml.html do + xml.body do + begin + xml.p do + raise Exception.new('boom') + end + rescue Exception => e + xml.pre e + end + end + end + assert_match %r{

}, xml.target! + assert_match %r{

}, xml.target! + end +end + +class TestDeclarations < Test::Unit::TestCase + def setup + @xml = Builder::XmlMarkup.new(:indent=>2) + end + + def test_declare + @xml.declare! :element + assert_equal "\n", @xml.target! + end + + def test_bare_arg + @xml.declare! :element, :arg + assert_equal"\n", @xml.target! + end + + def test_string_arg + @xml.declare! :element, "string" + assert_equal"\n", @xml.target! + end + + def test_mixed_args + @xml.declare! :element, :x, "y", :z, "-//OASIS//DTD DocBook XML//EN" + assert_equal "\n", @xml.target! + end + + def test_nested_declarations + @xml = Builder::XmlMarkup.new + @xml.declare! :DOCTYPE, :chapter do |x| + x.declare! :ELEMENT, :chapter, "(title,para+)".intern + end + assert_equal "]>", @xml.target! + end + + def test_nested_indented_declarations + @xml.declare! :DOCTYPE, :chapter do |x| + x.declare! :ELEMENT, :chapter, "(title,para+)".intern + end + assert_equal "\n]>\n", @xml.target! + end + + def test_complex_declaration + @xml.declare! :DOCTYPE, :chapter do |x| + x.declare! :ELEMENT, :chapter, "(title,para+)".intern + x.declare! :ELEMENT, :title, "(#PCDATA)".intern + x.declare! :ELEMENT, :para, "(#PCDATA)".intern + end + expected = %{ + + +]> +} + assert_equal expected, @xml.target! + end +end + + +class TestSpecialMarkup < Test::Unit::TestCase + def setup + @xml = Builder::XmlMarkup.new(:indent=>2) + end + + def test_comment + @xml.comment!("COMMENT") + assert_equal "\n", @xml.target! + end + + def test_indented_comment + @xml.p { @xml.comment! "OK" } + assert_equal "

\n \n

\n", @xml.target! + end + + def test_instruct + @xml.instruct! :abc, :version=>"0.9" + assert_equal "\n", @xml.target! + end + + def test_indented_instruct + @xml.p { @xml.instruct! :xml } + assert_match %r{

\n <\?xml version="1.0" encoding="UTF-8"\?>\n

\n}, + @xml.target! + end + + def test_instruct_without_attributes + @xml.instruct! :zz + assert_equal "\n", @xml.target! + end + + def test_xml_instruct + @xml.instruct! + assert_match(/^<\?xml version="1.0" encoding="UTF-8"\?>$/, @xml.target!) + end + + def test_xml_instruct_with_overrides + @xml.instruct! :xml, :encoding=>"UCS-2" + assert_match(/^<\?xml version="1.0" encoding="UCS-2"\?>$/, @xml.target!) + end + + def test_xml_instruct_with_standalong + @xml.instruct! :xml, :encoding=>"UCS-2", :standalone=>"yes" + assert_match(/^<\?xml version="1.0" encoding="UCS-2" standalone="yes"\?>$/, @xml.target!) + end + + def test_no_blocks + assert_raise(Builder::IllegalBlockError) do + @xml.instruct! { |x| x.hi } + end + assert_raise(Builder::IllegalBlockError) do + @xml.comment!(:element) { |x| x.hi } + end + end + + def test_cdata + @xml.cdata!("TEST") + assert_equal "\n", @xml.target! + end + + def test_cdata_with_ampersand + @xml.cdata!("TEST&CHECK") + assert_equal "\n", @xml.target! + end + + def test_cdata_with_included_close + @xml.cdata!("TEST]]>CHECK") + assert_equal "CHECK]]>\n", @xml.target! + end +end + +class TestIndentedXmlMarkup < Test::Unit::TestCase + def setup + @xml = Builder::XmlMarkup.new(:indent=>2) + end + + def test_one_level + @xml.ol { |x| x.li "text" } + assert_equal "
    \n
  1. text
  2. \n
\n", @xml.target! + end + + def test_two_levels + @xml.p { |x| + x.ol { x.li "text" } + x.br + } + assert_equal "

\n

    \n
  1. text
  2. \n
\n
\n

\n", @xml.target! + end + + def test_initial_level + @xml = Builder::XmlMarkup.new(:indent=>2, :margin=>4) + @xml.name { |x| x.first("Jim") } + assert_equal " \n Jim\n \n", @xml.target! + end + + class TestUtfMarkup < Test::Unit::TestCase + if ! String.method_defined?(:encode) + def setup + @old_kcode = $KCODE + end + + def teardown + $KCODE = @old_kcode + end + + def test_use_entities_if_no_encoding_is_given_and_kcode_is_none + $KCODE = 'NONE' + xml = Builder::XmlMarkup.new + xml.p("\xE2\x80\x99") + assert_match(%r(

), xml.target!) # + end + + def test_use_entities_if_encoding_is_utf_but_kcode_is_not + $KCODE = 'NONE' + xml = Builder::XmlMarkup.new + xml.instruct!(:xml, :encoding => 'UTF-8') + xml.p("\xE2\x80\x99") + assert_match(%r(

), xml.target!) # + end + else + # change in behavior. As there is no $KCODE anymore, the default + # moves from "does not understand utf-8" to "supports utf-8". + + def test_use_entities_if_no_encoding_is_given_and_kcode_is_none + xml = Builder::XmlMarkup.new + xml.p("\xE2\x80\x99") + assert_match("

\u2019

", xml.target!) # + end + + def test_use_entities_if_encoding_is_utf_but_kcode_is_not + xml = Builder::XmlMarkup.new + xml.instruct!(:xml, :encoding => 'UTF-8') + xml.p("\xE2\x80\x99") + assert_match("

\u2019

", xml.target!) # + end + end + + def encode string, encoding + if !String.method_defined?(:encode) + $KCODE = encoding + string + elsif encoding == 'UTF8' + string.force_encoding('UTF-8') + else + string + end + end + + def test_use_entities_if_kcode_is_utf_but_encoding_is_dummy_encoding + xml = Builder::XmlMarkup.new + xml.instruct!(:xml, :encoding => 'UTF-16') + xml.p(encode("\xE2\x80\x99", 'UTF8')) + assert_match(%r(

), xml.target!) # + end + + def test_use_entities_if_kcode_is_utf_but_encoding_is_unsupported_encoding + xml = Builder::XmlMarkup.new + xml.instruct!(:xml, :encoding => 'UCS-2') + xml.p(encode("\xE2\x80\x99", 'UTF8')) + assert_match(%r(

), xml.target!) # + end + + def test_use_utf8_if_encoding_defaults_and_kcode_is_utf8 + xml = Builder::XmlMarkup.new + xml.p(encode("\xE2\x80\x99",'UTF8')) + assert_equal encode("

\xE2\x80\x99

",'UTF8'), xml.target! + end + + def test_use_utf8_if_both_encoding_and_kcode_are_utf8 + xml = Builder::XmlMarkup.new + xml.instruct!(:xml, :encoding => 'UTF-8') + xml.p(encode("\xE2\x80\x99",'UTF8')) + assert_match encode("

\xE2\x80\x99

",'UTF8'), xml.target! + end + + def test_use_utf8_if_both_encoding_and_kcode_are_utf8_with_lowercase + xml = Builder::XmlMarkup.new + xml.instruct!(:xml, :encoding => 'utf-8') + xml.p(encode("\xE2\x80\x99",'UTF8')) + assert_match encode("

\xE2\x80\x99

",'UTF8'), xml.target! + end + end + + class TestXmlEvents < Test::Unit::TestCase + def setup + @handler = EventHandler.new + @xe = Builder::XmlEvents.new(:target=>@handler) + end + + def test_simple + @xe.p + assert_equal [:start, :p, nil], @handler.events.shift + assert_equal [:end, :p], @handler.events.shift + end + + def test_text + @xe.p("HI") + assert_equal [:start, :p, nil], @handler.events.shift + assert_equal [:text, "HI"], @handler.events.shift + assert_equal [:end, :p], @handler.events.shift + end + + def test_attributes + @xe.p("id"=>"2") + ev = @handler.events.shift + assert_equal [:start, :p], ev[0,2] + assert_equal "2", ev[2]['id'] + assert_equal [:end, :p], @handler.events.shift + end + + def test_indented + @xml = Builder::XmlEvents.new(:indent=>2, :target=>@handler) + @xml.p { |x| x.b("HI") } + assert_equal [:start, :p, nil], @handler.events.shift + assert_equal "\n ", pop_text + assert_equal [:start, :b, nil], @handler.events.shift + assert_equal "HI", pop_text + assert_equal [:end, :b], @handler.events.shift + assert_equal "\n", pop_text + assert_equal [:end, :p], @handler.events.shift + end + + def pop_text + result = '' + while ! @handler.events.empty? && @handler.events[0][0] == :text + result << @handler.events[0][1] + @handler.events.shift + end + result + end + + class EventHandler + attr_reader :events + def initialize + @events = [] + end + + def start_tag(sym, attrs) + @events << [:start, sym, attrs] + end + + def end_tag(sym) + @events << [:end, sym] + end + + def text(txt) + @events << [:text, txt] + end + end + end + +end diff --git a/test/test_method_caching.rb b/test/test_method_caching.rb new file mode 100644 index 0000000..94da212 --- /dev/null +++ b/test/test_method_caching.rb @@ -0,0 +1,62 @@ +#!/usr/bin/env ruby + +#-- +# Portions copyright 2011 by Bart ten Brinke (info@retrosync.com). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +require 'test/unit' +require 'test/preload' +require 'builder' + +class TestMethodCaching < Test::Unit::TestCase + + # We can directly ask if xml object responds to the cache_me or + # do_not_cache_me methods because xml is derived from BasicObject + # (and repond_to? is not defined in BasicObject). + # + # Instead we are going to stub out method_missing so that it throws + # an error, and then make sure that error is either thrown or not + # thrown as appropriate. + + def teardown + super + Builder::XmlBase.cache_method_calls = true + end + + def test_caching_does_not_break_weird_symbols + xml = Builder::XmlMarkup.new + xml.__send__("work-order", 1) + assert_equal "1", xml.target! + end + + def test_method_call_caching + xml = Builder::XmlMarkup.new + xml.cache_me + + def xml.method_missing(*args) + ::Kernel.fail StandardError, "SHOULD NOT BE CALLED" + end + assert_nothing_raised do + xml.cache_me + end + end + + def test_method_call_caching_disabled + Builder::XmlBase.cache_method_calls = false + xml = Builder::XmlMarkup.new + xml.do_not_cache_me + + def xml.method_missing(*args) + ::Kernel.fail StandardError, "SHOULD BE CALLED" + end + assert_raise(StandardError, /SHOULD BE CALLED/) do + xml.do_not_cache_me + end + end + +end diff --git a/test/test_namecollision.rb b/test/test_namecollision.rb new file mode 100644 index 0000000..5b16b30 --- /dev/null +++ b/test/test_namecollision.rb @@ -0,0 +1,39 @@ +#!/usr/bin/env ruby + +#-- +# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +require 'test/unit' +require 'builder/xchar' + +class TestNameCollisions < Test::Unit::TestCase + module Collide + def xchr + end + end + + def test_no_collision + assert_nothing_raised do + Builder.check_for_name_collision(Collide, :not_defined) + end + end + + def test_collision + assert_raise RuntimeError do + Builder.check_for_name_collision(Collide, "xchr") + end + end + + def test_collision_with_symbol + assert_raise RuntimeError do + Builder.check_for_name_collision(Collide, :xchr) + end + end +end diff --git a/test/test_xchar.rb b/test/test_xchar.rb new file mode 100644 index 0000000..fd67114 --- /dev/null +++ b/test/test_xchar.rb @@ -0,0 +1,77 @@ +#!/usr/bin/env ruby + +#-- +# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +#!/usr/bin/env ruby + +require 'test/unit' +require 'builder/xchar' + +if String.method_defined?(:encode) + class String + ENCODING_BINARY = Encoding.find('BINARY') + + # shim method for testing purposes + def to_xs(escape=true) + raise NameError.new('to_xs') unless caller[0].index(__FILE__) + + result = Builder::XChar.encode(self) + if escape + result.gsub(/[^\u0000-\u007F]/) {|c| "&##{c.ord};"} + else + # really only useful for testing purposes + result.force_encoding(ENCODING_BINARY) + end + end + end +end + +class TestXmlEscaping < Test::Unit::TestCase + REPLACEMENT_CHAR = Builder::XChar::REPLACEMENT_CHAR.to_xs + + def test_ascii + assert_equal 'abc', 'abc'.to_xs + end + + def test_predefined + assert_equal '&', '&'.to_xs # ampersand + assert_equal '<', '<'.to_xs # left angle bracket + assert_equal '>', '>'.to_xs # right angle bracket + end + + def test_invalid + assert_equal REPLACEMENT_CHAR, "\x00".to_xs # null + assert_equal REPLACEMENT_CHAR, "\x0C".to_xs # form feed + assert_equal REPLACEMENT_CHAR, "\xEF\xBF\xBF".to_xs # U+FFFF + end + + def test_iso_8859_1 + assert_equal 'ç', "\xE7".to_xs # small c cedilla + assert_equal '©', "\xA9".to_xs # copyright symbol + end + + def test_win_1252 + assert_equal '’', "\x92".to_xs # smart quote + assert_equal '€', "\x80".to_xs # euro + end + + def test_utf8 + assert_equal '’', "\xE2\x80\x99".to_xs # right single quote + assert_equal '©', "\xC2\xA9".to_xs # copy + end + + def test_utf8_verbatim + assert_equal "\xE2\x80\x99", "\xE2\x80\x99".to_xs(false) # right single quote + assert_equal "\xC2\xA9", "\xC2\xA9".to_xs(false) # copy + assert_equal "\xC2\xA9&\xC2\xA9", + "\xC2\xA9&\xC2\xA9".to_xs(false) # copy with ampersand + end +end From aff0b68a4ccc18c05b439d2e711218b455225cb5 Mon Sep 17 00:00:00 2001 From: Viliam Pucik Date: Sat, 22 Dec 2012 22:32:36 +0100 Subject: [PATCH 2/5] removed leftover files originating from builder gem --- README.rdoc | 225 ------------- doc/releases/builder-1.2.4.rdoc | 31 -- doc/releases/builder-2.0.0.rdoc | 46 --- doc/releases/builder-2.1.1.rdoc | 58 ---- test/test_eventbuilder.rb | 150 --------- test/test_markupbuilder.rb | 573 -------------------------------- test/test_method_caching.rb | 62 ---- test/test_namecollision.rb | 39 --- test/test_xchar.rb | 77 ----- 9 files changed, 1261 deletions(-) delete mode 100644 README.rdoc delete mode 100644 doc/releases/builder-1.2.4.rdoc delete mode 100644 doc/releases/builder-2.0.0.rdoc delete mode 100755 doc/releases/builder-2.1.1.rdoc delete mode 100644 test/test_eventbuilder.rb delete mode 100644 test/test_markupbuilder.rb delete mode 100644 test/test_method_caching.rb delete mode 100644 test/test_namecollision.rb delete mode 100644 test/test_xchar.rb diff --git a/README.rdoc b/README.rdoc deleted file mode 100644 index 1e340bc..0000000 --- a/README.rdoc +++ /dev/null @@ -1,225 +0,0 @@ -# coding: UTF-8 -= Project: Builder - -== Goal - -Provide a simple way to create XML markup and data structures. - -== Classes - -Builder::XmlMarkup:: Generate XML markup notiation -Builder::XmlEvents:: Generate XML events (i.e. SAX-like) - -Notes:: - -* An Builder::XmlTree class to generate XML tree - (i.e. DOM-like) structures is also planned, but not yet implemented. - Also, the events builder is currently lagging the markup builder in - features. - -== Usage - - require 'rubygems' - require_gem 'builder', '~> 2.0' - - builder = Builder::XmlMarkup.new - xml = builder.person { |b| b.name("Jim"); b.phone("555-1234") } - xml #=> Jim555-1234 - -or - - require 'rubygems' - require_gem 'builder' - - builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) - builder.person { |b| b.name("Jim"); b.phone("555-1234") } - # - # Prints: - # - # Jim - # 555-1234 - # - -== Compatibility - -=== Version 2.0.0 Compatibility Changes - -Version 2.0.0 introduces automatically escaped attribute values for -the first time. Versions prior to 2.0.0 did not insert escape -characters into attribute values in the XML markup. This allowed -attribute values to explicitly reference entities, which was -occasionally used by a small number of developers. Since strings -could always be explicitly escaped by hand, this was not a major -restriction in functionality. - -However, it did suprise most users of builder. Since the body text is -normally escaped, everybody expected the attribute values to be -escaped as well. Escaped attribute values were the number one support -request on the 1.x Builder series. - -Starting with Builder version 2.0.0, all attribute values expressed as -strings will be processed and the appropriate characters will be -escaped (e.g. "&" will be tranlated to "&"). Attribute values -that are expressed as Symbol values will not be processed for escaped -characters and will be unchanged in output. (Yes, this probably counts -as Symbol abuse, but the convention is convenient and flexible). - -Example: - - xml = Builder::XmlMarkup.new - xml.sample(:escaped=>"This&That", :unescaped=>:"Here&There") - xml.target! => - - -=== Version 1.0.0 Compatibility Changes - -Version 1.0.0 introduces some changes that are not backwards -compatible with earlier releases of builder. The main areas of -incompatibility are: - -* Keyword based arguments to +new+ (rather than positional based). It - was found that a developer would often like to specify indentation - without providing an explicit target, or specify a target without - indentation. Keyword based arguments handle this situation nicely. - -* Builder must now be an explicit target for markup tags. Instead of - writing - - xml_markup = Builder::XmlMarkup.new - xml_markup.div { strong("text") } - - you need to write - - xml_markup = Builder::XmlMarkup.new - xml_markup.div { xml_markup.strong("text") } - -* The builder object is passed as a parameter to all nested markup - blocks. This allows you to create a short alias for the builder - object that can be used within the block. For example, the previous - example can be written as: - - xml_markup = Builder::XmlMarkup.new - xml_markup.div { |xml| xml.strong("text") } - -* If you have both a pre-1.0 and a post-1.0 gem of builder installed, - you can choose which version to use through the RubyGems - +require_gem+ facility. - - require_gem 'builder', "~> 0.0" # Gets the old version - require_gem 'builder', "~> 1.0" # Gets the new version - -== Features - -* XML Comments are supported ... - - xml_markup.comment! "This is a comment" - #=> - -* XML processing instructions are supported ... - - xml_markup.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8" - #=> - - If the processing instruction is omitted, it defaults to "xml". - When the processing instruction is "xml", the defaults attributes - are: - - version:: 1.0 - encoding:: "UTF-8" - - (NOTE: if the encoding is set to "UTF-8" and $KCODE is set to - "UTF8", then Builder will emit UTF-8 encoded strings rather than - encoding non-ASCII characters as entities.) - -* XML entity declarations are now supported to a small degree. - - xml_markup.declare! :DOCTYPE, :chapter, :SYSTEM, "../dtds/chapter.dtd" - #=> - - The parameters to a declare! method must be either symbols or - strings. Symbols are inserted without quotes, and strings are - inserted with double quotes. Attribute-like arguments in hashes are - not allowed. - - If you need to have an argument to declare! be inserted without - quotes, but the arguement does not conform to the typical Ruby - syntax for symbols, then use the :"string" form to specify a symbol. - - For example: - - xml_markup.declare! :ELEMENT, :chapter, :"(title,para+)" - #=> - - Nested entity declarations are allowed. For example: - - @xml_markup.declare! :DOCTYPE, :chapter do |x| - x.declare! :ELEMENT, :chapter, :"(title,para+)" - x.declare! :ELEMENT, :title, :"(#PCDATA)" - x.declare! :ELEMENT, :para, :"(#PCDATA)" - end - - #=> - - - - - ]> - -* Some support for XML namespaces is now available. If the first - argument to a tag call is a symbol, it will be joined to the tag to - produce a namespace:tag combination. It is easier to show this than - describe it. - - xml.SOAP :Envelope do ... end - - Just put a space before the colon in a namespace to produce the - right form for builder (e.g. "SOAP:Envelope" => - "xml.SOAP :Envelope") - -* String attribute values are now escaped by default by - Builder (NOTE: this is _new_ behavior as of version 2.0). - - However, occasionally you need to use entities in attribute values. - Using a symbols (rather than a string) for an attribute value will - cause Builder to not run its quoting/escaping algorithm on that - particular value. - - (Note: The +escape_attrs+ option for builder is now - obsolete). - - Example: - - xml = Builder::XmlMarkup.new - xml.sample(:escaped=>"This&That", :unescaped=>:"Here&There") - xml.target! => - - -* UTF-8 Support - - Builder correctly translates UTF-8 characters into valid XML. (New - in version 2.0.0). Thanks to Sam Ruby for the translation code. - - You can get UTF-8 encoded output by making sure that the XML - encoding is set to "UTF-8" and that the $KCODE variable is set to - "UTF8". - - $KCODE = 'UTF8' - xml = Builder::Markup.new - xml.instruct!(:xml, :encoding => "UTF-8") - xml.sample("Iñtërnâtiônàl") - xml.target! => - "Iñtërnâtiônàl" - -== Links - -Documents :: http://builder.rubyforge.org/ -Github Clone :: git://github.com/jimweirich/builder.git -Issue / Bug Reports :: https://github.com/jimweirich/builder/issues?state=open - -== Contact - -Author:: Jim Weirich -Email:: jim.weirich@gmail.com -Home Page:: http://onestepback.org -License:: MIT Licence (http://www.opensource.org/licenses/mit-license.html) diff --git a/doc/releases/builder-1.2.4.rdoc b/doc/releases/builder-1.2.4.rdoc deleted file mode 100644 index a1cf54f..0000000 --- a/doc/releases/builder-1.2.4.rdoc +++ /dev/null @@ -1,31 +0,0 @@ -= Builder 1.2.4 Released. - -Added a "CDATA" method to the XML Markup builder (from Josh Knowles). - -== What is Builder? - -Builder::XmlMarkup allows easy programmatic creation of XML markup. -For example: - - builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) - builder.person { |b| b.name("Jim"); b.phone("555-1234") } - puts builder.target! - -will generate: - - - Jim - 555-1234 - - -== Availability - -The easiest way to get and install builder is via RubyGems ... - - gem install builder (you may need root/admin privileges) - -== Thanks - -* Josh Knowles for the cdata! patch. - --- Jim Weirich diff --git a/doc/releases/builder-2.0.0.rdoc b/doc/releases/builder-2.0.0.rdoc deleted file mode 100644 index ed9e086..0000000 --- a/doc/releases/builder-2.0.0.rdoc +++ /dev/null @@ -1,46 +0,0 @@ -= Builder 2.0.0 Released. - -== Changes in 2.0.0 - -* UTF-8 characters in data are now correctly translated to their XML - equivalents. (Thanks to Sam Ruby) - -* Attribute values are now escaped by default. See the README - file for details. - -NOTE: The escaping attribute values by default is different -than in previous releases of Builder. This makes version 2.0.0 -somewhat incompatible with the 1.x series of Builder. If you use "&", -"<", or ">" in attributes values, you may have to change your -code. (Essentially you remove the manual escaping. The new way is -easier, believe me). - -== What is Builder? - -Builder::XmlMarkup is a library that allows easy programmatic creation -of XML markup. For example: - - builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) - builder.person { |b| b.name("Jim"); b.phone("555-1234") } - -will generate: - - - Jim - 555-1234 - - -== Availability - -The easiest way to get and install builder is via RubyGems ... - - gem install builder (you may need root/admin privileges) - -== Thanks - -* Sam Ruby for the XChar module and the related UTF-8 translation - tools. -* Also to Sam Ruby for gently persuading me to start quoting attribute - values. - --- Jim Weirich diff --git a/doc/releases/builder-2.1.1.rdoc b/doc/releases/builder-2.1.1.rdoc deleted file mode 100755 index dbbf121..0000000 --- a/doc/releases/builder-2.1.1.rdoc +++ /dev/null @@ -1,58 +0,0 @@ -= Builder 2.1.1 Released. - -Release 2.1.1 of Builder is mainly a bug fix release. - -== Changes in 2.1.1 - -* Added reveal capability to BlankSlate. - -* Fixed a bug in BlankSlate where including a module into Object could - cause methods to leak into BlankSlate. - -* Fixed typo in XmlMarkup class docs (from Martin Fowler). - -* Fixed test on private methods to differentiate between targetted and - untargetted private methods. - -* Removed legacy capture of @self in XmlBase (@self was used back when - we used instance eval). - -* Added additional tests for global functions (both direct and - included). - -* Several misc internal cleanups, including rearranging the source - code tree. - -NOTE: The escaping attribute values by default is different -than in previous releases of Builder. This makes version 2.0.x -somewhat incompatible with the 1.x series of Builder. If you use "&", -"<", or ">" in attributes values, you may have to change your -code. (Essentially you remove the manual escaping. The new way is -easier, believe me). - -== What is Builder? - -Builder::XmlMarkup is a library that allows easy programmatic creation -of XML markup. For example: - - builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) - builder.person { |b| b.name("Jim"); b.phone("555-1234") } - -will generate: - - - Jim - 555-1234 - - -== Availability - -The easiest way to get and install builder is via RubyGems ... - - gem install builder (you may need root/admin privileges) - -== Thanks - -* Martin Fowler for spotting some typos in the documentation. - --- Jim Weirich diff --git a/test/test_eventbuilder.rb b/test/test_eventbuilder.rb deleted file mode 100644 index f434470..0000000 --- a/test/test_eventbuilder.rb +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env ruby - -#-- -# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). -# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). -# All rights reserved. - -# Permission is granted for use, copying, modification, distribution, -# and distribution of modified versions of this work as long as the -# above copyright notice is included. -#++ - -require 'test/unit' -require 'test/preload' -require 'builder' -require 'builder/xmlevents' - -class TestEvents < Test::Unit::TestCase - - class Target - attr_reader :events - - def initialize - @events = [] - end - - def start_tag(tag, attrs) - @events << [:start_tag, tag, attrs] - end - - def end_tag(tag) - @events << [:end_tag, tag] - end - - def text(string) - @events << [:text, string] - end - - end - - - def setup - @target = Target.new - @xml = Builder::XmlEvents.new(:target=>@target) - end - - def test_simple - @xml.one - expect [:start_tag, :one, nil] - expect [:end_tag, :one] - expect_done - end - - def test_nested - @xml.one { @xml.two } - expect [:start_tag, :one, nil] - expect [:start_tag, :two, nil] - expect [:end_tag, :two] - expect [:end_tag, :one] - expect_done - end - - def test_text - @xml.one("a") - expect [:start_tag, :one, nil] - expect [:text, "a"] - expect [:end_tag, :one] - expect_done - end - - def test_special_text - @xml.one("H&R") - expect [:start_tag, :one, nil] - expect [:text, "H&R"] - expect [:end_tag, :one] - expect_done - end - - def test_text_with_entity - @xml.one("H&R") - expect [:start_tag, :one, nil] - expect [:text, "H&R"] - expect [:end_tag, :one] - expect_done - end - - def test_attributes - @xml.a(:b=>"c", :x=>"y") - expect [:start_tag, :a, {:x => "y", :b => "c"}] - expect [:end_tag, :a] - expect_done - end - - def test_moderately_complex - @xml.tag! "address-book" do |x| - x.entry :id=>"1" do - x.name { - x.first "Bill" - x.last "Smith" - } - x.address "Cincinnati" - end - x.entry :id=>"2" do - x.name { - x.first "John" - x.last "Doe" - } - x.address "Columbus" - end - end - expect [:start_tag, "address-book".intern, nil] - expect [:start_tag, :entry, {:id => "1"}] - expect [:start_tag, :name, nil] - expect [:start_tag, :first, nil] - expect [:text, "Bill"] - expect [:end_tag, :first] - expect [:start_tag, :last, nil] - expect [:text, "Smith"] - expect [:end_tag, :last] - expect [:end_tag, :name] - expect [:start_tag, :address, nil] - expect [:text, "Cincinnati"] - expect [:end_tag, :address] - expect [:end_tag, :entry] - expect [:start_tag, :entry, {:id => "2"}] - expect [:start_tag, :name, nil] - expect [:start_tag, :first, nil] - expect [:text, "John"] - expect [:end_tag, :first] - expect [:start_tag, :last, nil] - expect [:text, "Doe"] - expect [:end_tag, :last] - expect [:end_tag, :name] - expect [:start_tag, :address, nil] - expect [:text, "Columbus"] - expect [:end_tag, :address] - expect [:end_tag, :entry] - expect [:end_tag, "address-book".intern] - expect_done - end - - def expect(value) - assert_equal value, @target.events.shift - end - - def expect_done - assert_nil @target.events.shift - end - -end diff --git a/test/test_markupbuilder.rb b/test/test_markupbuilder.rb deleted file mode 100644 index b9cee65..0000000 --- a/test/test_markupbuilder.rb +++ /dev/null @@ -1,573 +0,0 @@ -#!/usr/bin/env ruby - -#-- -# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). -# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). -# All rights reserved. - -# Permission is granted for use, copying, modification, distribution, -# and distribution of modified versions of this work as long as the -# above copyright notice is included. -#++ - -require 'test/unit' -require 'test/preload' -require 'builder' -require 'builder/xmlmarkup' - -class TestMarkup < Test::Unit::TestCase - def setup - @xml = Builder::XmlMarkup.new - end - - def test_create - assert_not_nil @xml - end - - def test_simple - @xml.simple - assert_equal "", @xml.target! - end - - def test_value - @xml.value("hi") - assert_equal "hi", @xml.target! - end - - def test_empty_value - @xml.value("") - assert_equal "", @xml.target! - end - - def test_nil_value - @xml.value(nil) - assert_equal "", @xml.target! - end - - def test_nested - @xml.outer { |x| x.inner("x") } - assert_equal "x", @xml.target! - end - - def test_attributes - @xml.ref(:id => 12) - assert_equal %{}, @xml.target! - end - - def test_string_attributes_are_quoted_by_default - @xml.ref(:id => "H&R") - assert_equal %{}, @xml.target! - end - - def test_symbol_attributes_are_unquoted_by_default - @xml.ref(:id => :"H&R") - assert_equal %{}, @xml.target! - end - - def test_attributes_quoted_can_be_turned_on - @xml = Builder::XmlMarkup.new - @xml.ref(:id => "") - assert_equal %{}, @xml.target! - end - - def test_mixed_attribute_quoting_with_nested_builders - x = Builder::XmlMarkup.new(:target=>@xml) - @xml.ref(:id=>:"H&R") { - x.element(:tag=>"Long&Short") - } - assert_equal "", - @xml.target! - end - - def test_multiple_attributes - @xml.ref(:id => 12, :name => "bill") - assert_match %r{^$}, @xml.target! - end - - def test_attributes_with_text - @xml.a("link", :href=>"http://onestepback.org") - assert_equal %{
link}, @xml.target! - end - - def test_attributes_with_newlines - @xml.abbr("W3C", :title=>"World\nWide\rWeb\r\nConsortium") - assert_equal %{W3C}, - @xml.target! - end - - def test_complex - @xml.body(:bg=>"#ffffff") { |x| - x.title("T", :style=>"red") - } - assert_equal %{T}, @xml.target! - end - - def test_funky_symbol - @xml.tag!("non-ruby-token", :id=>1) { |x| x.ok } - assert_equal %{}, @xml.target! - end - - def test_tag_can_handle_private_method - @xml.tag!("loop", :id=>1) { |x| x.ok } - assert_equal %{}, @xml.target! - end - - def test_no_explicit_marker - @xml.p { |x| x.b("HI") } - assert_equal "

HI

", @xml.target! - end - - def test_reference_local_vars - n = 3 - @xml.ol { |x| n.times { x.li(n) } } - assert_equal "
  1. 3
  2. 3
  3. 3
", @xml.target! - end - - def test_reference_methods - @xml.title { |x| x.a { x.b(name) } } - assert_equal "<a><b>bob</b></a>", @xml.target! - end - - def test_append_text - @xml.p { |x| x.br; x.text! "HI" } - assert_equal "


HI

", @xml.target! - end - - def test_ambiguous_markup - ex = assert_raise(ArgumentError) { - @xml.h1("data1") { b } - } - assert_match(/\btext\b/, ex.message) - assert_match(/\bblock\b/, ex.message) - end - - def test_capitalized_method - @xml.P { |x| x.B("hi"); x.BR(); x.EM { x.text! "world" } } - assert_equal "

hi
world

", @xml.target! - end - - def test_escaping - @xml.div { |x| x.text! ""; x.em("H&R Block") } - assert_equal %{
<hi>H&R Block
}, @xml.target! - end - - def test_non_escaping - @xml.div("ns:xml"=>:"&xml;") { |x| x << ""; x.em("H&R Block") } - assert_equal %{
H&R Block
}, @xml.target! - end - - def test_return_value - str = @xml.x("men") - assert_equal @xml.target!, str - end - - def test_stacked_builders - b = Builder::XmlMarkup.new( :target => @xml ) - b.div { @xml.span { @xml.a("text", :href=>"ref") } } - assert_equal "", @xml.target! - end - - def name - "bob" - end -end - -class TestAttributeEscaping < Test::Unit::TestCase - - def setup - @xml = Builder::XmlMarkup.new - end - - def test_element_gt - @xml.title('1<2') - assert_equal '1<2', @xml.target! - end - - def test_element_amp - @xml.title('AT&T') - assert_equal 'AT&T', @xml.target! - end - - def test_element_amp2 - @xml.title('&') - assert_equal '&amp;', @xml.target! - end - - def test_attr_less - @xml.a(:title => '2>1') - assert_equal '', @xml.target! - end - - def test_attr_amp - @xml.a(:title => 'AT&T') - assert_equal '', @xml.target! - end - - def test_attr_quot - @xml.a(:title => '"x"') - assert_equal '', @xml.target! - end - -end - -class TestNameSpaces < Test::Unit::TestCase - def setup - @xml = Builder::XmlMarkup.new(:indent=>2) - end - - def test_simple_name_spaces - @xml.rdf :RDF - assert_equal "\n", @xml.target! - end - - def test_long - xml = Builder::XmlMarkup.new(:indent=>2) - xml.instruct! - xml.rdf :RDF, - "xmlns:rdf" => :"&rdf;", - "xmlns:rdfs" => :"&rdfs;", - "xmlns:xsd" => :"&xsd;", - "xmlns:owl" => :"&owl;" do - xml.owl :Class, :'rdf:ID'=>'Bird' do - xml.rdfs :label, 'bird' - xml.rdfs :subClassOf do - xml.owl :Restriction do - xml.owl :onProperty, 'rdf:resource'=>'#wingspan' - xml.owl :maxCardinality,1,'rdf:datatype'=>'&xsd;nonNegativeInteger' - end - end - end - end - assert_match(/^<\?xml/, xml.target!) - assert_match(/\n/m, xml.target!) - end - - def test_ensure - xml = Builder::XmlMarkup.new - xml.html do - xml.body do - begin - xml.p do - raise Exception.new('boom') - end - rescue Exception => e - xml.pre e - end - end - end - assert_match %r{

}, xml.target! - assert_match %r{

}, xml.target! - end -end - -class TestDeclarations < Test::Unit::TestCase - def setup - @xml = Builder::XmlMarkup.new(:indent=>2) - end - - def test_declare - @xml.declare! :element - assert_equal "\n", @xml.target! - end - - def test_bare_arg - @xml.declare! :element, :arg - assert_equal"\n", @xml.target! - end - - def test_string_arg - @xml.declare! :element, "string" - assert_equal"\n", @xml.target! - end - - def test_mixed_args - @xml.declare! :element, :x, "y", :z, "-//OASIS//DTD DocBook XML//EN" - assert_equal "\n", @xml.target! - end - - def test_nested_declarations - @xml = Builder::XmlMarkup.new - @xml.declare! :DOCTYPE, :chapter do |x| - x.declare! :ELEMENT, :chapter, "(title,para+)".intern - end - assert_equal "]>", @xml.target! - end - - def test_nested_indented_declarations - @xml.declare! :DOCTYPE, :chapter do |x| - x.declare! :ELEMENT, :chapter, "(title,para+)".intern - end - assert_equal "\n]>\n", @xml.target! - end - - def test_complex_declaration - @xml.declare! :DOCTYPE, :chapter do |x| - x.declare! :ELEMENT, :chapter, "(title,para+)".intern - x.declare! :ELEMENT, :title, "(#PCDATA)".intern - x.declare! :ELEMENT, :para, "(#PCDATA)".intern - end - expected = %{ - - -]> -} - assert_equal expected, @xml.target! - end -end - - -class TestSpecialMarkup < Test::Unit::TestCase - def setup - @xml = Builder::XmlMarkup.new(:indent=>2) - end - - def test_comment - @xml.comment!("COMMENT") - assert_equal "\n", @xml.target! - end - - def test_indented_comment - @xml.p { @xml.comment! "OK" } - assert_equal "

\n \n

\n", @xml.target! - end - - def test_instruct - @xml.instruct! :abc, :version=>"0.9" - assert_equal "\n", @xml.target! - end - - def test_indented_instruct - @xml.p { @xml.instruct! :xml } - assert_match %r{

\n <\?xml version="1.0" encoding="UTF-8"\?>\n

\n}, - @xml.target! - end - - def test_instruct_without_attributes - @xml.instruct! :zz - assert_equal "\n", @xml.target! - end - - def test_xml_instruct - @xml.instruct! - assert_match(/^<\?xml version="1.0" encoding="UTF-8"\?>$/, @xml.target!) - end - - def test_xml_instruct_with_overrides - @xml.instruct! :xml, :encoding=>"UCS-2" - assert_match(/^<\?xml version="1.0" encoding="UCS-2"\?>$/, @xml.target!) - end - - def test_xml_instruct_with_standalong - @xml.instruct! :xml, :encoding=>"UCS-2", :standalone=>"yes" - assert_match(/^<\?xml version="1.0" encoding="UCS-2" standalone="yes"\?>$/, @xml.target!) - end - - def test_no_blocks - assert_raise(Builder::IllegalBlockError) do - @xml.instruct! { |x| x.hi } - end - assert_raise(Builder::IllegalBlockError) do - @xml.comment!(:element) { |x| x.hi } - end - end - - def test_cdata - @xml.cdata!("TEST") - assert_equal "\n", @xml.target! - end - - def test_cdata_with_ampersand - @xml.cdata!("TEST&CHECK") - assert_equal "\n", @xml.target! - end - - def test_cdata_with_included_close - @xml.cdata!("TEST]]>CHECK") - assert_equal "CHECK]]>\n", @xml.target! - end -end - -class TestIndentedXmlMarkup < Test::Unit::TestCase - def setup - @xml = Builder::XmlMarkup.new(:indent=>2) - end - - def test_one_level - @xml.ol { |x| x.li "text" } - assert_equal "
    \n
  1. text
  2. \n
\n", @xml.target! - end - - def test_two_levels - @xml.p { |x| - x.ol { x.li "text" } - x.br - } - assert_equal "

\n

    \n
  1. text
  2. \n
\n
\n

\n", @xml.target! - end - - def test_initial_level - @xml = Builder::XmlMarkup.new(:indent=>2, :margin=>4) - @xml.name { |x| x.first("Jim") } - assert_equal " \n Jim\n \n", @xml.target! - end - - class TestUtfMarkup < Test::Unit::TestCase - if ! String.method_defined?(:encode) - def setup - @old_kcode = $KCODE - end - - def teardown - $KCODE = @old_kcode - end - - def test_use_entities_if_no_encoding_is_given_and_kcode_is_none - $KCODE = 'NONE' - xml = Builder::XmlMarkup.new - xml.p("\xE2\x80\x99") - assert_match(%r(

), xml.target!) # - end - - def test_use_entities_if_encoding_is_utf_but_kcode_is_not - $KCODE = 'NONE' - xml = Builder::XmlMarkup.new - xml.instruct!(:xml, :encoding => 'UTF-8') - xml.p("\xE2\x80\x99") - assert_match(%r(

), xml.target!) # - end - else - # change in behavior. As there is no $KCODE anymore, the default - # moves from "does not understand utf-8" to "supports utf-8". - - def test_use_entities_if_no_encoding_is_given_and_kcode_is_none - xml = Builder::XmlMarkup.new - xml.p("\xE2\x80\x99") - assert_match("

\u2019

", xml.target!) # - end - - def test_use_entities_if_encoding_is_utf_but_kcode_is_not - xml = Builder::XmlMarkup.new - xml.instruct!(:xml, :encoding => 'UTF-8') - xml.p("\xE2\x80\x99") - assert_match("

\u2019

", xml.target!) # - end - end - - def encode string, encoding - if !String.method_defined?(:encode) - $KCODE = encoding - string - elsif encoding == 'UTF8' - string.force_encoding('UTF-8') - else - string - end - end - - def test_use_entities_if_kcode_is_utf_but_encoding_is_dummy_encoding - xml = Builder::XmlMarkup.new - xml.instruct!(:xml, :encoding => 'UTF-16') - xml.p(encode("\xE2\x80\x99", 'UTF8')) - assert_match(%r(

), xml.target!) # - end - - def test_use_entities_if_kcode_is_utf_but_encoding_is_unsupported_encoding - xml = Builder::XmlMarkup.new - xml.instruct!(:xml, :encoding => 'UCS-2') - xml.p(encode("\xE2\x80\x99", 'UTF8')) - assert_match(%r(

), xml.target!) # - end - - def test_use_utf8_if_encoding_defaults_and_kcode_is_utf8 - xml = Builder::XmlMarkup.new - xml.p(encode("\xE2\x80\x99",'UTF8')) - assert_equal encode("

\xE2\x80\x99

",'UTF8'), xml.target! - end - - def test_use_utf8_if_both_encoding_and_kcode_are_utf8 - xml = Builder::XmlMarkup.new - xml.instruct!(:xml, :encoding => 'UTF-8') - xml.p(encode("\xE2\x80\x99",'UTF8')) - assert_match encode("

\xE2\x80\x99

",'UTF8'), xml.target! - end - - def test_use_utf8_if_both_encoding_and_kcode_are_utf8_with_lowercase - xml = Builder::XmlMarkup.new - xml.instruct!(:xml, :encoding => 'utf-8') - xml.p(encode("\xE2\x80\x99",'UTF8')) - assert_match encode("

\xE2\x80\x99

",'UTF8'), xml.target! - end - end - - class TestXmlEvents < Test::Unit::TestCase - def setup - @handler = EventHandler.new - @xe = Builder::XmlEvents.new(:target=>@handler) - end - - def test_simple - @xe.p - assert_equal [:start, :p, nil], @handler.events.shift - assert_equal [:end, :p], @handler.events.shift - end - - def test_text - @xe.p("HI") - assert_equal [:start, :p, nil], @handler.events.shift - assert_equal [:text, "HI"], @handler.events.shift - assert_equal [:end, :p], @handler.events.shift - end - - def test_attributes - @xe.p("id"=>"2") - ev = @handler.events.shift - assert_equal [:start, :p], ev[0,2] - assert_equal "2", ev[2]['id'] - assert_equal [:end, :p], @handler.events.shift - end - - def test_indented - @xml = Builder::XmlEvents.new(:indent=>2, :target=>@handler) - @xml.p { |x| x.b("HI") } - assert_equal [:start, :p, nil], @handler.events.shift - assert_equal "\n ", pop_text - assert_equal [:start, :b, nil], @handler.events.shift - assert_equal "HI", pop_text - assert_equal [:end, :b], @handler.events.shift - assert_equal "\n", pop_text - assert_equal [:end, :p], @handler.events.shift - end - - def pop_text - result = '' - while ! @handler.events.empty? && @handler.events[0][0] == :text - result << @handler.events[0][1] - @handler.events.shift - end - result - end - - class EventHandler - attr_reader :events - def initialize - @events = [] - end - - def start_tag(sym, attrs) - @events << [:start, sym, attrs] - end - - def end_tag(sym) - @events << [:end, sym] - end - - def text(txt) - @events << [:text, txt] - end - end - end - -end diff --git a/test/test_method_caching.rb b/test/test_method_caching.rb deleted file mode 100644 index 94da212..0000000 --- a/test/test_method_caching.rb +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env ruby - -#-- -# Portions copyright 2011 by Bart ten Brinke (info@retrosync.com). -# All rights reserved. - -# Permission is granted for use, copying, modification, distribution, -# and distribution of modified versions of this work as long as the -# above copyright notice is included. -#++ - -require 'test/unit' -require 'test/preload' -require 'builder' - -class TestMethodCaching < Test::Unit::TestCase - - # We can directly ask if xml object responds to the cache_me or - # do_not_cache_me methods because xml is derived from BasicObject - # (and repond_to? is not defined in BasicObject). - # - # Instead we are going to stub out method_missing so that it throws - # an error, and then make sure that error is either thrown or not - # thrown as appropriate. - - def teardown - super - Builder::XmlBase.cache_method_calls = true - end - - def test_caching_does_not_break_weird_symbols - xml = Builder::XmlMarkup.new - xml.__send__("work-order", 1) - assert_equal "1", xml.target! - end - - def test_method_call_caching - xml = Builder::XmlMarkup.new - xml.cache_me - - def xml.method_missing(*args) - ::Kernel.fail StandardError, "SHOULD NOT BE CALLED" - end - assert_nothing_raised do - xml.cache_me - end - end - - def test_method_call_caching_disabled - Builder::XmlBase.cache_method_calls = false - xml = Builder::XmlMarkup.new - xml.do_not_cache_me - - def xml.method_missing(*args) - ::Kernel.fail StandardError, "SHOULD BE CALLED" - end - assert_raise(StandardError, /SHOULD BE CALLED/) do - xml.do_not_cache_me - end - end - -end diff --git a/test/test_namecollision.rb b/test/test_namecollision.rb deleted file mode 100644 index 5b16b30..0000000 --- a/test/test_namecollision.rb +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env ruby - -#-- -# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). -# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). -# All rights reserved. - -# Permission is granted for use, copying, modification, distribution, -# and distribution of modified versions of this work as long as the -# above copyright notice is included. -#++ - -require 'test/unit' -require 'builder/xchar' - -class TestNameCollisions < Test::Unit::TestCase - module Collide - def xchr - end - end - - def test_no_collision - assert_nothing_raised do - Builder.check_for_name_collision(Collide, :not_defined) - end - end - - def test_collision - assert_raise RuntimeError do - Builder.check_for_name_collision(Collide, "xchr") - end - end - - def test_collision_with_symbol - assert_raise RuntimeError do - Builder.check_for_name_collision(Collide, :xchr) - end - end -end diff --git a/test/test_xchar.rb b/test/test_xchar.rb deleted file mode 100644 index fd67114..0000000 --- a/test/test_xchar.rb +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env ruby - -#-- -# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). -# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). -# All rights reserved. - -# Permission is granted for use, copying, modification, distribution, -# and distribution of modified versions of this work as long as the -# above copyright notice is included. -#++ - -#!/usr/bin/env ruby - -require 'test/unit' -require 'builder/xchar' - -if String.method_defined?(:encode) - class String - ENCODING_BINARY = Encoding.find('BINARY') - - # shim method for testing purposes - def to_xs(escape=true) - raise NameError.new('to_xs') unless caller[0].index(__FILE__) - - result = Builder::XChar.encode(self) - if escape - result.gsub(/[^\u0000-\u007F]/) {|c| "&##{c.ord};"} - else - # really only useful for testing purposes - result.force_encoding(ENCODING_BINARY) - end - end - end -end - -class TestXmlEscaping < Test::Unit::TestCase - REPLACEMENT_CHAR = Builder::XChar::REPLACEMENT_CHAR.to_xs - - def test_ascii - assert_equal 'abc', 'abc'.to_xs - end - - def test_predefined - assert_equal '&', '&'.to_xs # ampersand - assert_equal '<', '<'.to_xs # left angle bracket - assert_equal '>', '>'.to_xs # right angle bracket - end - - def test_invalid - assert_equal REPLACEMENT_CHAR, "\x00".to_xs # null - assert_equal REPLACEMENT_CHAR, "\x0C".to_xs # form feed - assert_equal REPLACEMENT_CHAR, "\xEF\xBF\xBF".to_xs # U+FFFF - end - - def test_iso_8859_1 - assert_equal 'ç', "\xE7".to_xs # small c cedilla - assert_equal '©', "\xA9".to_xs # copyright symbol - end - - def test_win_1252 - assert_equal '’', "\x92".to_xs # smart quote - assert_equal '€', "\x80".to_xs # euro - end - - def test_utf8 - assert_equal '’', "\xE2\x80\x99".to_xs # right single quote - assert_equal '©', "\xC2\xA9".to_xs # copy - end - - def test_utf8_verbatim - assert_equal "\xE2\x80\x99", "\xE2\x80\x99".to_xs(false) # right single quote - assert_equal "\xC2\xA9", "\xC2\xA9".to_xs(false) # copy - assert_equal "\xC2\xA9&\xC2\xA9", - "\xC2\xA9&\xC2\xA9".to_xs(false) # copy with ampersand - end -end From 78fcd6090c80af0f7d09144b7ed5f781e2dbc9da Mon Sep 17 00:00:00 2001 From: Viliam Pucik Date: Sat, 22 Dec 2012 22:33:57 +0100 Subject: [PATCH 3/5] Added missing test file from builder gem https://raw.github.com/jimweirich/builder/master/test/preload.rb --- test/preload.rb | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 test/preload.rb diff --git a/test/preload.rb b/test/preload.rb new file mode 100644 index 0000000..395e043 --- /dev/null +++ b/test/preload.rb @@ -0,0 +1,39 @@ +#!/usr/bin/env ruby + +#-- +# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +# We are defining method_added in Kernel and Object so that when +# BlankSlate overrides them later, we can verify that it correctly +# calls the older hooks. + +module Kernel + class << self + attr_reader :k_added_names + alias_method :preload_method_added, :method_added + def method_added(name) + preload_method_added(name) + @k_added_names ||= [] + @k_added_names << name + end + end +end + +class Object + class << self + attr_reader :o_added_names + alias_method :preload_method_added, :method_added + def method_added(name) + preload_method_added(name) + @o_added_names ||= [] + @o_added_names << name + end + end +end From 5295de3aded1eb003fc67daa530c384203eb68c7 Mon Sep 17 00:00:00 2001 From: Viliam Pucik Date: Sat, 22 Dec 2012 22:35:53 +0100 Subject: [PATCH 4/5] removing shebangs from class files --- lib/blankslate.rb | 1 - test/preload.rb | 2 -- 2 files changed, 3 deletions(-) diff --git a/lib/blankslate.rb b/lib/blankslate.rb index e947376..4cae7d5 100644 --- a/lib/blankslate.rb +++ b/lib/blankslate.rb @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby #-- # Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org). # All rights reserved. diff --git a/test/preload.rb b/test/preload.rb index 395e043..631cd7d 100644 --- a/test/preload.rb +++ b/test/preload.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - #-- # Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org). # Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net). From e5f6cd241ef25514d90f1e2cebf634feaabb67b7 Mon Sep 17 00:00:00 2001 From: Viliam Pucik Date: Sat, 22 Dec 2012 22:36:16 +0100 Subject: [PATCH 5/5] Fixed test script permissions --- test/test_blankslate.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 test/test_blankslate.rb diff --git a/test/test_blankslate.rb b/test/test_blankslate.rb old mode 100644 new mode 100755