aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/test')
-rw-r--r--activesupport/test/autoload.rb80
-rw-r--r--activesupport/test/callback_inheritance_test.rb35
-rw-r--r--activesupport/test/core_ext/blank_test.rb9
-rw-r--r--activesupport/test/core_ext/date_time_ext_test.rb4
-rw-r--r--activesupport/test/core_ext/enumerable_test.rb5
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb8
-rw-r--r--activesupport/test/core_ext/integer_ext_test.rb5
-rw-r--r--activesupport/test/core_ext/object/to_query_test.rb8
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb31
-rw-r--r--activesupport/test/core_ext/time_with_zone_test.rb6
-rw-r--r--activesupport/test/deprecation_test.rb2
-rw-r--r--activesupport/test/fixtures/autoload/another_class.rb2
-rw-r--r--activesupport/test/fixtures/autoload/some_class.rb2
-rw-r--r--activesupport/test/isolation_test.rb262
-rw-r--r--activesupport/test/json/encoding_test.rb4
-rw-r--r--activesupport/test/notifications_test.rb278
-rw-r--r--activesupport/test/test_test.rb9
-rw-r--r--activesupport/test/whiny_nil_test.rb13
-rw-r--r--activesupport/test/xml_mini/libxml_engine_test.rb9
-rw-r--r--activesupport/test/xml_mini/libxmlsax_engine_test.rb194
-rw-r--r--activesupport/test/xml_mini/nokogiri_engine_test.rb40
-rw-r--r--activesupport/test/xml_mini/nokogirisax_engine_test.rb217
22 files changed, 921 insertions, 302 deletions
diff --git a/activesupport/test/autoload.rb b/activesupport/test/autoload.rb
new file mode 100644
index 0000000000..5d8026a9ca
--- /dev/null
+++ b/activesupport/test/autoload.rb
@@ -0,0 +1,80 @@
+require 'abstract_unit'
+
+class TestAutoloadModule < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ module ::Fixtures
+ extend ActiveSupport::Autoload
+
+ module Autoload
+ extend ActiveSupport::Autoload
+ end
+ end
+
+ test "the autoload module works like normal autoload" do
+ module ::Fixtures::Autoload
+ autoload :SomeClass, "fixtures/autoload/some_class"
+ end
+
+ assert_nothing_raised { ::Fixtures::Autoload::SomeClass }
+ end
+
+ test "when specifying an :eager constant it still works like normal autoload by default" do
+ module ::Fixtures::Autoload
+ autoload :SomeClass, "fixtures/autoload/some_class"
+ end
+
+ assert !$LOADED_FEATURES.include?("fixtures/autoload/some_class.rb")
+ assert_nothing_raised { ::Fixtures::Autoload::SomeClass }
+ end
+
+ test ":eager constants can be triggered via ActiveSupport::Autoload.eager_autoload!" do
+ module ::Fixtures::Autoload
+ autoload :SomeClass, "fixtures/autoload/some_class"
+ end
+ ActiveSupport::Autoload.eager_autoload!
+ assert $LOADED_FEATURES.include?("fixtures/autoload/some_class.rb")
+ assert_nothing_raised { ::Fixtures::Autoload::SomeClass }
+ end
+
+ test "the location of autoloaded constants defaults to :name.underscore" do
+ module ::Fixtures::Autoload
+ autoload :SomeClass
+ end
+
+ assert !$LOADED_FEATURES.include?("fixtures/autoload/some_class.rb")
+ assert_nothing_raised { ::Fixtures::Autoload::SomeClass }
+ end
+
+ test "the location of :eager autoloaded constants defaults to :name.underscore" do
+ module ::Fixtures::Autoload
+ autoload :SomeClass
+ end
+
+ ActiveSupport::Autoload.eager_autoload!
+ assert $LOADED_FEATURES.include?("fixtures/autoload/some_class.rb")
+ assert_nothing_raised { ::Fixtures::Autoload::SomeClass }
+ end
+
+ test "a directory for a block of autoloads can be specified" do
+ module ::Fixtures
+ autoload_under "autoload" do
+ autoload :AnotherClass
+ end
+ end
+
+ assert !$LOADED_FEATURES.include?("fixtures/autoload/another_class.rb")
+ assert_nothing_raised { ::Fixtures::AnotherClass }
+ end
+
+ test "a path for a block of autoloads can be specified" do
+ module ::Fixtures
+ autoload_at "fixtures/autoload/another_class" do
+ autoload :AnotherClass
+ end
+ end
+
+ assert !$LOADED_FEATURES.include?("fixtures/autoload/another_class.rb")
+ assert_nothing_raised { ::Fixtures::AnotherClass }
+ end
+end \ No newline at end of file
diff --git a/activesupport/test/callback_inheritance_test.rb b/activesupport/test/callback_inheritance_test.rb
index 18721eab19..2e978f01be 100644
--- a/activesupport/test/callback_inheritance_test.rb
+++ b/activesupport/test/callback_inheritance_test.rb
@@ -56,6 +56,31 @@ class Child < GrandParent
end
end
+class EmptyParent
+ include ActiveSupport::Callbacks
+
+ def performed?
+ @performed ||= false
+ end
+
+ define_callbacks :dispatch
+
+ def perform!
+ @performed = true
+ end
+
+ def dispatch
+ _run_dispatch_callbacks
+ self
+ end
+end
+
+class EmptyChild < EmptyParent
+ set_callback :dispatch, :before, :do_nothing
+
+ def do_nothing
+ end
+end
class BasicCallbacksTest < Test::Unit::TestCase
def setup
@@ -113,3 +138,13 @@ class InheritedCallbacksTest2 < Test::Unit::TestCase
assert_equal %w(before1 before2 update after2 after1), @update2.log
end
end
+
+class DynamicInheritedCallbacks < Test::Unit::TestCase
+ def test_callbacks_looks_to_the_superclass_before_running
+ child = EmptyChild.new.dispatch
+ assert !child.performed?
+ EmptyParent.set_callback :dispatch, :before, :perform!
+ child = EmptyChild.new.dispatch
+ assert child.performed?
+ end
+end
diff --git a/activesupport/test/core_ext/blank_test.rb b/activesupport/test/core_ext/blank_test.rb
index 1dbbf3ff30..ed6c625a0a 100644
--- a/activesupport/test/core_ext/blank_test.rb
+++ b/activesupport/test/core_ext/blank_test.rb
@@ -14,12 +14,17 @@ class BlankTest < Test::Unit::TestCase
NOT = [ EmptyFalse.new, Object.new, true, 0, 1, 'a', [nil], { nil => 0 } ]
def test_blank
- BLANK.each { |v| assert v.blank?, "#{v.inspect} should be blank" }
+ BLANK.each { |v| assert v.blank?, "#{v.inspect} should be blank" }
NOT.each { |v| assert !v.blank?, "#{v.inspect} should not be blank" }
end
def test_present
BLANK.each { |v| assert !v.present?, "#{v.inspect} should not be present" }
- NOT.each { |v| assert v.present?, "#{v.inspect} should be present" }
+ NOT.each { |v| assert v.present?, "#{v.inspect} should be present" }
+ end
+
+ def test_presence
+ BLANK.each { |v| assert_equal nil, v.presence, "#{v.inspect}.presence should return nil" }
+ NOT.each { |v| assert_equal v, v.presence, "#{v.inspect}.presence should return self" }
end
end
diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb
index 4341ead488..278c05797b 100644
--- a/activesupport/test/core_ext/date_time_ext_test.rb
+++ b/activesupport/test/core_ext/date_time_ext_test.rb
@@ -350,6 +350,10 @@ class DateTimeExtCalculationsTest < Test::Unit::TestCase
assert_equal 946684800.0, DateTime.civil(1999,12,31,19,0,0,Rational(-5,24)).to_f
end
+ def test_to_i
+ assert_equal 946684800, DateTime.civil(2000).to_i
+ end
+
protected
def with_env_tz(new_tz = 'US/Eastern')
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb
index 66f5f9fbde..4650b796b6 100644
--- a/activesupport/test/core_ext/enumerable_test.rb
+++ b/activesupport/test/core_ext/enumerable_test.rb
@@ -89,4 +89,9 @@ class EnumerableTests < Test::Unit::TestCase
assert ![ 1, 2 ].many? {|x| x > 1 }
assert [ 1, 2, 2 ].many? {|x| x > 1 }
end
+
+ def test_exclude?
+ assert [ 1 ].exclude?(2)
+ assert ![ 1 ].exclude?(1)
+ end
end
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index 4642bb1330..5b1d53ac7b 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -902,9 +902,11 @@ class HashToXmlTest < Test::Unit::TestCase
def test_expansion_count_is_limited
expected = {
- 'ActiveSupport::XmlMini_REXML' => 'RuntimeError',
- 'ActiveSupport::XmlMini_Nokogiri' => 'Nokogiri::XML::SyntaxError',
- 'ActiveSupport::XmlMini_LibXML' => 'LibXML::XML::Error',
+ 'ActiveSupport::XmlMini_REXML' => 'RuntimeError',
+ 'ActiveSupport::XmlMini_Nokogiri' => 'Nokogiri::XML::SyntaxError',
+ 'ActiveSupport::XmlMini_NokogiriSAX' => 'RuntimeError',
+ 'ActiveSupport::XmlMini_LibXML' => 'LibXML::XML::Error',
+ 'ActiveSupport::XmlMini_LibXMLSAX' => 'LibXML::XML::Error',
}[ActiveSupport::XmlMini.backend.name].constantize
assert_raise expected do
diff --git a/activesupport/test/core_ext/integer_ext_test.rb b/activesupport/test/core_ext/integer_ext_test.rb
index e1591089f5..fe8c7eb224 100644
--- a/activesupport/test/core_ext/integer_ext_test.rb
+++ b/activesupport/test/core_ext/integer_ext_test.rb
@@ -5,6 +5,11 @@ class IntegerExtTest < Test::Unit::TestCase
def test_multiple_of
[ -7, 0, 7, 14 ].each { |i| assert i.multiple_of?(7) }
[ -7, 7, 14 ].each { |i| assert ! i.multiple_of?(6) }
+
+ # test the 0 edge case
+ assert 0.multiple_of?(0)
+ assert !5.multiple_of?(0)
+
# test with a prime
assert !22953686867719691230002707821868552601124472329079.multiple_of?(2)
assert !22953686867719691230002707821868552601124472329079.multiple_of?(3)
diff --git a/activesupport/test/core_ext/object/to_query_test.rb b/activesupport/test/core_ext/object/to_query_test.rb
index 0fb15be654..4d655913cc 100644
--- a/activesupport/test/core_ext/object/to_query_test.rb
+++ b/activesupport/test/core_ext/object/to_query_test.rb
@@ -17,22 +17,22 @@ class ToQueryTest < Test::Unit::TestCase
end
def test_nested_conversion
- assert_query_equal 'person%5Blogin%5D=seckar&person%5Bname%5D=Nicholas',
+ assert_query_equal 'person[login]=seckar&person[name]=Nicholas',
:person => {:name => 'Nicholas', :login => 'seckar'}
end
def test_multiple_nested
- assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10',
+ assert_query_equal 'account[person][id]=20&person[id]=10',
:person => {:id => 10}, :account => {:person => {:id => 20}}
end
def test_array_values
- assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20',
+ assert_query_equal 'person[id][]=10&person[id][]=20',
:person => {:id => [10, 20]}
end
def test_array_values_are_not_sorted
- assert_query_equal 'person%5Bid%5D%5B%5D=20&person%5Bid%5D%5B%5D=10',
+ assert_query_equal 'person[id][]=20&person[id][]=10',
:person => {:id => [20, 10]}
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 56ed296dac..9a805bc010 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -350,6 +350,24 @@ class OutputSafetyTest < ActiveSupport::TestCase
assert_equal @string, @string.html_safe!
end
+ test "A fixnum is safe by default" do
+ assert 5.html_safe?
+ end
+
+ test "An object is unsafe by default" do
+ klass = Class.new(Object) do
+ def to_str
+ "other"
+ end
+ end
+
+ @string.html_safe!
+ @string << klass.new
+
+ assert_equal "helloother", @string
+ assert !@string.html_safe?
+ end
+
test "Adding a safe string to another safe string returns a safe string" do
@other_string = "other".html_safe!
@string.html_safe!
@@ -416,4 +434,17 @@ class OutputSafetyTest < ActiveSupport::TestCase
@other_string << @string
assert @other_string.html_safe?
end
+
+ test "Concatting a fixnum to safe always yields safe" do
+ @string.html_safe!
+ @string.concat(13)
+ assert @string.html_safe?
+ end
+end
+
+class StringExcludeTest < ActiveSupport::TestCase
+ test 'inverse of #include' do
+ assert_equal false, 'foo'.exclude?('o')
+ assert_equal true, 'foo'.exclude?('p')
+ end
end
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index bb60968a4f..3a12100e86 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -284,6 +284,12 @@ class TimeWithZoneTest < Test::Unit::TestCase
assert_equal 946684800, result
assert result.is_a?(Integer)
end
+
+ def test_to_i_with_wrapped_datetime
+ datetime = DateTime.civil(2000, 1, 1, 0)
+ twz = ActiveSupport::TimeWithZone.new(datetime, @time_zone)
+ assert_equal 946684800, twz.to_i
+ end
def test_to_time
assert_equal @twz, @twz.to_time
diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb
index a3ae39d071..cf27357b32 100644
--- a/activesupport/test/deprecation_test.rb
+++ b/activesupport/test/deprecation_test.rb
@@ -62,7 +62,7 @@ class DeprecationTest < ActiveSupport::TestCase
end
def test_deprecate_class_method
- assert_deprecated(/none is deprecated.*test_deprecate_class_method at/) do
+ assert_deprecated(/none is deprecated.*test_deprecate_class_method/) do
assert_equal 1, @dtc.none
end
diff --git a/activesupport/test/fixtures/autoload/another_class.rb b/activesupport/test/fixtures/autoload/another_class.rb
new file mode 100644
index 0000000000..a240b3de41
--- /dev/null
+++ b/activesupport/test/fixtures/autoload/another_class.rb
@@ -0,0 +1,2 @@
+class Fixtures::AnotherClass
+end \ No newline at end of file
diff --git a/activesupport/test/fixtures/autoload/some_class.rb b/activesupport/test/fixtures/autoload/some_class.rb
new file mode 100644
index 0000000000..13b3c73ef5
--- /dev/null
+++ b/activesupport/test/fixtures/autoload/some_class.rb
@@ -0,0 +1,2 @@
+class Fixtures::Autoload::SomeClass
+end \ No newline at end of file
diff --git a/activesupport/test/isolation_test.rb b/activesupport/test/isolation_test.rb
index 20e11df1dd..a7af5e96f6 100644
--- a/activesupport/test/isolation_test.rb
+++ b/activesupport/test/isolation_test.rb
@@ -4,159 +4,179 @@ require 'rbconfig'
if defined?(MiniTest) || defined?(Test::Unit::TestResultFailureSupport)
$stderr.puts "Isolation tests can test test-unit 1 only"
-else
- # Does awesome
- if ENV['CHILD']
- class ChildIsolationTest < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
-
- def self.setup
- File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "a") do |f|
- f.puts "hello"
- end
- end
+elsif ENV['CHILD']
+ class ChildIsolationTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
- def setup
- @instance = "HELLO"
+ def self.setup
+ File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "a") do |f|
+ f.puts "hello"
end
+ end
- def teardown
- raise if @boom
- end
+ def setup
+ @instance = "HELLO"
+ end
- test "runs the test" do
- assert true
- end
+ def teardown
+ raise if @boom
+ end
- test "captures errors" do
- raise
- end
+ test "runs the test" do
+ assert true
+ end
- test "captures failures" do
- assert false
- end
+ test "captures errors" do
+ raise
+ end
- test "first runs in isolation" do
- assert_nil $x
- $x = 1
- end
+ test "captures failures" do
+ assert false
+ end
- test "second runs in isolation" do
- assert_nil $x
- $x = 2
- end
+ test "first runs in isolation" do
+ assert_nil $x
+ $x = 1
+ end
- test "runs with slow tests" do
- sleep 0.3
- assert true
- sleep 0.2
- end
+ test "second runs in isolation" do
+ assert_nil $x
+ $x = 2
+ end
- test "runs setup" do
- assert "HELLO", @instance
- end
+ test "runs with slow tests" do
+ sleep 0.3
+ assert true
+ sleep 0.2
+ end
- test "runs teardown" do
- @boom = true
- end
+ test "runs setup" do
+ assert "HELLO", @instance
+ end
- test "resets requires one" do
- assert !defined?(OmgOmg)
- assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size
- require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg"))
- end
+ test "runs teardown" do
+ @boom = true
+ end
- test "resets requires two" do
- assert !defined?(OmgOmg)
- assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size
- require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg"))
- end
+ test "resets requires one" do
+ assert !defined?(OmgOmg)
+ assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size
+ require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg"))
end
- else
- class ParentIsolationTest < ActiveSupport::TestCase
-
- File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "w") {}
-
- ENV["CHILD"] = "1"
- OUTPUT = `#{RbConfig::CONFIG["bindir"]}/#{RbConfig::CONFIG["ruby_install_name"]} -I#{File.dirname(__FILE__)} "#{File.expand_path(__FILE__)}" -v`
- ENV.delete("CHILD")
-
- def setup
- # Extract the results
- @results = {}
- OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result|
- result =~ %r'^(\w+)\(\w+\):\s*(\.|E|F)$'
- @results[$1] = { 'E' => :error, '.' => :success, 'F' => :failure }[$2]
- end
-
- # Extract the backtraces
- @backtraces = {}
- OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace|
- # \n 1) Error:\ntest_captures_errors(ChildIsolationTest):
- backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i
- @backtraces[$2] = { :type => $1, :output => backtrace }
- end
- end
- def assert_failing(name)
- assert_equal :failure, @results[name.to_s], "Test #{name} did not fail"
- end
+ test "resets requires two" do
+ assert !defined?(OmgOmg)
+ assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size
+ require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg"))
+ end
+ end
+else
+ class ParentIsolationTest < ActiveSupport::TestCase
- def assert_passing(name)
- assert_equal :success, @results[name.to_s], "Test #{name} did not pass"
- end
+ File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "w") {}
- def assert_erroring(name)
- assert_equal :error, @results[name.to_s], "Test #{name} did not error"
- end
+ ENV["CHILD"] = "1"
+ OUTPUT = `#{RbConfig::CONFIG["bindir"]}/#{RbConfig::CONFIG["ruby_install_name"]} -I#{File.dirname(__FILE__)} "#{File.expand_path(__FILE__)}" -v`
+ ENV.delete("CHILD")
- test "has all tests" do
- assert_equal 10, @results.length
- end
+ def setup
+ defined?(::MiniTest) ? parse_minitest : parse_testunit
+ end
- test "passing tests are still reported" do
- assert_passing :test_runs_the_test
- assert_passing :test_runs_with_slow_tests
+ def parse_testunit
+ @results = {}
+ OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result|
+ result =~ %r'^(\w+)\(\w+\):\s*(\.|E|F)$'
+ @results[$1] = { 'E' => :error, '.' => :success, 'F' => :failure }[$2]
end
- test "resets global variables" do
- assert_passing :test_first_runs_in_isolation
- assert_passing :test_second_runs_in_isolation
+ # Extract the backtraces
+ @backtraces = {}
+ OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace|
+ # \n 1) Error:\ntest_captures_errors(ChildIsolationTest):
+ backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i
+ @backtraces[$2] = { :type => $1, :output => backtrace }
end
+ end
- test "resets requires" do
- assert_passing :test_resets_requires_one
- assert_passing :test_resets_requires_two
- end
+ def parse_minitest
+ @results = {}
+ OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result|
+ result =~ %r'^\w+#(\w+):.*:\s*(.*Assertion.*|.*RuntimeError.*|\.\s*)$'
+ val = :success
+ val = :error if $2.include?('RuntimeError')
+ val = :failure if $2.include?('Assertion')
- test "erroring tests are still reported" do
- assert_erroring :test_captures_errors
+ @results[$1] = val
end
- test "runs setup and teardown methods" do
- assert_passing :test_runs_setup
- assert_erroring :test_runs_teardown
+ # Extract the backtraces
+ @backtraces = {}
+ OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace|
+ # \n 1) Error:\ntest_captures_errors(ChildIsolationTest):
+ backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i
+ @backtraces[$2] = { :type => $1, :output => backtrace }
end
+ end
- test "correct tests fail" do
- assert_failing :test_captures_failures
- end
+ def assert_failing(name)
+ assert_equal :failure, @results[name.to_s], "Test #{name} failed"
+ end
- test "backtrace is printed for errors" do
- assert_equal 'Error', @backtraces["test_captures_errors"][:type]
- assert_match %r{isolation_test.rb:\d+:in `test_captures_errors'}, @backtraces["test_captures_errors"][:output]
- end
+ def assert_passing(name)
+ assert_equal :success, @results[name.to_s], "Test #{name} passed"
+ end
- test "backtrace is printed for failures" do
- assert_equal 'Failure', @backtraces["test_captures_failures"][:type]
- assert_match %r{isolation_test.rb:\d+:in `test_captures_failures'}, @backtraces["test_captures_failures"][:output]
- end
+ def assert_erroring(name)
+ assert_equal :error, @results[name.to_s], "Test #{name} errored"
+ end
- test "self.setup is run only once" do
- text = File.read(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"))
- assert_equal "hello\n", text
- end
+ test "has all tests" do
+ assert_equal 10, @results.length
+ end
+
+ test "passing tests are still reported" do
+ assert_passing :test_runs_the_test
+ assert_passing :test_runs_with_slow_tests
+ end
+ test "resets global variables" do
+ assert_passing :test_first_runs_in_isolation
+ assert_passing :test_second_runs_in_isolation
end
+
+ test "resets requires" do
+ assert_passing :test_resets_requires_one
+ assert_passing :test_resets_requires_two
+ end
+
+ test "erroring tests are still reported" do
+ assert_erroring :test_captures_errors
+ end
+
+ test "runs setup and teardown methods" do
+ assert_passing :test_runs_setup
+ assert_erroring :test_runs_teardown
+ end
+
+ test "correct tests fail" do
+ assert_failing :test_captures_failures
+ end
+
+ test "backtrace is printed for errors" do
+ assert_equal 'Error', @backtraces["test_captures_errors"][:type]
+ assert_match %r{isolation_test.rb:\d+}, @backtraces["test_captures_errors"][:output]
+ end
+
+ test "backtrace is printed for failures" do
+ assert_equal 'Failure', @backtraces["test_captures_failures"][:type]
+ assert_match %r{isolation_test.rb:\d+}, @backtraces["test_captures_failures"][:output]
+ end
+
+ test "self.setup is run only once" do
+ text = File.read(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"))
+ assert_equal "hello\n", text
+ end
+
end
end
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index 5d81d09f03..cf9a635b5f 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -23,7 +23,9 @@ class TestJSONEncoding < Test::Unit::TestCase
StringTests = [[ 'this is the <string>', %("this is the \\u003Cstring\\u003E")],
[ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ],
- [ 'http://test.host/posts/1', %("http://test.host/posts/1")]]
+ [ 'http://test.host/posts/1', %("http://test.host/posts/1")],
+ [ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ %("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000B\\f\\r\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F") ]]
ArrayTests = [[ ['a', 'b', 'c'], %([\"a\",\"b\",\"c\"]) ],
[ [1, 'a', :b, nil, false], %([1,\"a\",\"b\",null,false]) ]]
diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb
index 01106e83e9..3ba77ae135 100644
--- a/activesupport/test/notifications_test.rb
+++ b/activesupport/test/notifications_test.rb
@@ -1,206 +1,168 @@
require 'abstract_unit'
-# Allow LittleFanout to be cleaned.
-class ActiveSupport::Notifications::LittleFanout
- def clear
- @listeners.clear
- end
-end
+module Notifications
+ class TestCase < ActiveSupport::TestCase
+ def setup
+ Thread.abort_on_exception = true
+
+ @notifier = ActiveSupport::Notifications::Notifier.new
+ @events = []
+ @notifier.subscribe { |*args| @events << event(*args) }
+ end
-class NotificationsEventTest < Test::Unit::TestCase
- def test_events_are_initialized_with_details
- event = event(:foo, Time.now, Time.now + 1, 1, random_id, :payload => :bar)
- assert_equal :foo, event.name
- assert_equal Hash[:payload => :bar], event.payload
- end
+ def teardown
+ Thread.abort_on_exception = false
+ end
- def test_events_consumes_information_given_as_payload
- time = Time.now
- event = event(:foo, time, time + 0.01, 1, random_id, {})
+ private
+ def event(*args)
+ ActiveSupport::Notifications::Event.new(*args)
+ end
- assert_equal Hash.new, event.payload
- assert_equal time, event.time
- assert_equal 1, event.result
- assert_equal 10.0, event.duration
+ def drain
+ @notifier.wait
+ end
end
- def test_event_is_parent_based_on_time_frame
- time = Time.utc(2009, 01, 01, 0, 0, 1)
+ class PubSubTest < TestCase
+ def test_events_are_published_to_a_listener
+ @notifier.publish :foo
+ @notifier.wait
+ assert_equal [[:foo]], @events
+ end
- parent = event(:foo, Time.utc(2009), Time.utc(2009) + 100, nil, random_id, {})
- child = event(:foo, time, time + 10, nil, random_id, {})
- not_child = event(:foo, time, time + 100, nil, random_id, {})
+ def test_subscriber_with_pattern
+ events = []
+ @notifier.subscribe('1') { |*args| events << args }
- assert parent.parent_of?(child)
- assert !child.parent_of?(parent)
- assert !parent.parent_of?(not_child)
- assert !not_child.parent_of?(parent)
- end
+ @notifier.publish '1'
+ @notifier.publish '1.a'
+ @notifier.publish 'a.1'
+ @notifier.wait
-protected
+ assert_equal [['1'], ['1.a']], events
+ end
- def random_id
- @random_id ||= ActiveSupport::SecureRandom.hex(10)
- end
+ def test_subscriber_with_pattern_as_regexp
+ events = []
+ @notifier.subscribe(/\d/) { |*args| events << args }
- def event(*args)
- ActiveSupport::Notifications::Event.new(*args)
- end
-end
+ @notifier.publish '1'
+ @notifier.publish 'a.1'
+ @notifier.publish '1.a'
+ @notifier.wait
-class NotificationsMainTest < Test::Unit::TestCase
- def setup
- @events = []
- Thread.abort_on_exception = true
- ActiveSupport::Notifications.subscribe do |*args|
- @events << ActiveSupport::Notifications::Event.new(*args)
+ assert_equal [['1'], ['a.1'], ['1.a']], events
end
- end
- def teardown
- Thread.abort_on_exception = false
- ActiveSupport::Notifications.queue.clear
- end
+ def test_multiple_subscribers
+ @another = []
+ @notifier.subscribe { |*args| @another << args }
+ @notifier.publish :foo
+ @notifier.wait
- def test_notifications_returns_action_result
- result = ActiveSupport::Notifications.instrument(:awesome, :payload => "notifications") do
- 1 + 1
+ assert_equal [[:foo]], @events
+ assert_equal [[:foo]], @another
end
- assert_equal 2, result
+ private
+ def event(*args)
+ args
+ end
end
- def test_events_are_published_to_a_listener
- ActiveSupport::Notifications.instrument(:awesome, :payload => "notifications") do
- 1 + 1
- end
+ class SyncPubSubTest < PubSubTest
+ def setup
+ Thread.abort_on_exception = true
- drain
-
- assert_equal 1, @events.size
- assert_equal :awesome, @events.last.name
- assert_equal Hash[:payload => "notifications"], @events.last.payload
+ @notifier = ActiveSupport::Notifications::Notifier.new(ActiveSupport::Notifications::Fanout.new(true))
+ @events = []
+ @notifier.subscribe { |*args| @events << event(*args) }
+ end
end
- def test_nested_events_can_be_instrumented
- ActiveSupport::Notifications.instrument(:awesome, :payload => "notifications") do
- ActiveSupport::Notifications.instrument(:wot, :payload => "child") do
- 1 + 1
- end
-
- drain
-
- assert_equal 1, @events.size
- assert_equal :wot, @events.first.name
- assert_equal Hash[:payload => "child"], @events.first.payload
+ class InstrumentationTest < TestCase
+ def test_instrument_returns_block_result
+ assert_equal 2, @notifier.instrument(:awesome) { 1 + 1 }
end
- drain
-
- assert_equal 2, @events.size
- assert_equal :awesome, @events.last.name
- assert_equal Hash[:payload => "notifications"], @events.last.payload
- end
-
- def test_event_is_pushed_even_if_block_fails
- ActiveSupport::Notifications.instrument(:awesome, :payload => "notifications") do
- raise "OMG"
- end rescue RuntimeError
+ def test_nested_events_can_be_instrumented
+ @notifier.instrument(:awesome, :payload => "notifications") do
+ @notifier.instrument(:wot, :payload => "child") do
+ 1 + 1
+ end
- drain
+ drain
- assert_equal 1, @events.size
- assert_equal :awesome, @events.last.name
- assert_equal Hash[:payload => "notifications"], @events.last.payload
- end
+ assert_equal 1, @events.size
+ assert_equal :wot, @events.first.name
+ assert_equal Hash[:payload => "child"], @events.first.payload
+ end
- def test_event_is_pushed_even_without_block
- ActiveSupport::Notifications.instrument(:awesome, :payload => "notifications")
- drain
+ drain
- assert_equal 1, @events.size
- assert_equal :awesome, @events.last.name
- assert_equal Hash[:payload => "notifications"], @events.last.payload
- end
+ assert_equal 2, @events.size
+ assert_equal :awesome, @events.last.name
+ assert_equal Hash[:payload => "notifications"], @events.last.payload
+ end
- def test_subscribed_in_a_transaction
- @another = []
+ def test_instrument_publishes_when_exception_is_raised
+ begin
+ @notifier.instrument(:awesome, :payload => "notifications") do
+ raise "OMG"
+ end
+ flunk
+ rescue
+ end
- ActiveSupport::Notifications.subscribe("cache") do |*args|
- @another << ActiveSupport::Notifications::Event.new(*args)
- end
+ drain
- ActiveSupport::Notifications.instrument(:cache){ 1 }
- ActiveSupport::Notifications.transaction do
- ActiveSupport::Notifications.instrument(:cache){ 1 }
+ assert_equal 1, @events.size
+ assert_equal :awesome, @events.last.name
+ assert_equal Hash[:payload => "notifications"], @events.last.payload
end
- ActiveSupport::Notifications.instrument(:cache){ 1 }
- drain
+ def test_event_is_pushed_even_without_block
+ @notifier.instrument(:awesome, :payload => "notifications")
+ drain
- assert_equal 3, @another.size
- before, during, after = @another.map {|e| e.transaction_id }
- assert_equal before, after
- assert_not_equal before, during
+ assert_equal 1, @events.size
+ assert_equal :awesome, @events.last.name
+ assert_equal Hash[:payload => "notifications"], @events.last.payload
+ end
end
- def test_subscriber_with_pattern
- @another = []
+ class EventTest < TestCase
+ def test_events_are_initialized_with_details
+ time = Time.now
+ event = event(:foo, time, time + 0.01, random_id, {})
- ActiveSupport::Notifications.subscribe("cache") do |*args|
- @another << ActiveSupport::Notifications::Event.new(*args)
+ assert_equal :foo, event.name
+ assert_equal time, event.time
+ assert_equal 10.0, event.duration
end
- ActiveSupport::Notifications.instrument(:cache){ 1 }
-
- drain
-
- assert_equal 1, @another.size
- assert_equal :cache, @another.first.name
- assert_equal 1, @another.first.result
- end
-
- def test_subscriber_with_pattern_as_regexp
- @another = []
- ActiveSupport::Notifications.subscribe(/cache/) do |*args|
- @another << ActiveSupport::Notifications::Event.new(*args)
+ def test_events_consumes_information_given_as_payload
+ event = event(:foo, Time.now, Time.now + 1, random_id, :payload => :bar)
+ assert_equal Hash[:payload => :bar], event.payload
end
- ActiveSupport::Notifications.instrument(:something){ 0 }
- ActiveSupport::Notifications.instrument(:cache){ 1 }
+ def test_event_is_parent_based_on_time_frame
+ time = Time.utc(2009, 01, 01, 0, 0, 1)
- drain
+ parent = event(:foo, Time.utc(2009), Time.utc(2009) + 100, random_id, {})
+ child = event(:foo, time, time + 10, random_id, {})
+ not_child = event(:foo, time, time + 100, random_id, {})
- assert_equal 1, @another.size
- assert_equal :cache, @another.first.name
- assert_equal 1, @another.first.result
- end
-
- def test_with_several_consumers_and_several_events
- @another = []
- ActiveSupport::Notifications.subscribe do |*args|
- @another << ActiveSupport::Notifications::Event.new(*args)
+ assert parent.parent_of?(child)
+ assert !child.parent_of?(parent)
+ assert !parent.parent_of?(not_child)
+ assert !not_child.parent_of?(parent)
end
- 1.upto(100) do |i|
- ActiveSupport::Notifications.instrument(:value){ i }
- end
-
- drain
-
- assert_equal 100, @events.size
- assert_equal :value, @events.first.name
- assert_equal 1, @events.first.result
- assert_equal 100, @events.last.result
-
- assert_equal 100, @another.size
- assert_equal :value, @another.first.name
- assert_equal 1, @another.first.result
- assert_equal 100, @another.last.result
+ protected
+ def random_id
+ @random_id ||= ActiveSupport::SecureRandom.hex(10)
+ end
end
-
- private
- def drain
- sleep(0.1) until ActiveSupport::Notifications.queue.drained?
- end
end
diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb
index 5cbffb81fc..1928da51ca 100644
--- a/activesupport/test/test_test.rb
+++ b/activesupport/test/test_test.rb
@@ -102,9 +102,9 @@ class SetupAndTeardownTest < ActiveSupport::TestCase
teardown :foo, :sentinel, :foo
def test_inherited_setup_callbacks
- assert_equal [:reset_callback_record, :foo], self.class.setup_callback_chain.map(&:method)
+ assert_equal [:reset_callback_record, :foo], self.class._setup_callbacks.map(&:raw_filter)
assert_equal [:foo], @called_back
- assert_equal [:foo, :sentinel, :foo], self.class.teardown_callback_chain.map(&:method)
+ assert_equal [:foo, :sentinel, :foo], self.class._teardown_callbacks.map(&:raw_filter)
end
def setup
@@ -114,6 +114,7 @@ class SetupAndTeardownTest < ActiveSupport::TestCase
end
protected
+
def reset_callback_record
@called_back = []
end
@@ -133,9 +134,9 @@ class SubclassSetupAndTeardownTest < SetupAndTeardownTest
teardown :bar
def test_inherited_setup_callbacks
- assert_equal [:reset_callback_record, :foo, :bar], self.class.setup_callback_chain.map(&:method)
+ assert_equal [:reset_callback_record, :foo, :bar], self.class._setup_callbacks.map(&:raw_filter)
assert_equal [:foo, :bar], @called_back
- assert_equal [:foo, :sentinel, :foo, :bar], self.class.teardown_callback_chain.map(&:method)
+ assert_equal [:foo, :sentinel, :foo, :bar], self.class._teardown_callbacks.map(&:raw_filter)
end
protected
diff --git a/activesupport/test/whiny_nil_test.rb b/activesupport/test/whiny_nil_test.rb
index 009d97940f..1e4f8d854a 100644
--- a/activesupport/test/whiny_nil_test.rb
+++ b/activesupport/test/whiny_nil_test.rb
@@ -13,38 +13,39 @@ class WhinyNilTest < Test::Unit::TestCase
def test_unchanged
nil.method_thats_not_in_whiners
rescue NoMethodError => nme
- assert(nme.message =~ /nil:NilClass/)
+ assert_match(/nil:NilClass/, nme.message)
end
def test_active_record
nil.save!
rescue NoMethodError => nme
- assert(!(nme.message =~ /nil:NilClass/))
+ assert_no_match(/nil:NilClass/, nme.message)
assert_match(/nil\.save!/, nme.message)
end
def test_array
nil.each
rescue NoMethodError => nme
- assert(!(nme.message =~ /nil:NilClass/))
+ assert_no_match(/nil:NilClass/, nme.message)
assert_match(/nil\.each/, nme.message)
end
def test_id
nil.id
rescue RuntimeError => nme
- assert(!(nme.message =~ /nil:NilClass/))
+ assert_no_match(/nil:NilClass/, nme.message)
end
def test_no_to_ary_coercion
nil.to_ary
rescue NoMethodError => nme
- assert(nme.message =~ /nil:NilClass/)
+ assert_no_match(/nil:NilClass/, nme.message)
+ assert_match(/nil\.to_ary/, nme.message)
end
def test_no_to_str_coercion
nil.to_str
rescue NoMethodError => nme
- assert(nme.message =~ /nil:NilClass/)
+ assert_match(/nil:NilClass/, nme.message)
end
end
diff --git a/activesupport/test/xml_mini/libxml_engine_test.rb b/activesupport/test/xml_mini/libxml_engine_test.rb
index 900c8052d6..83d03bccc6 100644
--- a/activesupport/test/xml_mini/libxml_engine_test.rb
+++ b/activesupport/test/xml_mini/libxml_engine_test.rb
@@ -184,6 +184,15 @@ class LibxmlEngineTest < Test::Unit::TestCase
eoxml
end
+ def test_children_with_blank_text_and_attribute
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products type="file"> </products>
+ </root>
+ eoxml
+ end
+
+
private
def assert_equal_rexml(xml)
hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
diff --git a/activesupport/test/xml_mini/libxmlsax_engine_test.rb b/activesupport/test/xml_mini/libxmlsax_engine_test.rb
new file mode 100644
index 0000000000..864810099e
--- /dev/null
+++ b/activesupport/test/xml_mini/libxmlsax_engine_test.rb
@@ -0,0 +1,194 @@
+require 'abstract_unit'
+require 'active_support/xml_mini'
+require 'active_support/core_ext/hash/conversions'
+
+begin
+ require 'libxml'
+rescue LoadError
+ # Skip libxml tests
+else
+
+class LibXMLSAXEngineTest < Test::Unit::TestCase
+ include ActiveSupport
+
+ def setup
+ @default_backend = XmlMini.backend
+ XmlMini.backend = 'LibXMLSAX'
+ end
+
+ def teardown
+ XmlMini.backend = @default_backend
+ end
+
+ def test_exception_thrown_on_expansion_attack
+ assert_raise LibXML::XML::Error do
+ attack_xml = <<-EOT
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE member [
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
+ ]>
+ <member>
+ &a;
+ </member>
+ EOT
+
+ Hash.from_xml(attack_xml)
+ end
+ end
+
+ def test_setting_libxml_as_backend
+ XmlMini.backend = 'LibXMLSAX'
+ assert_equal XmlMini_LibXMLSAX, XmlMini.backend
+ end
+
+ def test_blank_returns_empty_hash
+ assert_equal({}, XmlMini.parse(nil))
+ assert_equal({}, XmlMini.parse(''))
+ end
+
+ def test_array_type_makes_an_array
+ assert_equal_rexml(<<-eoxml)
+ <blog>
+ <posts type="array">
+ <post>a post</post>
+ <post>another post</post>
+ </posts>
+ </blog>
+ eoxml
+ end
+
+ def test_one_node_document_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products/>
+ eoxml
+ end
+
+ def test_one_node_with_attributes_document_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products foo="bar"/>
+ eoxml
+ end
+
+ def test_products_node_with_book_node_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products>
+ <book name="awesome" id="12345" />
+ </products>
+ eoxml
+ end
+
+ def test_products_node_with_two_book_nodes_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products>
+ <book name="awesome" id="12345" />
+ <book name="america" id="67890" />
+ </products>
+ eoxml
+ end
+
+ def test_single_node_with_content_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products>
+ hello world
+ </products>
+ eoxml
+ end
+
+ def test_children_with_children
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ <book name="america" id="67890" />
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_text
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ hello everyone
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_non_adjacent_text
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ good
+ <products>
+ hello everyone
+ </products>
+ morning
+ </root>
+ eoxml
+ end
+
+ def test_parse_from_io
+ io = StringIO.new(<<-eoxml)
+ <root>
+ good
+ <products>
+ hello everyone
+ </products>
+ morning
+ </root>
+ eoxml
+ XmlMini.parse(io)
+ end
+
+ def test_children_with_simple_cdata
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ <![CDATA[cdatablock]]>
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_multiple_cdata
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_text_and_cdata
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ hello <![CDATA[cdatablock]]>
+ morning
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_blank_text
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products> </products>
+ </root>
+ eoxml
+ end
+
+ private
+ def assert_equal_rexml(xml)
+ hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
+ assert_equal(hash, XmlMini.parse(xml))
+ end
+end
+
+end
diff --git a/activesupport/test/xml_mini/nokogiri_engine_test.rb b/activesupport/test/xml_mini/nokogiri_engine_test.rb
index e16f36acee..db0d7c5b02 100644
--- a/activesupport/test/xml_mini/nokogiri_engine_test.rb
+++ b/activesupport/test/xml_mini/nokogiri_engine_test.rb
@@ -159,17 +159,53 @@ class NokogiriEngineTest < Test::Unit::TestCase
XmlMini.parse(io)
end
- def test_children_with_cdata
+ def test_children_with_simple_cdata
assert_equal_rexml(<<-eoxml)
<root>
<products>
- hello <![CDATA[everyone]]>
+ <![CDATA[cdatablock]]>
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_multiple_cdata
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_text_and_cdata
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ hello <![CDATA[cdatablock]]>
morning
</products>
</root>
eoxml
end
+ def test_children_with_blank_text
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products> </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_blank_text_and_attribute
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products type="file"> </products>
+ </root>
+ eoxml
+ end
+
private
def assert_equal_rexml(xml)
hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
diff --git a/activesupport/test/xml_mini/nokogirisax_engine_test.rb b/activesupport/test/xml_mini/nokogirisax_engine_test.rb
new file mode 100644
index 0000000000..1149d0fecc
--- /dev/null
+++ b/activesupport/test/xml_mini/nokogirisax_engine_test.rb
@@ -0,0 +1,217 @@
+require 'abstract_unit'
+require 'active_support/xml_mini'
+require 'active_support/core_ext/hash/conversions'
+
+begin
+ require 'nokogiri'
+rescue LoadError
+ # Skip nokogiri tests
+else
+
+class NokogiriSAXEngineTest < Test::Unit::TestCase
+ include ActiveSupport
+
+ def setup
+ @default_backend = XmlMini.backend
+ XmlMini.backend = 'NokogiriSAX'
+ end
+
+ def teardown
+ XmlMini.backend = @default_backend
+ end
+
+ def test_file_from_xml
+ hash = Hash.from_xml(<<-eoxml)
+ <blog>
+ <logo type="file" name="logo.png" content_type="image/png">
+ </logo>
+ </blog>
+ eoxml
+ assert hash.has_key?('blog')
+ assert hash['blog'].has_key?('logo')
+
+ file = hash['blog']['logo']
+ assert_equal 'logo.png', file.original_filename
+ assert_equal 'image/png', file.content_type
+ end
+
+ def test_exception_thrown_on_expansion_attack
+ assert_raise RuntimeError do
+ attack_xml = <<-EOT
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE member [
+ <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
+ <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
+ <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
+ <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
+ <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
+ <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
+ <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
+ ]>
+ <member>
+ &a;
+ </member>
+ EOT
+
+ Hash.from_xml(attack_xml)
+ end
+ end
+
+ def test_setting_nokogiri_as_backend
+ XmlMini.backend = 'Nokogiri'
+ assert_equal XmlMini_Nokogiri, XmlMini.backend
+ end
+
+ def test_blank_returns_empty_hash
+ assert_equal({}, XmlMini.parse(nil))
+ assert_equal({}, XmlMini.parse(''))
+ end
+
+ def test_array_type_makes_an_array
+ assert_equal_rexml(<<-eoxml)
+ <blog>
+ <posts type="array">
+ <post>a post</post>
+ <post>another post</post>
+ </posts>
+ </blog>
+ eoxml
+ end
+
+ def test_one_node_document_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products/>
+ eoxml
+ end
+
+ def test_one_node_with_attributes_document_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products foo="bar"/>
+ eoxml
+ end
+
+ def test_products_node_with_book_node_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products>
+ <book name="awesome" id="12345" />
+ </products>
+ eoxml
+ end
+
+ def test_products_node_with_two_book_nodes_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products>
+ <book name="awesome" id="12345" />
+ <book name="america" id="67890" />
+ </products>
+ eoxml
+ end
+
+ def test_single_node_with_content_as_hash
+ assert_equal_rexml(<<-eoxml)
+ <products>
+ hello world
+ </products>
+ eoxml
+ end
+
+ def test_children_with_children
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ <book name="america" id="67890" />
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_text
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ hello everyone
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_non_adjacent_text
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ good
+ <products>
+ hello everyone
+ </products>
+ morning
+ </root>
+ eoxml
+ end
+
+ def test_parse_from_io
+ io = StringIO.new(<<-eoxml)
+ <root>
+ good
+ <products>
+ hello everyone
+ </products>
+ morning
+ </root>
+ eoxml
+ XmlMini.parse(io)
+ end
+
+ def test_children_with_simple_cdata
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ <![CDATA[cdatablock]]>
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_multiple_cdata
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ <![CDATA[cdatablock1]]><![CDATA[cdatablock2]]>
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_text_and_cdata
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products>
+ hello <![CDATA[cdatablock]]>
+ morning
+ </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_blank_text
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products> </products>
+ </root>
+ eoxml
+ end
+
+ def test_children_with_blank_text_and_attribute
+ assert_equal_rexml(<<-eoxml)
+ <root>
+ <products type="file"> </products>
+ </root>
+ eoxml
+ end
+
+ private
+ def assert_equal_rexml(xml)
+ hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) }
+ assert_equal(hash, XmlMini.parse(xml))
+ end
+end
+
+end