[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:254

From: ko1 atdot.net
Date: 14 Feb 2006 09:20:57 -0000
Subject: [yarv-diff:254] r417 - in trunk: . lib test test/pathname test/scanf test/socket test/stringio test/uri

Author: ko1
Date: 2006-02-14 18:20:57 +0900 (Tue, 14 Feb 2006)
New Revision: 417

Added:
   trunk/lib/thread.rb
   trunk/test/pathname/
   trunk/test/pathname/test_pathname.rb
   trunk/test/scanf/
   trunk/test/scanf/data.txt
   trunk/test/scanf/test_scanf.rb
   trunk/test/scanf/test_scanfblocks.rb
   trunk/test/scanf/test_scanfio.rb
   trunk/test/socket/
   trunk/test/socket/test_socket.rb
   trunk/test/socket/test_tcp.rb
   trunk/test/socket/test_udp.rb
   trunk/test/socket/test_unix.rb
   trunk/test/stringio/
   trunk/test/stringio/test_stringio.rb
   trunk/test/uri/
   trunk/test/uri/test_common.rb
   trunk/test/uri/test_ftp.rb
   trunk/test/uri/test_generic.rb
   trunk/test/uri/test_http.rb
   trunk/test/uri/test_ldap.rb
   trunk/test/uri/test_mailto.rb
Modified:
   trunk/
   trunk/ChangeLog
   trunk/eval.c
   trunk/eval_proc.c
   trunk/test.rb
   trunk/yarvcore.c
Log:
 r624@lermite:  ko1 | 2006-02-14 16:41:50 +0900
 	* yarvcore.c, eval_proc.c : fix rb_proc_arity
 
 	* eval.c : declare funcall same as send (temporarily)
 
 	* lib/thread.rb : added
 
 	* test/pathname/test_pathname.rb : imported from ruby 1.9
 
 	* test/scanf/data.txt : ditto
 
 	* test/scanf/test_scanf.rb : ditto
 
 	* test/scanf/test_scanfblocks.rb : ditto
 
 	* test/scanf/test_scanfio.rb : ditto
 
 	* test/socket/test_socket.rb : ditto
 
 	* test/socket/test_tcp.rb : ditto
 
 	* test/socket/test_udp.rb : ditto
 
 	* test/socket/test_unix.rb : ditto
 
 	* test/stringio/test_stringio.rb : ditto
 
 	* test/uri/test_common.rb : ditto
 
 	* test/uri/test_ftp.rb : ditto
 
 	* test/uri/test_generic.rb : ditto
 
 	* test/uri/test_http.rb : ditto
 
 	* test/uri/test_ldap.rb : ditto
 
 	* test/uri/test_mailto.rb : ditto
 



Property changes on: trunk
___________________________________________________________________
Name: svk:merge
   - 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:623
   + 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:624

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/ChangeLog	2006-02-14 09:20:57 UTC (rev 417)
@@ -4,6 +4,47 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-02-14(Tue) 16:40:01 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* yarvcore.c, eval_proc.c : fix rb_proc_arity
+
+	* eval.c : declare funcall same as send (temporarily)
+
+	* lib/thread.rb : added
+
+	* test/pathname/test_pathname.rb : imported from ruby 1.9
+
+	* test/scanf/data.txt : ditto
+
+	* test/scanf/test_scanf.rb : ditto
+
+	* test/scanf/test_scanfblocks.rb : ditto
+
+	* test/scanf/test_scanfio.rb : ditto
+
+	* test/socket/test_socket.rb : ditto
+
+	* test/socket/test_tcp.rb : ditto
+
+	* test/socket/test_udp.rb : ditto
+
+	* test/socket/test_unix.rb : ditto
+
+	* test/stringio/test_stringio.rb : ditto
+
+	* test/uri/test_common.rb : ditto
+
+	* test/uri/test_ftp.rb : ditto
+
+	* test/uri/test_generic.rb : ditto
+
+	* test/uri/test_http.rb : ditto
+
+	* test/uri/test_ldap.rb : ditto
+
+	* test/uri/test_mailto.rb : ditto
+
+
 2006-02-14(Tue) 15:59:28 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* thread.c : Change Thread.critical warnning message

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/eval.c	2006-02-14 09:20:57 UTC (rev 417)
@@ -2841,6 +2841,8 @@
     rb_define_global_function("local_variables", rb_f_local_variables, 0);
 
     rb_define_method(rb_mKernel, "send", rb_f_send, -1);
+    rb_define_method(rb_mKernel, "funcall", rb_f_send, -1); /* temporarily */
+    
     rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
     rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
 

Modified: trunk/eval_proc.c
===================================================================
--- trunk/eval_proc.c	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/eval_proc.c	2006-02-14 09:20:57 UTC (rev 417)
@@ -258,19 +258,11 @@
  */
 
 VALUE
-rb_proc_call(proc, args)
-    VALUE proc, args;		/* OK */
+rb_proc_call(VALUE proc, VALUE args)
 {
     return proc_invoke(proc, args, Qundef, 0);
 }
 
-int
-rb_proc_arity(proc)
-    VALUE proc;
-{
-    UNSUPPORTED(rb_proc_arity);
-}
-
 /*
  *  call-seq:
  *     prc.arity -> fixnum

Added: trunk/lib/thread.rb
===================================================================
--- trunk/lib/thread.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/lib/thread.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,352 @@
+#
+#		thread.rb - thread support classes
+#			$Date: 2005/12/29 12:03:55 $
+#			by Yukihiro Matsumoto <matz netlab.co.jp>
+#
+# Copyright (C) 2001  Yukihiro Matsumoto
+# Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
+# Copyright (C) 2000  Information-technology Promotion Agency, Japan
+#
+
+unless defined? Thread
+  raise "Thread not available for this ruby interpreter"
+end
+
+unless defined? ThreadError
+  class ThreadError<StandardError
+  end
+end
+
+if $DEBUG
+  Thread.abort_on_exception = true
+end
+
+# 
+# ConditionVariable objects augment class Mutex. Using condition variables,
+# it is possible to suspend while in the middle of a critical section until a
+# resource becomes available.
+#
+# Example:
+#
+#   require 'thread'
+#
+#   mutex = Mutex.new
+#   resource = ConditionVariable.new
+#   
+#   a = Thread.new {
+#     mutex.synchronize {
+#       # Thread 'a' now needs the resource
+#       resource.wait(mutex)
+#       # 'a' can now have the resource
+#     }
+#   }
+#   
+#   b = Thread.new {
+#     mutex.synchronize {
+#       # Thread 'b' has finished using the resource
+#       resource.signal
+#     }
+#   }
+#
+class ConditionVariable
+  #
+  # Creates a new ConditionVariable
+  #
+  def initialize
+    @waiters = []
+  end
+  
+  #
+  # Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
+  #
+  def wait(mutex)
+    begin
+      # TODO: mutex should not be used
+      @waiters.push(Thread.current)
+      mutex.unlock_and_stop
+    ensure
+      mutex.lock
+    end
+  end
+  
+  #
+  # Wakes up the first thread in line waiting for this lock.
+  #
+  def signal
+    begin
+      t = @waiters.shift
+      t.run if t
+    rescue ThreadError
+      retry
+    end
+  end
+    
+  #
+  # Wakes up all threads waiting for this lock.
+  #
+  def broadcast
+    # TODO: imcomplete
+    waiters0 = nil
+    Thread.exclusive do
+      waiters0 = @waiters.dup
+      @waiters.clear
+    end
+    for t in waiters0
+      begin
+	t.run
+      rescue ThreadError
+      end
+    end
+  end
+end
+
+#
+# This class provides a way to synchronize communication between threads.
+#
+# Example:
+#
+#   require 'thread'
+#   
+#   queue = Queue.new
+#   
+#   producer = Thread.new do
+#     5.times do |i|
+#       sleep rand(i) # simulate expense
+#       queue << i
+#       puts "#{i} produced"
+#     end
+#   end
+#   
+#   consumer = Thread.new do
+#     5.times do |i|
+#       value = queue.pop
+#       sleep rand(i/2) # simulate expense
+#       puts "consumed #{value}"
+#     end
+#   end
+#   
+#   consumer.join
+#
+class Queue
+  #
+  # Creates a new queue.
+  #
+  def initialize
+    @que = []
+    @waiting = []
+    @que.taint		# enable tainted comunication
+    @waiting.taint
+    self.taint
+    @mutex = Mutex.new
+  end
+
+  #
+  # Pushes +obj+ to the queue.
+  #
+  def push(obj)
+    t = nil
+    @mutex.synchronize{
+      @que.push obj
+      begin
+        t = @waiting.shift
+        t.wakeup if t
+      rescue ThreadError
+        retry
+      end
+    }
+    begin
+      t.run if t
+    rescue ThreadError
+    end
+  end
+
+  #
+  # Alias of push
+  #
+  alias << push
+
+  #
+  # Alias of push
+  #
+  alias enq push
+
+  #
+  # Retrieves data from the queue.  If the queue is empty, the calling thread is
+  # suspended until data is pushed onto the queue.  If +non_block+ is true, the
+  # thread isn't suspended, and an exception is raised.
+  #
+  def pop(non_block=false)
+    raise ThreadError, "queue empty" if non_block
+    while true
+      @mutex.synchronize{
+        if @que.empty?
+          @waiting.push Thread.current
+          @mutex.unlock_and_stop
+          @mutex.lock
+        else
+          return @que.shift
+        end
+      }
+    end
+  end
+
+  #
+  # Alias of pop
+  #
+  alias shift pop
+
+  #
+  # Alias of pop
+  #
+  alias deq pop
+
+  #
+  # Returns +true+ is the queue is empty.
+  #
+  def empty?
+    @que.empty?
+  end
+
+  #
+  # Removes all objects from the queue.
+  #
+  def clear
+    @que.clear
+  end
+
+  #
+  # Returns the length of the queue.
+  #
+  def length
+    @que.length
+  end
+
+  #
+  # Alias of length.
+  #
+  alias size length
+
+  #
+  # Returns the number of threads waiting on the queue.
+  #
+  def num_waiting
+    @waiting.size
+  end
+end
+
+#
+# This class represents queues of specified size capacity.  The push operation
+# may be blocked if the capacity is full.
+#
+# See Queue for an example of how a SizedQueue works.
+#
+class SizedQueue<Queue
+  #
+  # Creates a fixed-length queue with a maximum size of +max+.
+  #
+  def initialize(max)
+    raise ArgumentError, "queue size must be positive" unless max > 0
+    @max = max
+    @queue_wait = []
+    @queue_wait.taint		# enable tainted comunication
+    super()
+  end
+
+  #
+  # Returns the maximum size of the queue.
+  #
+  def max
+    @max
+  end
+
+  #
+  # Sets the maximum size of the queue.
+  #
+  def max=(max)
+    Thread.critical = true
+    if max <= @max
+      @max = max
+      Thread.critical = false
+    else
+      diff = max - @max
+      @max = max
+      Thread.critical = false
+      diff.times do
+	begin
+	  t = @queue_wait.shift
+	  t.run if t
+	rescue ThreadError
+	  retry
+	end
+      end
+    end
+    max
+  end
+
+  #
+  # Pushes +obj+ to the queue.  If there is no space left in the queue, waits
+  # until space becomes available.
+  #
+  def push(obj)
+    Thread.critical = true
+    while @que.length >= @max
+      @queue_wait.push Thread.current
+      Thread.stop
+      Thread.critical = true
+    end
+    super
+  end
+
+  #
+  # Alias of push
+  #
+  alias << push
+
+  #
+  # Alias of push
+  #
+  alias enq push
+
+  #
+  # Retrieves data from the queue and runs a waiting thread, if any.
+  #
+  def pop(*args)
+    retval = super
+    Thread.critical = true
+    if @que.length < @max
+      begin
+	t = @queue_wait.shift
+	t.wakeup if t
+      rescue ThreadError
+	retry
+      ensure
+	Thread.critical = false
+      end
+      begin
+	t.run if t
+      rescue ThreadError
+      end
+    end
+    retval
+  end
+
+  #
+  # Alias of pop
+  #
+  alias shift pop
+
+  #
+  # Alias of pop
+  #
+  alias deq pop
+
+  #
+  # Returns the number of threads waiting on the queue.
+  #
+  def num_waiting
+    @waiting.size + @queue_wait.size
+  end
+end
+
+# Documentation comments:
+#  - How do you make RDoc inherit documentation from superclass?

Added: trunk/test/pathname/test_pathname.rb
===================================================================
--- trunk/test/pathname/test_pathname.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/pathname/test_pathname.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,461 @@
+#!/usr/bin/env ruby
+
+require 'test/unit'
+require 'pathname'
+
+require 'fileutils'
+require 'tmpdir'
+
+class TestPathname < Test::Unit::TestCase
+  def self.define_assertion(name, &block)
+    @defassert_num ||= {}
+    @defassert_num[name] ||= 0
+    @defassert_num[name] += 1
+    define_method("test_#{name}_#{@defassert_num[name]}", &block)
+  end
+
+  def self.defassert(name, result, *args)
+    define_assertion(name) {
+      assert_equal(result, self.send(name, *args), "#{name}(#{args.map {|a| a.inspect }.join(', ')})")
+    }
+  end
+
+  DOSISH = File::ALT_SEPARATOR != nil
+  DOSISH_DRIVE_LETTER = File.dirname("A:") == "A:."
+  DOSISH_UNC = File.dirname("//") == "//"
+
+  def cleanpath_aggressive(path)
+    Pathname.new(path).cleanpath.to_s
+  end
+
+  defassert(:cleanpath_aggressive, '/',       '/')
+  defassert(:cleanpath_aggressive, '.',       '')
+  defassert(:cleanpath_aggressive, '.',       '.')
+  defassert(:cleanpath_aggressive, '..',      '..')
+  defassert(:cleanpath_aggressive, 'a',       'a')
+  defassert(:cleanpath_aggressive, '/',       '/.')
+  defassert(:cleanpath_aggressive, '/',       '/..')
+  defassert(:cleanpath_aggressive, '/a',      '/a')
+  defassert(:cleanpath_aggressive, '.',       './')
+  defassert(:cleanpath_aggressive, '..',      '../')
+  defassert(:cleanpath_aggressive, 'a',       'a/')
+  defassert(:cleanpath_aggressive, 'a/b',     'a//b')
+  defassert(:cleanpath_aggressive, 'a',       'a/.')
+  defassert(:cleanpath_aggressive, 'a',       'a/./')
+  defassert(:cleanpath_aggressive, '.',       'a/..')
+  defassert(:cleanpath_aggressive, '.',       'a/../')
+  defassert(:cleanpath_aggressive, '/a',      '/a/.')
+  defassert(:cleanpath_aggressive, '..',      './..')
+  defassert(:cleanpath_aggressive, '..',      '../.')
+  defassert(:cleanpath_aggressive, '..',      './../')
+  defassert(:cleanpath_aggressive, '..',      '.././')
+  defassert(:cleanpath_aggressive, '/',       '/./..')
+  defassert(:cleanpath_aggressive, '/',       '/../.')
+  defassert(:cleanpath_aggressive, '/',       '/./../')
+  defassert(:cleanpath_aggressive, '/',       '/.././')
+  defassert(:cleanpath_aggressive, 'a/b/c',   'a/b/c')
+  defassert(:cleanpath_aggressive, 'b/c',     './b/c')
+  defassert(:cleanpath_aggressive, 'a/c',     'a/./c')
+  defassert(:cleanpath_aggressive, 'a/b',     'a/b/.')
+  defassert(:cleanpath_aggressive, '.',       'a/../.')
+  defassert(:cleanpath_aggressive, '/a',      '/../.././../a')
+  defassert(:cleanpath_aggressive, '../../d', 'a/b/../../../../c/../d')
+
+  if DOSISH_UNC
+    defassert(:cleanpath_aggressive, '//a/b/c', '//a/b/c/')
+  else
+    defassert(:cleanpath_aggressive, '/',       '///')
+    defassert(:cleanpath_aggressive, '/a',      '///a')
+    defassert(:cleanpath_aggressive, '/',       '///..')
+    defassert(:cleanpath_aggressive, '/',       '///.')
+    defassert(:cleanpath_aggressive, '/',       '///a/../..')
+  end
+
+  def cleanpath_conservative(path)
+    Pathname.new(path).cleanpath(true).to_s
+  end
+
+  defassert(:cleanpath_conservative, '/',      '/')
+  defassert(:cleanpath_conservative, '.',      '')
+  defassert(:cleanpath_conservative, '.',      '.')
+  defassert(:cleanpath_conservative, '..',     '..')
+  defassert(:cleanpath_conservative, 'a',      'a')
+  defassert(:cleanpath_conservative, '/',      '/.')
+  defassert(:cleanpath_conservative, '/',      '/..')
+  defassert(:cleanpath_conservative, '/a',     '/a')
+  defassert(:cleanpath_conservative, '.',      './')
+  defassert(:cleanpath_conservative, '..',     '../')
+  defassert(:cleanpath_conservative, 'a/',     'a/')
+  defassert(:cleanpath_conservative, 'a/b',    'a//b')
+  defassert(:cleanpath_conservative, 'a/.',    'a/.')
+  defassert(:cleanpath_conservative, 'a/.',    'a/./')
+  defassert(:cleanpath_conservative, 'a/..',   'a/../')
+  defassert(:cleanpath_conservative, '/a/.',   '/a/.')
+  defassert(:cleanpath_conservative, '..',     './..')
+  defassert(:cleanpath_conservative, '..',     '../.')
+  defassert(:cleanpath_conservative, '..',     './../')
+  defassert(:cleanpath_conservative, '..',     '.././')
+  defassert(:cleanpath_conservative, '/',      '/./..')
+  defassert(:cleanpath_conservative, '/',      '/../.')
+  defassert(:cleanpath_conservative, '/',      '/./../')
+  defassert(:cleanpath_conservative, '/',      '/.././')
+  defassert(:cleanpath_conservative, 'a/b/c',  'a/b/c')
+  defassert(:cleanpath_conservative, 'b/c',    './b/c')
+  defassert(:cleanpath_conservative, 'a/c',    'a/./c')
+  defassert(:cleanpath_conservative, 'a/b/.',  'a/b/.')
+  defassert(:cleanpath_conservative, 'a/..',   'a/../.')
+  defassert(:cleanpath_conservative, '/a',     '/../.././../a')
+  defassert(:cleanpath_conservative, 'a/b/../../../../c/../d', 'a/b/../../../../c/../d')
+
+  if DOSISH_UNC
+    defassert(:cleanpath_conservative, '//',     '//')
+  else
+    defassert(:cleanpath_conservative, '/',      '//')
+  end
+
+  # has_trailing_separator?(path) -> bool
+  def has_trailing_separator?(path)
+    Pathname.allocate.funcall(:has_trailing_separator?, path)
+  end
+
+  defassert(:has_trailing_separator?, false, "/")
+  defassert(:has_trailing_separator?, false, "///")
+  defassert(:has_trailing_separator?, false, "a")
+  defassert(:has_trailing_separator?, true, "a/")
+
+  def add_trailing_separator(path)
+    Pathname.allocate.funcall(:add_trailing_separator, path)
+  end
+
+  def del_trailing_separator(path)
+    Pathname.allocate.funcall(:del_trailing_separator, path)
+  end
+
+  defassert(:del_trailing_separator, "/", "/")
+  defassert(:del_trailing_separator, "/a", "/a")
+  defassert(:del_trailing_separator, "/a", "/a/")
+  defassert(:del_trailing_separator, "/a", "/a//")
+  defassert(:del_trailing_separator, ".", ".")
+  defassert(:del_trailing_separator, ".", "./")
+  defassert(:del_trailing_separator, ".", ".//")
+
+  if DOSISH_DRIVE_LETTER
+    defassert(:del_trailing_separator, "A:", "A:")
+    defassert(:del_trailing_separator, "A:/", "A:/")
+    defassert(:del_trailing_separator, "A:/", "A://")
+    defassert(:del_trailing_separator, "A:.", "A:.")
+    defassert(:del_trailing_separator, "A:.", "A:./")
+    defassert(:del_trailing_separator, "A:.", "A:.//")
+  end
+
+  if DOSISH_UNC
+    defassert(:del_trailing_separator, "//", "//")
+    defassert(:del_trailing_separator, "//a", "//a")
+    defassert(:del_trailing_separator, "//a", "//a/")
+    defassert(:del_trailing_separator, "//a", "//a//")
+    defassert(:del_trailing_separator, "//a/b", "//a/b")
+    defassert(:del_trailing_separator, "//a/b", "//a/b/")
+    defassert(:del_trailing_separator, "//a/b", "//a/b//")
+    defassert(:del_trailing_separator, "//a/b/c", "//a/b/c")
+    defassert(:del_trailing_separator, "//a/b/c", "//a/b/c/")
+    defassert(:del_trailing_separator, "//a/b/c", "//a/b/c//")
+  else
+    defassert(:del_trailing_separator, "/", "///")
+    defassert(:del_trailing_separator, "///a", "///a/")
+  end
+
+  if DOSISH
+    defassert(:del_trailing_separator, "a", "a\\")
+    defassert(:del_trailing_separator, "\225\\", "\225\\\\") # SJIS
+  end
+
+  def plus(path1, path2) # -> path
+    (Pathname.new(path1) + Pathname.new(path2)).to_s
+  end
+
+  defassert(:plus, '/', '/', '/')
+  defassert(:plus, 'a/b', 'a', 'b')
+  defassert(:plus, 'a', 'a', '.')
+  defassert(:plus, 'b', '.', 'b')
+  defassert(:plus, '.', '.', '.')
+  defassert(:plus, '/b', 'a', '/b')
+
+  defassert(:plus, '/', '/', '..')
+  defassert(:plus, '.', 'a', '..')
+  defassert(:plus, 'a', 'a/b', '..')
+  defassert(:plus, '../..', '..', '..')
+  defassert(:plus, '/c', '/', '../c')
+  defassert(:plus, 'c', 'a', '../c')
+  defassert(:plus, 'a/c', 'a/b', '../c')
+  defassert(:plus, '../../c', '..', '../c')
+
+  defassert(:plus, 'a//b/d//e', 'a//b/c', '../d//e')
+
+  def relative?(path)
+    Pathname.new(path).relative?
+  end
+
+  defassert(:relative?, false, '/')
+  defassert(:relative?, false, '/a')
+  defassert(:relative?, false, '/..')
+  defassert(:relative?, true, 'a')
+  defassert(:relative?, true, 'a/b')
+
+  if DOSISH_DRIVE_LETTER
+    defassert(:relative?, false, 'A:')
+    defassert(:relative?, false, 'A:/')
+    defassert(:relative?, false, 'A:/a')
+  end
+
+  if File.dirname('//') == '//'
+    defassert(:relative?, false, '//')
+    defassert(:relative?, false, '//a')
+    defassert(:relative?, false, '//a/')
+    defassert(:relative?, false, '//a/b')
+    defassert(:relative?, false, '//a/b/')
+    defassert(:relative?, false, '//a/b/c')
+  end
+
+  def relative_path_from(dest_directory, base_directory)
+    Pathname.new(dest_directory).relative_path_from(Pathname.new(base_directory)).to_s
+  end
+
+  defassert(:relative_path_from, "../a", "a", "b")
+  defassert(:relative_path_from, "../a", "a", "b/")
+  defassert(:relative_path_from, "../a", "a/", "b")
+  defassert(:relative_path_from, "../a", "a/", "b/")
+  defassert(:relative_path_from, "../a", "/a", "/b")
+  defassert(:relative_path_from, "../a", "/a", "/b/")
+  defassert(:relative_path_from, "../a", "/a/", "/b")
+  defassert(:relative_path_from, "../a", "/a/", "/b/")
+
+  defassert(:relative_path_from, "../b", "a/b", "a/c")
+  defassert(:relative_path_from, "../a", "../a", "../b")
+
+  defassert(:relative_path_from, "a", "a", ".")
+  defassert(:relative_path_from, "..", ".", "a")
+
+  defassert(:relative_path_from, ".", ".", ".")
+  defassert(:relative_path_from, ".", "..", "..")
+  defassert(:relative_path_from, "..", "..", ".")
+
+  defassert(:relative_path_from, "c/d", "/a/b/c/d", "/a/b")
+  defassert(:relative_path_from, "../..", "/a/b", "/a/b/c/d")
+  defassert(:relative_path_from, "../../../../e", "/e", "/a/b/c/d")
+  defassert(:relative_path_from, "../b/c", "a/b/c", "a/d")
+
+  defassert(:relative_path_from, "../a", "/../a", "/b")
+  defassert(:relative_path_from, "../../a", "../a", "b")
+  defassert(:relative_path_from, ".", "/a/../../b", "/b")
+  defassert(:relative_path_from, "..", "a/..", "a")
+  defassert(:relative_path_from, ".", "a/../b", "b")
+
+  defassert(:relative_path_from, "a", "a", "b/..")
+  defassert(:relative_path_from, "b/c", "b/c", "b/..")
+
+  def self.defassert_raise(name, exc, *args)
+    define_assertion(name) {
+      message = "#{name}(#{args.map {|a| a.inspect }.join(', ')})"
+      assert_raise(exc, message) { self.send(name, *args) }
+    }
+  end
+
+  defassert_raise(:relative_path_from, ArgumentError, "/", ".")
+  defassert_raise(:relative_path_from, ArgumentError, ".", "/")
+  defassert_raise(:relative_path_from, ArgumentError, "a", "..")
+  defassert_raise(:relative_path_from, ArgumentError, ".", "..")
+
+  def realpath(path)
+    Pathname.new(path).realpath.to_s
+  end
+
+  def test_realpath
+    begin
+      File.symlink(nil, nil)
+    rescue NotImplementedError
+      return
+    rescue TypeError
+    end
+    dir = "#{Dir.tmpdir}/tst-pathname-#$$"
+    Dir.mkdir(dir)
+    begin
+      File.symlink("not-exist-target", "#{dir}/not-exist")
+      assert_raise(Errno::ENOENT) { realpath("#{dir}/not-exist") }
+      File.symlink("loop", "#{dir}/loop")
+      assert_raise(Errno::ELOOP) { realpath("#{dir}/loop") }
+    ensure
+      FileUtils.rmtree(dir)
+    end
+  end
+
+  def descend(path)
+    Pathname.new(path).enum_for(:descend).map {|v| v.to_s }
+  end
+
+  defassert(:descend, %w[/ /a /a/b /a/b/c], "/a/b/c")
+  defassert(:descend, %w[a a/b a/b/c], "a/b/c")
+  defassert(:descend, %w[. ./a ./a/b ./a/b/c], "./a/b/c")
+  defassert(:descend, %w[a/], "a/")
+
+  def ascend(path)
+    Pathname.new(path).enum_for(:ascend).map {|v| v.to_s }
+  end
+
+  defassert(:ascend, %w[/a/b/c /a/b /a /], "/a/b/c")
+  defassert(:ascend, %w[a/b/c a/b a], "a/b/c")
+  defassert(:ascend, %w[./a/b/c ./a/b ./a .], "./a/b/c")
+  defassert(:ascend, %w[a/], "a/")
+
+  def test_initialize
+    p1 = Pathname.new('a')
+    assert_equal('a', p1.to_s)
+    p2 = Pathname.new(p1)
+    assert_equal(p1, p2)
+  end
+
+  class AnotherStringLike # :nodoc:
+    def initialize(s) @s = s end
+    def to_str() @s end
+    def ==(other) @s == other end
+  end
+
+  def test_equality
+    obj = Pathname.new("a")
+    str = "a"
+    sym = :a
+    ano = AnotherStringLike.new("a")
+    assert_equal(false, obj == str)
+    assert_equal(false, str == obj)
+    assert_equal(false, obj == ano)
+    assert_equal(false, ano == obj)
+    assert_equal(false, obj == sym)
+    assert_equal(false, sym == obj)
+
+    obj2 = Pathname.new("a")
+    assert_equal(true, obj == obj2)
+    assert_equal(true, obj === obj2)
+    assert_equal(true, obj.eql?(obj2))
+  end
+
+  def test_hashkey
+    h = {}
+    h[Pathname.new("a")] = 1
+    h[Pathname.new("a")] = 2
+    assert_equal(1, h.size)
+  end
+
+  def assert_pathname_cmp(e, s1, s2)
+    p1 = Pathname.new(s1)
+    p2 = Pathname.new(s2)
+    r = p1 <=> p2
+    assert(e == r,
+      "#{p1.inspect} <=> #{p2.inspect}: <#{e}> expected but was <#{r}>")
+  end
+  def test_comparison
+    assert_pathname_cmp( 0, "a", "a")
+    assert_pathname_cmp( 1, "b", "a")
+    assert_pathname_cmp(-1, "a", "b")
+    ss = %w(
+      a
+      a/
+      a/b
+      a.
+      a0
+    )
+    s1 = ss.shift
+    ss.each {|s2|
+      assert_pathname_cmp(-1, s1, s2)
+      s1 = s2
+    }
+  end
+
+  def test_comparison_string
+    assert_equal(nil, Pathname.new("a") <=> "a")
+    assert_equal(nil, "a" <=> Pathname.new("a"))
+  end
+
+  def root?(path)
+    Pathname.new(path).root?
+  end
+
+  defassert(:root?, true, "/")
+  defassert(:root?, true, "//")
+  defassert(:root?, true, "///")
+  defassert(:root?, false, "")
+  defassert(:root?, false, "a")
+
+  def test_destructive_update
+    path = Pathname.new("a")
+    path.to_s.replace "b"
+    assert_equal(Pathname.new("a"), path)
+  end
+
+  def test_null_character
+    assert_raise(ArgumentError) { Pathname.new("\0") }
+  end
+
+  def test_taint
+    obj = Pathname.new("a"); assert_same(obj, obj.taint)
+    obj = Pathname.new("a"); assert_same(obj, obj.untaint)
+
+    assert_equal(false, Pathname.new("a"      )           .tainted?)
+    assert_equal(false, Pathname.new("a"      )      .to_s.tainted?)
+    assert_equal(true,  Pathname.new("a"      ).taint     .tainted?)
+    assert_equal(true,  Pathname.new("a"      ).taint.to_s.tainted?)
+    assert_equal(true,  Pathname.new("a".taint)           .tainted?)
+    assert_equal(true,  Pathname.new("a".taint)      .to_s.tainted?)
+    assert_equal(true,  Pathname.new("a".taint).taint     .tainted?)
+    assert_equal(true,  Pathname.new("a".taint).taint.to_s.tainted?)
+
+    str = "a"
+    path = Pathname.new(str)
+    str.taint
+    assert_equal(false, path     .tainted?)
+    assert_equal(false, path.to_s.tainted?)
+  end
+
+  def test_untaint
+    obj = Pathname.new("a"); assert_same(obj, obj.untaint)
+
+    assert_equal(false, Pathname.new("a").taint.untaint     .tainted?)
+    assert_equal(false, Pathname.new("a").taint.untaint.to_s.tainted?)
+
+    str = "a".taint
+    path = Pathname.new(str)
+    str.untaint
+    assert_equal(true, path     .tainted?)
+    assert_equal(true, path.to_s.tainted?)
+  end
+
+  def test_freeze
+    obj = Pathname.new("a"); assert_same(obj, obj.freeze)
+
+    assert_equal(false, Pathname.new("a"       )            .frozen?)
+    assert_equal(false, Pathname.new("a".freeze)            .frozen?)
+    assert_equal(true,  Pathname.new("a"       ).freeze     .frozen?)
+    assert_equal(true,  Pathname.new("a".freeze).freeze     .frozen?)
+    assert_equal(false, Pathname.new("a"       )       .to_s.frozen?)
+    assert_equal(false, Pathname.new("a".freeze)       .to_s.frozen?)
+    assert_equal(false, Pathname.new("a"       ).freeze.to_s.frozen?)
+    assert_equal(false, Pathname.new("a".freeze).freeze.to_s.frozen?)
+  end
+
+  def test_to_s
+    str = "a"
+    obj = Pathname.new(str)
+    assert_equal(str, obj.to_s)
+    assert_not_same(str, obj.to_s)
+    assert_not_same(obj.to_s, obj.to_s)
+  end
+
+  def test_kernel_open
+    count = 0
+    result = Kernel.open(Pathname.new(__FILE__)) {|f|
+      assert(File.identical?(__FILE__, f))
+      count += 1
+      2
+    }
+    assert_equal(1, count)
+    assert_equal(2, result)
+  end
+end


Property changes on: trunk/test/pathname/test_pathname.rb
___________________________________________________________________
Name: svn:mime-type
   + text/script

Added: trunk/test/scanf/data.txt
===================================================================
--- trunk/test/scanf/data.txt	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/scanf/data.txt	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,6 @@
+this is 33 a fun
+little input file
+
+with
+
+characters

Added: trunk/test/scanf/test_scanf.rb
===================================================================
--- trunk/test/scanf/test_scanf.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/scanf/test_scanf.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,310 @@
+# $Id: test_scanf.rb,v 1.2 2004/03/02 11:21:32 dblack Exp $
+#
+# scanf for Ruby
+#
+# Unit tests
+#
+
+require 'scanf.rb'
+require 'test/unit'
+
+# Comment out either of these lines to skip those tests.
+
+class TestStringScanf < Test::Unit::TestCase;end
+class TestIOScanf < Test::Unit::TestCase;end
+
+module ScanfTests
+
+def tests
+    [
+
+# Scratchpad
+      [ "%2[a]", "nbc", []],
+      [ "%*d %*3d %*s", "123 +456 abc", [] ],
+      [ "%d%c", "123 x", [ 123, " " ] ],
+      [ "%d%c", "123x", [ 123, "x" ] ],
+      [ "%d %c", "123x", [ 123, "x" ] ],
+      [ "%d %c", "123 x", [ 123, "x" ] ],
+
+# Testing failures
+      [ "%x", "x", [] ],
+      [ "%2x", "x", [] ],
+      [ "%i", "x", [] ],
+#  ]; end; def nothing; [
+      [ "%2i", "x", [] ],
+      [ "%2o", "x", [] ],
+      [ "%d", "x", [] ],
+      [ "%2d", "x", [] ],
+      [ "%3d", "+x3", [] ],
+      [ "%d%[abc]", "eabc", [] ],
+      [ "%d\n%[abc]", "\neabc", [] ],
+      [ "%d%[^abc]", "ghiabc", [ ] ],
+      [ "%d%[abc]", "abc", [] ],
+      [ "%*d %*3d %*s", "123 +456 abc", [] ],
+      [ "%d%s", "", [] ],
+      [ "%d%s", "blah 123 string", [] ],
+      [ "%[\n]", "abc\n", [] ],
+      [ "%[\n]", "abc\n", [] ],
+      [ "%[\n]", "abc\n", [] ],
+      [ "%f", "x", [] ],
+      [ "%f", "z", [] ],
+      [ "%f", "z3.2534", [] ],
+      [ "", "", [] ],
+      [ "", "abc 123", [] ],
+      [ '%[^\\w]%c', "a...1", [] ],
+
+# Testing 'x'
+      [ "%3x", "0xz", [0] ],
+
+# Testing 'i'
+      [ "%3i", "097", [0] ],
+      [ "%3i", "0xz", [0] ],
+      [ "%1i", "3", [ 3 ] ],
+      [ "%2i", "07", [ 7 ] ],
+      [ "%2i", "0a", [ 0 ] ],
+
+# Testing 'c'
+      [ "%3c", "abc", [ "abc" ] ],
+      [ "%3c", "a\nb", [ "a\nb" ] ],
+      [ "%3c", "a\nbcd", [ "a\nb" ] ],
+      [ "%c\n\n", "x\n\n", [ "x" ] ],
+      [ "%c\n\n", "x\n\n", [ "x" ] ],
+      [ "%c", "\n", [ "\n" ] ],
+      [ "%c", "x\n", [ "x" ] ],
+      [ "%2c", " 123", [" 1"] ],
+      [ " %c", " x", ["x"] ],
+      [ "%c", " x", [" "] ],
+      [ "%c", "123", ["1"] ],
+      [ "%2c", "123", ["12"] ],
+      [ "%5c", "a\nb\n\n", [ "a\nb\n\n" ] ],
+      [ "%6c", "a\nb\n\nx", [ "a\nb\n\nx" ] ],
+      [ "%5c", "ab\ncd", [ "ab\ncd" ] ],
+      [ "%5c", "a\nb\n\n", [ "a\nb\n\n" ] ],
+
+# Testing 'o'
+      [ "%3o", "0xz", [0] ],
+
+# Testing 'd'
+      [ "%d", "\n123", [ 123 ] ],
+      [ "%d", "\n\n123", [ 123 ] ],
+      [ "%d", "\n123", [ 123 ] ],
+      [ "%1d", "2", [2] ],
+
+# Mixed tests
+# Includes:
+#   whitespace/newline
+#   mixed integer bases
+#   various mixed specifiers
+
+      [ "%[^\\w]%c", "...1", [ "...", "1"] ],
+      [ '%[^\\w]%c', "...1", [ "...", "1"] ],
+      [ "%[abc\n]%d", "a\n\nb\n\nc   123", [ "a\n\nb\n\nc", 123 ] ],
+      [ "%[abc\n]%d", "a\n\nb\n\nc \t  123", [ "a\n\nb\n\nc", 123 ] ],
+      [ "%[abc\t]%d", "a\t\tb\t\tc   123", [ "a\t\tb\t\tc", 123 ] ],
+      [ "%d%3[abc\n]", "123a\nbeaab", [ 123, "a\nb" ] ],
+      [ "%d%20c",  "42   is the key", [ 42, "   is the key" ] ],
+      [ "%d %20c",  "42   is the key", [ 42, "is the key" ] ],
+      [ "%d%3[^abc\n]%d", "123de\nf123", [ 123, "de" ] ],
+      [ "%d %4c", "3abc", [ 3, "abc" ] ],
+      [ "%f%d\n%[abc]", "1\neabc", [1.0] ],
+      [ "%d%3[abc]", "123aaab", [ 123, "aaa" ] ],
+      [ "%d%3[abc]", "123 aaab", [ 123 ] ],
+      [ "%d%3[abc]", "123aeaab", [ 123, "a" ] ],
+      [ "%d%[^abc]", "123defabc", [123, "def" ] ],
+      [ "%d%3[^abc]", "123defdef", [ 123, "def" ] ],
+      [ "%d%3[^abc] ", "123defdef   ", [ 123, "def" ] ],
+      [ "%d%3[^abc]ghi", "123defghi", [ 123, "def" ] ],
+      [ "%d%3[^abc]", "123defdef", [ 123, "def" ] ],
+      [ "%d%3[^abc]", "123adefdef", [ 123 ] ],
+      [ "%d%3[^abc]", "123deafdef", [ 123, "de" ] ],
+      [ "%d%3[^abc\n]", "123de\nf", [ 123, "de" ] ],
+      [ "%s%c%c%s", "abc\n\ndef", ["abc", "\n","\n", "def" ] ],
+      [ "%c%d", "\n\n123", [ "\n",123 ] ],
+      [ "%s%c%d", "abc\n123", [ "abc", "\n", 123 ] ],
+      [ "%s%c%d", "abc\n\n123", [ "abc", "\n", 123 ] ],
+      [ "%c%d", "\t\n123", [ "\t",123 ] ],
+      [ "%s%c%d", "abc\t\n123", [ "abc", "\t", 123 ] ],
+      [ "%3c%d", "abc123", [ "abc", 123 ] ],
+      [ "%3c\n%d", "abc123", [ "abc", 123 ] ],
+      [ "%3c\n%d", "abc 123", [ "abc", 123 ] ],
+      [ "%3c %d", "abc123", [ "abc", 123 ] ],
+      [ "%3c\t%d", "abc \n 123", [ "abc", 123 ] ],
+      [ "%3c\t%d", "abc \n 123   ", [ "abc", 123 ] ],
+      [ "%3c%d", "a\nb123", [ "a\nb", 123 ] ],
+      [ "%f%3c", "1.2x\ny", [ 1.2, "x\ny"] ],
+      [ "%d\n%d\n%d", "123 456 789", [ 123,456,789 ] ],
+      [ "%d\n%i%2d%x\n%d", "123 0718932", [ 123, 071, 89, 0x32] ],
+      [ "%c\n%c", "x y", [ "x", "y" ] ],
+      [ "%c\t%c", "x y", [ "x", "y" ] ],
+      [ "%s\n%s", "x y", [ "x", "y" ] ],
+      [ "%s%s\n", "x y", [ "x", "y" ] ],
+      [ "%c\n\n%c", "x\n\ny", [ "x", "y" ] ],
+      [ "%s%d%d", "abc\n123\n456", [ "abc", 123, 456 ] ],
+      [ "%3s%c%3c%d", "1.2x\n\ny123", [ "1.2", "x", "\n\ny", 123 ] ],
+      [ "%f%3c", "1.2x\ny", [ 1.2, "x\ny"] ],
+      [ "%c\n%c", "x\n\ny", [ "x", "y" ] ],
+      [ "%c\n\n%c", "x\n\ny", [ "x", "y" ] ],
+      [ "%c  %c", "x\n\ny", [ "x", "y" ] ],
+      [ "%s\n\n%c", "x\n\ny", [ "x", "y" ] ],
+      [ "%s\n\n%s", "x\n\ny", [ "x", "y" ] ],
+      [ "%d\n\n%d", "23\n\n45", [ 23, 45 ] ],
+      [ "%d\n%d", "23\n\n45", [ 23, 45 ] ],
+      [ "%c\n\n%c", "x y", [ "x", "y" ] ],
+      [ "%c%c", "x\n\ny", [ "x", "\n" ] ],
+      [ "%c\n%c", "x y", [ "x", "y" ] ],
+      [ "%c\t%c", "x y", [ "x", "y" ] ],
+      [ "%s\n%s", "x y", [ "x", "y" ] ],
+      [ "%s%s\n", "x y", [ "x", "y" ] ],
+      [ "%c%c", "x\n", [ "x", "\n" ] ],
+      [ "%d%c%c%d", "345   678", [ 345, " ", " ", 678] ],
+      [ "%d   %c%s", "123   x  hello", [123, "x", "hello"] ],
+      [ "%d%2c", "654 123", [654," 1"] ],
+      [ "%5c%s", "a\nb\n\nxyz", [ "a\nb\n\n","xyz" ] ],
+      [ "%s%[ xyz]%d", "hello x 32", ["hello", " x ", 32] ],
+      [ "%5s%8[a-z]%d", "helloblahblah 32", ["hello", "blahblah", 32] ],
+      [ '%s%[abcde\\s]%d', "hello badea 32", ["hello", " badea ", 32] ],
+      [ '%d%[\\s]%c', "123 \n\t X", [ 123," \n\t ", "X"] ],
+      [ "%4s%2c%c", "1.2x\n\ny", [ "1.2x", "\n\n","y"] ],
+      [ "%f%c %3c%d", "1.2x\n\ny123", [ 1.2, "x", "y12", 3 ] ],
+      [ "%s%5c", "abc ab\ncd", [ "abc", " ab\nc" ] ],
+      [ "%5c%f", "ab\ncd1.2", [ "ab\ncd",1.2 ] ],
+      [ "%5c%c", "ab\ncd1", [ "ab\ncd","1" ] ],
+      [ "%f%c%2c%d", "1.2x\ny123", [ 1.2, "x", "\ny", 123 ] ],
+      [ "%f%c%3c", "1.2x\ny123", [ 1.2, "x", "\ny1"] ],
+      [ "%s\n%s", "blah\n\nand\nmore stuff", [ "blah", "and" ] ],
+      [ "%o%d%x", "21912a3", [ "21".oct, 912, "a3".hex ] ],
+      [ "%3o%4d%3x", "21912a3", [ "21".oct, 912, "a3".hex ] ],
+      [ "%3o%4d%5x", "2191240xa3", [ "21".oct, 9124, "a3".hex ] ],
+      [ "%3d%3x", "12abc", [12, "abc".hex] ],
+      [ "%s%i%d", "hello +0xdef 123", [ "hello", "def".hex, 123] ],
+      [ "%s%i%d", "hello -0xdef 123", [ "hello", -"def".hex, 123] ],
+      [ "%s%i%i%i", "hello 012 -012 100", [ "hello", 10, -10, 100 ] ],
+      [ "%s%i%i%i", "hello 012 0x12 100", [ "hello", 10, 18, 100 ] ],
+      [ "%s%5i%3i%4i", "hello 0x123 123 0123", [ "hello", "0x123".hex, 123,"0123".oct] ],
+      [ "%s%3i%4i", "hello 1230123", [ "hello", 123,"0123".oct] ],
+      [ "%s%3i", "hello 1230", [ "hello", 123] ],
+      [ "%s%5x%d", "hello 0xdef 123", [ "hello", "def".hex, 123] ],
+      [ "%s%6x%d", "hello +0xdef 123", [ "hello", "def".hex, 123] ],
+      [ "%s%6x%d", "hello -0xdef 123", [ "hello", -"def".hex, 123] ],
+      [ "%s%6x%d", "hello -0xdef 123", [ "hello", -"def".hex, 123] ],
+      [ "%s%4x%d", "hello -def 123", [ "hello", -"def".hex, 123] ],
+      [ "%s%3x%d", "hello def 123", [ "hello", "def".hex, 123] ],
+      [ "%s%x%d", "hello -def 123", [ "hello", -"def".hex, 123] ],
+      [ "%s%x%d", "hello -0xdef 123", [ "hello", -"def".hex, 123] ],
+      [ "%s%x%d", "hello 0xdef 123", [ "hello", "def".hex, 123] ],
+      [ "%s%d%x%s", "hello 123 abc def", [ "hello", 123, "abc".hex, "def"] ],
+      [ "%s%d%o%d", "hello 012 012 100", [ "hello", 12, 10, 100 ] ],
+      [ "%s%d%o%d", "hello 012 -012 100", [ "hello", 12, -10, 100 ] ],
+      [ "%s%o%x%d", "hello 012 0x12 100", [ "hello", 10, 18, 100 ] ],
+      [ "%s%d%o%d", "hello 012 +01288", [ "hello", 12, 10, 88 ] ],
+      [ "%f %d %s", "12.3e23 45 string", ["12.3e23".to_f, 45, "string"] ],
+      [ "%f %d %s", "12.3e+23 45 string", ["12.3e23".to_f, 45, "string"] ],
+      [ "%f %d %s", "12.3e-23 45 string", ["12.3e-23".to_f, 45, "string"] ],
+      [ "%f %d %s", "12.3e23 45 string", ["12.3e23".to_f, 45, "string"] ],
+      [ "%f %d %s", "-12.3e-23 45 string", ["-12.3e-23".to_f, 45, "string"] ],
+      [ "%f %d %s", "12.e23 45 string", ["12.e23".to_f, 45, "string"] ],
+      [ "%5f %d %s", "1.2e23 string", ["1.2e2".to_f, 3, "string"] ],
+      [ "%5f%d %s", "1.2e23 string", ["1.2e2".to_f, 3, "string"] ],
+      [ "%5f%d %d %s", "1.2e23 45 string", ["1.2e2".to_f, 3, 45, "string"] ],
+      [ "%6f %d %d %s", "+1.2e23 45 string", ["1.2e2".to_f, 3, 45, "string"] ],
+      [ "%d %d", "123 \n 345", [123, 345] ],
+      [ "%d %*d", "123 \n 345", [123] ],
+      [ "%d %3d789", "123 +45789", [123, 45] ],
+      [ "%d %3d%d", "123 +456789", [123, 45, 6789] ],
+      [ "%d %3dabc", "123 456abc", [123, 456] ],
+      [ "%d %s", "123abc", [123, "abc"] ],
+      [ "%d%s %s", "123 abc def", [123, "abc", "def"] ],
+      [ "%s%s", "abc123 def", ["abc123", "def"] ],
+      [ "%s%s %s", "123 abc def", ["123", "abc", "def"] ],
+      [ "%s%%%s", "abc % def", ["abc", "def"] ],
+      [ "%d %3d %s", "+123 456abc", [123, 456, "abc"] ],
+      [ "%d %3d %s", "123 456abc", [123, 456, "abc"] ],
+      [ "%d %3d %s", "123 +456 abc", [123, 45, "6"] ],
+      [ "%d %3d %s", "-123-456abc", [-123, -45, "6abc"] ],
+      [ "%dabc%d", "123abc345", [123, 345] ],
+      [ "%d%5s%d", "123 abcde12", [123, "abcde", 12] ],
+      [ "%5d%5s%5d", "12345abcde67890", [12345, "abcde", 67890] ],
+      [ "%5d%*5s%5d", "12345abcde67890", [12345, 67890] ],
+      [ " 12345%5s%5d", "12345abcde67890", [ "abcde", 67890] ],
+      [ "%5dabcde%5d", "12345abcde67890", [ 12345, 67890] ],
+      [ "%s%%%*s", "abc % def", ["abc"] ],
+      [ "%*6s %d", "string 123", [123] ],
+      [ "%d %*3d %s", "-123-456abc", [-123, "6abc"] ],
+      [ "%d%s", "123", [123] ],
+      [ "%s%d", "abc", ["abc"] ],
+      [ "%f%x", "3.2e45x", ["3.2e45x".to_f] ],
+      [ "%s%d", "abc", ["abc"] ],
+      [ "%*5f%d %d %s", "1.2e23 45 string", [3, 45, "string"] ],
+      [ "%5f%*d %d %s", "1.2e23 45 string", ["1.2e2".to_f, 45, "string"] ],
+      [ "%*5f%*d %*d %s", "1.2e23 45 string", ["string"] ],
+      [ "%f %*d %s", "12.e23 45 string", ["12.e23".to_f, "string"] ],
+      [ "%5f %d %s", "1.2e23 string", ["1.2e2".to_f, 3, "string"] ],
+      [ "%s %f %s %d %x%c%c%c%c", 
+        "float: 1.2e23 dec/hex: 135a23 abc", 
+        ["float:", "1.2e23".to_f, "dec/hex:", 135, "a23".hex, " ", "a", "b", "c" ] ],
+
+# Testing 's'
+      [ "%s\n", "blah\n\n\n", [ "blah" ] ],
+
+# Testing '['
+      [ "%[a\nb]", "a\nb", [ "a\nb" ] ],
+      [ "%[abc]", "acb", [ "acb" ] ],
+      [ "%[abc\n]", "a\nb", [ "a\nb" ] ],
+      [ "%[^abc]", "defabc", [ "def" ] ],
+      [ "%[-abc]", "abc-cba", [ "abc-cba" ] ],
+      [ "%[\n]", "\n", [ "\n" ] ],
+      [ "%[\n]", "\nabc", [ "\n" ] ],
+      [ "%[\n\t]", "\t\n", [ "\t\n" ] ],
+      [ "%[a-f]", "abczef", [ "abc" ] ],
+      [ "%d%3[abc]", "123 aaab", [ 123 ] ],
+      [ "%d%3[^abc]", "123adefdef", [ 123 ] ],
+      [ "%d%3[[:lower:]] %f", "123ade1.2", [ 123,"ade",1.2 ] ],
+      [ "%d%3[[:lower:]] %f", "123ad1.2", [ 123,"ad",1.2 ] ],
+      [ "%d%3[[:lower:]] %f", "123 ad1.2", [ 123 ] ],
+      [ "%d%[[:lower:]]", "123abcdef1.2", [ 123, "abcdef" ] ],
+      [ "%[[:lower:]]%d", "abcdef123", [ "abcdef", 123 ] ],
+      [ "%[[:digit:]]%[[:alpha:]]", "123abcdef", [ "123", "abcdef" ] ],
+      [ "%[[:digit:]]%d", "123 123", [ "123", 123 ] ],
+      [ "%[[:upper:]]", "ABCdefGHI", [ "ABC" ] ],
+
+# Testing 'f'
+      [ "%2f", "x", [0.0] ],  # width-floats match anything (by design)
+      [ "%f", "1.23e45", [1.23e+45] ],
+      [ "%f", "3.25ee", [3.25] ],
+      [ "%f", "3..25", [3.0] ],
+      [ "%f", "+3.25", [3.25] ],
+      [ "%f", "+3.25e2", [325.0] ],
+      [ "%f", "3.z", [3.0] ],
+     ]
+    end
+  end
+
+class TestStringScanf
+  include Scanf
+  extend ScanfTests
+
+  i = 1
+  self.tests.each do |test|
+    define_method("test_#{i}") do ||
+      assert_equal(test[2], test[1].scanf(test[0]))
+      end
+    i += 1
+  end
+end
+
+class TestIOScanf
+  include Scanf
+  extend ScanfTests
+  
+  i = 1
+  self.tests.each do |test|
+    define_method("test_#{i}") do ||
+      File.open("iotest.dat", "w") {|fh| fh.print test[1]}
+      File.open("iotest.dat", "r") { |fh|
+        assert_equal(test[2], fh.scanf(test[0]))
+      }
+      File.delete("iotest.dat")
+    end
+    i += 1
+  end
+end

Added: trunk/test/scanf/test_scanfblocks.rb
===================================================================
--- trunk/test/scanf/test_scanfblocks.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/scanf/test_scanfblocks.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,78 @@
+# $Id: test_scanfblocks.rb,v 1.2 2004/03/02 11:21:32 dblack Exp $
+#
+# scanf for Ruby
+#
+# Some not very comprehensive tests of block behavior.
+
+
+require 'test/unit'
+require 'scanf'
+
+class TestScanfBlock < Test::Unit::TestCase
+
+  def setup
+    @str = <<-EOS
+    Beethoven  1770
+    Bach       1685
+    Handel     1685
+    Scarlatti  1685
+    Brahms     1833
+    EOS
+  end
+  
+alias set_up setup
+  def test_str1
+    res = @str.scanf("%s%d") { |name, year| "#{name} was born in #{year}." }
+    assert_equal(res,
+    [ "Beethoven was born in 1770.",
+      "Bach was born in 1685.",
+      "Handel was born in 1685.",
+      "Scarlatti was born in 1685.",
+      "Brahms was born in 1833." ])
+  end
+
+  def test_str2
+    names = @str.scanf("%s%d") { |name, year| name.upcase }
+    assert_equal(names, ["BEETHOVEN", "BACH", "HANDEL", "SCARLATTI", "BRAHMS"])
+  end
+
+  def test_str3
+    assert_equal("".scanf("%d%f%s") {}, [])
+  end
+
+  def test_str4
+    assert_equal("abc".scanf("%d%f%s") {}, [])
+  end
+
+  def test_str5
+    assert_equal("abc".scanf("") {}, [])
+  end
+
+  def test_io1
+    File.open("iotest.dat", "w") { |fh| fh.puts(@str) }
+    fh = File.open("iotest.dat", "rb")
+    res = fh.scanf("%s%d") { |name, year| "#{name} was born in #{year}." }
+
+    assert_equal(
+    [ "Beethoven was born in 1770.",
+      "Bach was born in 1685.",
+      "Handel was born in 1685.",
+      "Scarlatti was born in 1685.",
+      "Brahms was born in 1833." ],res)
+    fh.close
+  ensure
+    File.delete("iotest.dat")  
+    end
+
+  def test_io2
+    File.open("iotest.dat", "w").close
+    fh = File.open("iotest.dat","rb")
+    assert_equal(fh.scanf("") {}, [])
+    fh.seek(0)
+    assert_equal(fh.scanf("%d%f%s") {}, [])
+    fh.close
+  ensure
+    File.delete("iotest.dat")  
+  end
+
+end

Added: trunk/test/scanf/test_scanfio.rb
===================================================================
--- trunk/test/scanf/test_scanfio.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/scanf/test_scanfio.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,19 @@
+# $Id: test_scanfio.rb,v 1.2 2004/03/02 11:21:32 dblack Exp $
+#
+# scanf for Ruby
+#
+# Ad hoc tests of IO#scanf (needs to be expanded)
+
+
+require "scanf"
+
+class TestScanfIO
+  def test_io
+    fh = File.new(File.join(File.dirname(__FILE__), "data.txt"), "r")
+    assert_equal(0, fh.pos)
+    assert_equal(["this", "is"], fh.scanf("%s%s"))
+    assert_equal([33, "littel"], fh.scanf("%da fun%s"))
+    #p fh.pos
+  end
+end
+

Added: trunk/test/socket/test_socket.rb
===================================================================
--- trunk/test/socket/test_socket.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/socket/test_socket.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,74 @@
+begin
+  require "socket"
+  require "test/unit"
+rescue LoadError
+end
+
+class TestBasicSocket < Test::Unit::TestCase
+  def inet_stream
+    sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+    yield sock
+  ensure
+    assert_raise(IOError) {sock.close}
+  end
+
+  def test_getsockopt
+    inet_stream do |s|
+      n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE)
+      assert_equal([Socket::SOCK_STREAM].pack("i"), n)
+      n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
+      assert_equal([0].pack("i"), n)
+      val = Object.new
+      class << val; self end.funcall(:define_method, :to_int) {
+        s.close
+        Socket::SO_TYPE
+      }
+      assert_raise(IOError) {
+        n = s.getsockopt(Socket::SOL_SOCKET, val)
+      }
+    end
+  end
+
+  def test_setsockopt # [ruby-dev:25039]
+    s = nil
+    linger = [0, 0].pack("ii")
+
+    val = Object.new
+    class << val; self end.funcall(:define_method, :to_str) {
+      s.close
+      linger
+    }
+    inet_stream do |s|
+      assert_equal(0, s.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger))
+
+      assert_raise(IOError) {
+        s.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, val)
+      }
+    end
+
+    val = Object.new
+    class << val; self end.funcall(:define_method, :to_int) {
+      s.close
+      Socket::SO_LINGER
+    }
+    inet_stream do |s|
+      assert_raise(IOError) {
+        s.setsockopt(Socket::SOL_SOCKET, val, linger)
+      }
+    end
+  end
+
+  def test_listen
+    s = nil
+    log = Object.new
+    class << log; self end.funcall(:define_method, :to_int) {
+      s.close
+      2
+    }
+    inet_stream do |s|
+      assert_raise(IOError) {
+        s.listen(log)
+      }
+    end
+  end
+end if defined?(Socket)

Added: trunk/test/socket/test_tcp.rb
===================================================================
--- trunk/test/socket/test_tcp.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/socket/test_tcp.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,28 @@
+begin
+  require "socket"
+  require "test/unit"
+rescue LoadError
+end
+
+
+class TestTCPSocket < Test::Unit::TestCase
+  def test_recvfrom # [ruby-dev:24705]
+    c = s = nil
+    svr = TCPServer.new("localhost", 0)
+    th = Thread.new {
+      c = svr.accept
+      Thread.pass
+      ObjectSpace.each_object(String) {|s|
+        s.replace "a" if s.length == 0x10000 and !s.frozen?
+      }
+      c.print("x"*0x1000)
+    }
+    addr = svr.addr
+    sock = TCPSocket.open(addr[2], addr[1])
+    assert_raise(RuntimeError, SocketError) {
+      sock.recvfrom(0x10000)
+    }
+  ensure
+    th.join
+  end
+end if defined?(TCPSocket)

Added: trunk/test/socket/test_udp.rb
===================================================================
--- trunk/test/socket/test_udp.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/socket/test_udp.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,32 @@
+begin
+  require "socket"
+  require "test/unit"
+rescue LoadError
+end
+
+
+class TestUDPSocket < Test::Unit::TestCase
+  def test_connect # [ruby-dev:25045]
+    s = UDPSocket.new
+    host = Object.new
+    class << host; self end.funcall(:define_method, :to_str) {
+      s.close
+      "127.0.0.1"
+    }
+    assert_raise(IOError) {
+      s.connect(host, 1)
+    }
+  end
+
+  def test_bind # [ruby-dev:25057]
+    s = UDPSocket.new
+    host = Object.new
+    class << host; self end.funcall(:define_method, :to_str) {
+      s.close
+      "127.0.0.1"
+    }
+    assert_raise(IOError) {
+      s.bind(host, 2000)
+    }
+  end
+end if defined?(UDPSocket)

Added: trunk/test/socket/test_unix.rb
===================================================================
--- trunk/test/socket/test_unix.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/socket/test_unix.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,30 @@
+begin
+  require "socket"
+  require "test/unit"
+rescue LoadError
+end
+
+class TestUNIXSocket < Test::Unit::TestCase
+  def test_fd_passing
+    r1, w = IO.pipe
+    s1, s2 = UNIXSocket.pair
+    begin
+      s1.send_io(nil)
+    rescue NotImplementedError
+      assert_raise(NotImplementedError) { s2.recv_io }
+    rescue TypeError
+      s1.send_io(r1)
+      r2 = s2.recv_io
+      assert_equal(r1.stat.ino, r2.stat.ino)
+      assert_not_equal(r1.fileno, r2.fileno)
+      w.syswrite "a"
+      assert_equal("a", r2.sysread(10))
+    ensure
+      s1.close
+      s2.close
+      w.close
+      r1.close
+      r2.close if r2 && !r2.closed?
+    end
+  end
+end if defined?(UNIXSocket)

Added: trunk/test/stringio/test_stringio.rb
===================================================================
--- trunk/test/stringio/test_stringio.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/stringio/test_stringio.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,43 @@
+require 'test/unit'
+require 'stringio'
+dir = File.expand_path(__FILE__)
+2.times {dir = File.dirname(dir)}
+$:.replace([File.join(dir, "ruby")] | $:)
+require 'ut_eof'
+
+class TestStringIO < Test::Unit::TestCase
+  include TestEOF
+  def open_file(content)
+    f = StringIO.new(content)
+    yield f
+  end
+  alias open_file_rw open_file
+
+  include TestEOF::Seek
+
+  def test_truncate # [ruby-dev:24190]
+    io = StringIO.new("")
+    io.puts "abc"
+    io.truncate(0)
+    io.puts "def"
+    assert_equal("\0\0\0\0def\n", io.string)
+  end
+
+  def test_seek_beyond_eof # [ruby-dev:24194]
+    io = StringIO.new
+    n = 100
+    io.seek(n)
+    io.print "last"
+    assert_equal("\0" * n + "last", io.string)
+  end
+
+  def test_overwrite # [ruby-core:03836]
+    stringio = StringIO.new
+    responses = ['', 'just another ruby', 'hacker']
+    responses.each do |resp|
+      stringio.puts(resp)
+      stringio.rewind
+    end
+    assert_equal("hacker\nother ruby\n", stringio.string)
+  end
+end

Added: trunk/test/uri/test_common.rb
===================================================================
--- trunk/test/uri/test_common.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/uri/test_common.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,56 @@
+require 'test/unit'
+require 'uri'
+
+module URI
+
+
+class TestCommon < Test::Unit::TestCase
+  def setup
+  end
+
+  def teardown
+  end
+
+  def test_extract
+    # ruby-list:36086
+    assert_equal(['http://example.com'], 
+		 URI.extract('http://example.com'))
+    assert_equal(['http://example.com'], 
+		 URI.extract('(http://example.com)'))
+    assert_equal(['http://example.com/foo)'], 
+		 URI.extract('(http://example.com/foo)'))
+    assert_equal(['http://example.jphttp://example.jp'], 
+		 URI.extract('http://example.jphttp://example.jp'))
+    assert_equal(['http://example.jphttp://example.jp'], 
+		 URI.extract('http://example.jphttp://example.jp', ['http']))
+    assert_equal(['http://', 'mailto:'].sort, 
+		 URI.extract('ftp:// http:// mailto: https://', ['http', 'mailto']).sort)
+    # reported by Doug Kearns <djkea2 mugca.its.monash.edu.au>
+    assert_equal(['From:', 'mailto:xxx xxx.xxx.xxx]'].sort, 
+		 URI.extract('From: XXX [mailto:xxx xxx.xxx.xxx]').sort)
+  end
+
+  def test_regexp
+    assert_instance_of Regexp, URI.regexp
+    assert_instance_of Regexp, URI.regexp(['http'])
+    assert_equal URI.regexp, URI.regexp
+    assert_equal 'http://', 'x http:// x'.slice(URI.regexp)
+    assert_equal 'http://', 'x http:// x'.slice(URI.regexp(['http']))
+    assert_equal 'http://', 'x http:// x ftp://'.slice(URI.regexp(['http']))
+    assert_equal nil, 'http://'.slice(URI.regexp([]))
+    assert_equal nil, ''.slice(URI.regexp)
+    assert_equal nil, 'xxxx'.slice(URI.regexp)
+    assert_equal nil, ':'.slice(URI.regexp)
+    assert_equal 'From:', 'From:'.slice(URI.regexp)
+  end
+
+  def test_kernel_uri
+    expected = URI.parse("http://www.ruby-lang.org/")
+    assert_equal(expected, URI("http://www.ruby-lang.org/"))
+    assert_equal(expected, Kernel::URI("http://www.ruby-lang.org/"))
+    assert_raise(NoMethodError) { Object.new.URI("http://www.ruby-lang.org/") }
+  end
+end
+
+
+end

Added: trunk/test/uri/test_ftp.rb
===================================================================
--- trunk/test/uri/test_ftp.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/uri/test_ftp.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,62 @@
+require 'test/unit'
+require 'uri/ftp'
+
+module URI
+
+
+class TestFTP < Test::Unit::TestCase
+  def setup
+  end
+
+  def test_parse
+    url = URI.parse('ftp://user:pass host.com/abc/def')
+    assert_kind_of(URI::FTP, url)
+
+    exp = [
+      'ftp',
+      'user:pass', 'host.com', URI::FTP.default_port, 
+      'abc/def', nil,
+    ]
+    ary = [
+      url.scheme, url.userinfo, url.host, url.port,
+      url.path, url.opaque
+    ]
+    assert_equal(exp, ary)
+
+    assert_equal('user', url.user)
+    assert_equal('pass', url.password)
+  end
+
+  def test_paths
+    # If you think what's below is wrong, please read RubyForge bug 2055, 
+    # RFC 1738 section 3.2.2, and RFC 2396.
+    u = URI.parse('ftp://ftp.example.com/foo/bar/file.ext')
+    assert(u.path == 'foo/bar/file.ext')
+    u = URI.parse('ftp://ftp.example.com//foo/bar/file.ext')
+    assert(u.path == '/foo/bar/file.ext')
+    u = URI.parse('ftp://ftp.example.com/%2Ffoo/bar/file.ext')
+    assert(u.path == '/foo/bar/file.ext')
+  end
+
+  def test_assemble
+    # uri/ftp is conservative and uses the older RFC 1738 rules, rather than
+    # assuming everyone else has implemented RFC 2396.
+    uri = URI::FTP.build(['user:password', 'ftp.example.com', nil, 
+                         '/path/file.zip', 'i'])
+    assert(uri.to_s == 
+           'ftp://user:password ftp.example.com/%2Fpath/file.zip;type=i')
+  end
+
+  def test_select
+    assert_equal(['ftp', 'a.b.c', 21], URI.parse('ftp://a.b.c/').select(:scheme, :host, :port))
+    u = URI.parse('ftp://a.b.c/')
+    ary = u.component.collect {|c| u.send(c)}
+    assert_equal(ary, u.select(*u.component))
+    assert_raises(ArgumentError) do
+      u.select(:scheme, :host, :not_exist, :port)
+    end
+  end
+end
+
+
+end

Added: trunk/test/uri/test_generic.rb
===================================================================
--- trunk/test/uri/test_generic.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/uri/test_generic.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,698 @@
+require 'test/unit'
+require 'uri'
+
+module URI
+
+
+class TestGeneric < Test::Unit::TestCase
+  def setup
+    @url = 'http://a/b/c/d;p?q'
+    @base_url = URI.parse(@url)
+  end
+
+  def teardown
+  end
+
+  def uri_to_ary(uri)
+    uri.class.component.collect {|c| uri.send(c)}
+  end
+
+  def test_parse
+    # 0
+    assert_kind_of(URI::HTTP, @base_url)
+
+    exp = [
+      'http', 
+      nil, 'a', URI::HTTP.default_port, 
+      '/b/c/d;p', 
+      'q',
+      nil
+    ]
+    ary = uri_to_ary(@base_url)
+    assert_equal(exp, ary)
+
+    # 1
+    url = URI.parse('ftp://ftp.is.co.za/rfc/rfc1808.txt')
+    assert_kind_of(URI::FTP, url)
+
+    exp = [
+      'ftp', 
+      nil, 'ftp.is.co.za', URI::FTP.default_port, 
+      'rfc/rfc1808.txt', nil,
+    ]
+    ary = uri_to_ary(url)
+    assert_equal(exp, ary)
+
+    # 2
+    url = URI.parse('gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles')
+    assert_kind_of(URI::Generic, url)
+
+    exp = [
+      'gopher', 
+      nil, 'spinaltap.micro.umn.edu', nil, nil,
+      '/00/Weather/California/Los%20Angeles', nil,
+      nil,
+      nil
+    ]
+    ary = uri_to_ary(url)
+    assert_equal(exp, ary)
+
+    # 3
+    url = URI.parse('http://www.math.uio.no/faq/compression-faq/part1.html')
+    assert_kind_of(URI::HTTP, url)
+
+    exp = [
+      'http', 
+      nil, 'www.math.uio.no', URI::HTTP.default_port, 
+      '/faq/compression-faq/part1.html', 
+      nil,
+      nil
+    ]
+    ary = uri_to_ary(url)
+    assert_equal(exp, ary)
+
+    # 4
+    url = URI.parse('mailto:mduerst ifi.unizh.ch')
+    assert_kind_of(URI::Generic, url)
+
+    exp = [
+      'mailto', 
+      'mduerst ifi.unizh.ch',
+      []
+    ]
+    ary = uri_to_ary(url)
+    assert_equal(exp, ary)
+
+    # 5
+    url = URI.parse('news:comp.infosystems.www.servers.unix')
+    assert_kind_of(URI::Generic, url)
+
+    exp = [
+      'news', 
+      nil, nil, nil, nil, 
+      nil, 'comp.infosystems.www.servers.unix',
+      nil,
+      nil
+    ]
+    ary = uri_to_ary(url)
+    assert_equal(exp, ary)
+
+    # 6
+    url = URI.parse('telnet://melvyl.ucop.edu/')
+    assert_kind_of(URI::Generic, url)
+
+    exp = [
+      'telnet', 
+      nil, 'melvyl.ucop.edu', nil, nil, 
+      '/', nil,
+      nil,
+      nil
+    ]
+    ary = uri_to_ary(url)
+    assert_equal(exp, ary)
+
+    # 7
+    # reported by Mr. Kubota <em6t-kbt asahi-net.or.jp>
+    assert_raises(URI::InvalidURIError) { URI.parse('http://a_b:80/') }
+    assert_raises(URI::InvalidURIError) { URI.parse('http://a_b/') }
+
+    # 8
+    # reported by m_seki
+    uri = URI.parse('file:///foo/bar.txt')
+    assert_kind_of(URI::Generic, url)
+    uri = URI.parse('file:/foo/bar.txt')
+    assert_kind_of(URI::Generic, url)
+
+    # 9
+    # [ruby-dev:25667]
+    url = URI.parse('ftp://:pass@localhost/')
+    assert_equal('', url.user)
+    assert_equal('pass', url.password)
+    assert_equal(':pass', url.userinfo)
+    url = URI.parse('ftp://user@localhost/')
+    assert_equal('user', url.user)
+    assert_equal(nil, url.password)
+    assert_equal('user', url.userinfo)
+    url = URI.parse('ftp://localhost/')
+    assert_equal(nil, url.user)
+    assert_equal(nil, url.password)
+    assert_equal(nil, url.userinfo)
+  end
+
+  def test_merge
+    u1 = URI.parse('http://foo')
+    u2 = URI.parse('http://foo/')
+    u3 = URI.parse('http://foo/bar')
+    u4 = URI.parse('http://foo/bar/')
+
+    assert_equal(URI.parse('http://foo/baz'), u1 + 'baz')
+    assert_equal(URI.parse('http://foo/baz'), u2 + 'baz')
+    assert_equal(URI.parse('http://foo/baz'), u3 + 'baz')
+    assert_equal(URI.parse('http://foo/bar/baz'), u4 + 'baz')
+
+    assert_equal(URI.parse('http://foo/baz'), u1 + '/baz')
+    assert_equal(URI.parse('http://foo/baz'), u2 + '/baz')
+    assert_equal(URI.parse('http://foo/baz'), u3 + '/baz')
+    assert_equal(URI.parse('http://foo/baz'), u4 + '/baz')
+
+    # from [ruby-dev:11508] Re: uri
+    url = URI.parse('http://hoge/a.html') + 'b.html'
+    assert_equal('http://hoge/b.html', url.to_s)
+
+    # reported by Mr. Kubota <em6t-kbt asahi-net.or.jp>
+    url = URI.parse('http://a/b') + 'http://x/y'
+    assert_equal('http://x/y', url.to_s)
+    assert_equal(url, URI.parse('')                     + 'http://x/y')
+    assert_equal(url, URI.parse('').normalize           + 'http://x/y')
+    assert_equal(url, URI.parse('http://a/b').normalize + 'http://x/y')
+
+    u = URI.parse('http://foo/bar/baz')
+    assert_equal(nil, u.merge!(""))
+    assert_equal(nil, u.merge!(u))
+    assert(nil != u.merge!("."))
+    assert_equal('http://foo/bar/', u.to_s)
+    assert(nil != u.merge!("../baz"))
+    assert_equal('http://foo/baz', u.to_s)
+
+    # [ruby-dev:23628]
+    u0 = URI.parse('mailto:foo example.com')
+    u1 = URI.parse('mailto:foo example.com#bar')
+    assert_equal(uri_to_ary(u0 + '#bar'), uri_to_ary(u1))
+
+    # [ruby-list:39838]
+    u0 = URI.parse('http://www.example.com/')
+    u1 = URI.parse('http://www.example.com/foo/..') + './'
+    assert_equal(u0, u1)
+    u0 = URI.parse('http://www.example.com/foo/')
+    u1 = URI.parse('http://www.example.com/foo/bar/..') + './'
+    assert_equal(u0, u1)
+    u0 = URI.parse('http://www.example.com/foo/bar/')
+    u1 = URI.parse('http://www.example.com/foo/bar/baz/..') + './'
+    assert_equal(u0, u1)
+    u0 = URI.parse('http://www.example.com/')
+    u1 = URI.parse('http://www.example.com/foo/bar/../..') + './'
+    assert_equal(u0, u1)
+    u0 = URI.parse('http://www.example.com/foo/')
+    u1 = URI.parse('http://www.example.com/foo/bar/baz/../..') + './'
+    assert_equal(u0, u1)
+
+    # [ruby-list:39844]
+    u = URI.parse('http://www.example.com/')
+    u0 = u + './foo/'
+    u1 = u + './foo/bar/..'
+    assert_equal(u0, u1)
+    u = URI.parse('http://www.example.com/')
+    u0 = u + './'
+    u1 = u + './foo/bar/../..'
+    assert_equal(u0, u1)
+  end
+
+  def test_route
+    url = URI.parse('http://hoge/a.html').route_to('http://hoge/b.html')
+    assert_equal('b.html', url.to_s)
+
+    url = URI.parse('http://hoge/a/').route_to('http://hoge/b/')
+    assert_equal('../b/', url.to_s)
+    url = URI.parse('http://hoge/a/b').route_to('http://hoge/b/')
+    assert_equal('../b/', url.to_s)
+
+    url = URI.parse('http://hoge/a/b/').route_to('http://hoge/b/')
+    assert_equal('../../b/', url.to_s)
+
+    url = URI.parse('http://hoge/a/b/').route_to('http://HOGE/b/')
+    assert_equal('../../b/', url.to_s)
+
+    url = URI.parse('http://hoge/a/b/').route_to('http://MOGE/b/')
+    assert_equal('//MOGE/b/', url.to_s)
+
+    url = URI.parse('file:///a/b/').route_to('file:///a/b/')
+    assert_equal('', url.to_s)
+
+    url = URI.parse('mailto:foo example.com').route_to('mailto:foo example.com#bar')
+    assert_equal('#bar', url.to_s)
+
+    url = URI.parse('mailto:foo example.com#bar').route_to('mailto:foo example.com')
+    assert_equal('', url.to_s)
+
+    url = URI.parse('mailto:foo example.com').route_to('mailto:foo example.com')
+    assert_equal('', url.to_s)
+  end
+
+  def test_rfc2396_examples
+#  http://a/b/c/d;p?q
+#        g:h           =  g:h
+    url = @base_url.merge('g:h')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g:h', url.to_s)
+    url = @base_url.route_to('g:h')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g:h', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g             =  http://a/b/c/g
+    url = @base_url.merge('g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ./g           =  http://a/b/c/g
+    url = @base_url.merge('./g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g')
+    assert_kind_of(URI::Generic, url)
+    assert('./g' != url.to_s) # ok
+    assert_equal('g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g/            =  http://a/b/c/g/
+    url = @base_url.merge('g/')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g/', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g/')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g/', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        /g            =  http://a/g
+    url = @base_url.merge('/g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/g', url.to_s)
+    url = @base_url.route_to('http://a/g')
+    assert_kind_of(URI::Generic, url)
+    assert('/g' != url.to_s) # ok
+    assert_equal('../../g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        //g           =  http://g
+    url = @base_url.merge('//g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://g', url.to_s)
+    url = @base_url.route_to('http://g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('//g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ?y            =  http://a/b/c/?y
+    url = @base_url.merge('?y')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/?y', url.to_s)
+    url = @base_url.route_to('http://a/b/c/?y')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('?y', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g?y           =  http://a/b/c/g?y
+    url = @base_url.merge('g?y')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g?y', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g?y')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g?y', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        #s            =  (current document)#s
+    url = @base_url.merge('#s')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal( base_url.to_s + '#s', url.to_s)
+    url = @base_url.route_to( base_url.to_s + '#s')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('#s', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g#s           =  http://a/b/c/g#s
+    url = @base_url.merge('g#s')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g#s', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g#s')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g#s', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g?y#s         =  http://a/b/c/g?y#s
+    url = @base_url.merge('g?y#s')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g?y#s', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g?y#s')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g?y#s', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ;x            =  http://a/b/c/;x
+    url = @base_url.merge(';x')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/;x', url.to_s)
+    url = @base_url.route_to('http://a/b/c/;x')
+    assert_kind_of(URI::Generic, url)
+    assert_equal(';x', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g;x           =  http://a/b/c/g;x
+    url = @base_url.merge('g;x')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g;x', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g;x')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g;x', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g;x?y#s       =  http://a/b/c/g;x?y#s
+    url = @base_url.merge('g;x?y#s')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g;x?y#s', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g;x?y#s')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g;x?y#s', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        .             =  http://a/b/c/
+    url = @base_url.merge('.')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/', url.to_s)
+    url = @base_url.route_to('http://a/b/c/')
+    assert_kind_of(URI::Generic, url)
+    assert('.' != url.to_s) # ok
+    assert_equal('./', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ./            =  http://a/b/c/
+    url = @base_url.merge('./')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/', url.to_s)
+    url = @base_url.route_to('http://a/b/c/')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('./', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ..            =  http://a/b/
+    url = @base_url.merge('..')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/', url.to_s)
+    url = @base_url.route_to('http://a/b/')
+    assert_kind_of(URI::Generic, url)
+    assert('..' != url.to_s) # ok
+    assert_equal('../', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ../           =  http://a/b/
+    url = @base_url.merge('../')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/', url.to_s)
+    url = @base_url.route_to('http://a/b/')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('../', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ../g          =  http://a/b/g
+    url = @base_url.merge('../g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/g', url.to_s)
+    url = @base_url.route_to('http://a/b/g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('../g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ../..         =  http://a/
+    url = @base_url.merge('../..')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/', url.to_s)
+    url = @base_url.route_to('http://a/')
+    assert_kind_of(URI::Generic, url)
+    assert('../..' != url.to_s) # ok
+    assert_equal('../../', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ../../        =  http://a/
+    url = @base_url.merge('../../')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/', url.to_s)
+    url = @base_url.route_to('http://a/')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('../../', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ../../g       =  http://a/g
+    url = @base_url.merge('../../g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/g', url.to_s)
+    url = @base_url.route_to('http://a/g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('../../g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        <>            =  (current document)
+    url = @base_url.merge('')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/d;p?q', url.to_s)
+    url = @base_url.route_to('http://a/b/c/d;p?q')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        /./g          =  http://a/./g
+    url = @base_url.merge('/./g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/./g', url.to_s)
+    url = @base_url.route_to('http://a/./g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('/./g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        /../g         =  http://a/../g
+    url = @base_url.merge('/../g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/../g', url.to_s)
+    url = @base_url.route_to('http://a/../g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('/../g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g.            =  http://a/b/c/g.
+    url = @base_url.merge('g.')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g.', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g.')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g.', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        .g            =  http://a/b/c/.g
+    url = @base_url.merge('.g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/.g', url.to_s)
+    url = @base_url.route_to('http://a/b/c/.g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('.g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g..           =  http://a/b/c/g..
+    url = @base_url.merge('g..')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g..', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g..')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g..', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ..g           =  http://a/b/c/..g
+    url = @base_url.merge('..g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/..g', url.to_s)
+    url = @base_url.route_to('http://a/b/c/..g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('..g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ../../../g    =  http://a/../g
+    url = @base_url.merge('../../../g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/../g', url.to_s)
+    url = @base_url.route_to('http://a/../g')
+    assert_kind_of(URI::Generic, url)
+    assert('../../../g' != url.to_s) # ok? yes, it confuses you
+    assert_equal('/../g', url.to_s)  # and it is clearly
+
+#  http://a/b/c/d;p?q
+#        ../../../../g =  http://a/../../g
+    url = @base_url.merge('../../../../g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/../../g', url.to_s)
+    url = @base_url.route_to('http://a/../../g')
+    assert_kind_of(URI::Generic, url)
+    assert('../../../../g' != url.to_s) # ok? yes, it confuses you
+    assert_equal('/../../g', url.to_s)  # and it is clearly
+
+#  http://a/b/c/d;p?q
+#        ./../g        =  http://a/b/g
+    url = @base_url.merge('./../g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/g', url.to_s)
+    url = @base_url.route_to('http://a/b/g')
+    assert_kind_of(URI::Generic, url)
+    assert('./../g' != url.to_s) # ok
+    assert_equal('../g', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        ./g/.         =  http://a/b/c/g/
+    url = @base_url.merge('./g/.')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g/', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g/')
+    assert_kind_of(URI::Generic, url)
+    assert('./g/.' != url.to_s) # ok
+    assert_equal('g/', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g/./h         =  http://a/b/c/g/h
+    url = @base_url.merge('g/./h')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g/h', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g/h')
+    assert_kind_of(URI::Generic, url)
+    assert('g/./h' != url.to_s) # ok
+    assert_equal('g/h', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g/../h        =  http://a/b/c/h
+    url = @base_url.merge('g/../h')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/h', url.to_s)
+    url = @base_url.route_to('http://a/b/c/h')
+    assert_kind_of(URI::Generic, url)
+    assert('g/../h' != url.to_s) # ok
+    assert_equal('h', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g;x=1/./y     =  http://a/b/c/g;x=1/y
+    url = @base_url.merge('g;x=1/./y')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g;x=1/y', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g;x=1/y')
+    assert_kind_of(URI::Generic, url)
+    assert('g;x=1/./y' != url.to_s) # ok
+    assert_equal('g;x=1/y', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g;x=1/../y    =  http://a/b/c/y
+    url = @base_url.merge('g;x=1/../y')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/y', url.to_s)
+    url = @base_url.route_to('http://a/b/c/y')
+    assert_kind_of(URI::Generic, url)
+    assert('g;x=1/../y' != url.to_s) # ok
+    assert_equal('y', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g?y/./x       =  http://a/b/c/g?y/./x
+    url = @base_url.merge('g?y/./x')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g?y/./x', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g?y/./x')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g?y/./x', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g?y/../x      =  http://a/b/c/g?y/../x
+    url = @base_url.merge('g?y/../x')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g?y/../x', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g?y/../x')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g?y/../x', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g#s/./x       =  http://a/b/c/g#s/./x
+    url = @base_url.merge('g#s/./x')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g#s/./x', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g#s/./x')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g#s/./x', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        g#s/../x      =  http://a/b/c/g#s/../x
+    url = @base_url.merge('g#s/../x')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http://a/b/c/g#s/../x', url.to_s)
+    url = @base_url.route_to('http://a/b/c/g#s/../x')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('g#s/../x', url.to_s)
+
+#  http://a/b/c/d;p?q
+#        http:g        =  http:g           ; for validating parsers
+#                      |  http://a/b/c/g   ; for backwards compatibility
+    url = @base_url.merge('http:g')
+    assert_kind_of(URI::HTTP, url)
+    assert_equal('http:g', url.to_s)
+    url = @base_url.route_to('http:g')
+    assert_kind_of(URI::Generic, url)
+    assert_equal('http:g', url.to_s)
+  end
+
+  def test_join
+    assert_equal(URI.parse('http://foo/bar'), URI.join('http://foo/bar'))
+    assert_equal(URI.parse('http://foo/bar'), URI.join('http://foo', 'bar'))
+    assert_equal(URI.parse('http://foo/bar/'), URI.join('http://foo', 'bar/'))
+
+    assert_equal(URI.parse('http://foo/baz'), URI.join('http://foo', 'bar', 'baz'))
+    assert_equal(URI.parse('http://foo/baz'), URI.join('http://foo', 'bar', '/baz'))
+    assert_equal(URI.parse('http://foo/baz/'), URI.join('http://foo', 'bar', '/baz/'))
+    assert_equal(URI.parse('http://foo/bar/baz'), URI.join('http://foo', 'bar/', 'baz'))
+    assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar', 'baz', 'hoge'))
+
+    assert_equal(URI.parse('http://foo/bar/baz'), URI.join('http://foo', 'bar/baz'))
+    assert_equal(URI.parse('http://foo/bar/hoge'), URI.join('http://foo', 'bar/baz', 'hoge'))
+    assert_equal(URI.parse('http://foo/bar/baz/hoge'), URI.join('http://foo', 'bar/baz/', 'hoge'))
+    assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
+    assert_equal(URI.parse('http://foo/bar/hoge'), URI.join('http://foo', 'bar/baz', 'hoge'))
+    assert_equal(URI.parse('http://foo/bar/baz/hoge'), URI.join('http://foo', 'bar/baz/', 'hoge'))
+    assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
+  end
+
+  # ruby-dev:16728
+  def test_set_component
+    uri = URI.parse('http://foo:bar@baz')
+    assert_equal('oof', uri.user = 'oof')
+    assert_equal('http://oof:bar@baz', uri.to_s)
+    assert_equal('rab', uri.password = 'rab')
+    assert_equal('http://oof:rab@baz', uri.to_s)
+    assert_equal('foo', uri.userinfo = 'foo')
+    assert_equal('http://foo:rab@baz', uri.to_s)
+    assert_equal(['foo', 'bar'], uri.userinfo = ['foo', 'bar'])
+    assert_equal('http://foo:bar@baz', uri.to_s)
+    assert_equal(['foo'], uri.userinfo = ['foo'])
+    assert_equal('http://foo:bar@baz', uri.to_s)
+    assert_equal('zab', uri.host = 'zab')
+    assert_equal('http://foo:bar@zab', uri.to_s)
+    assert_equal(8080, uri.port = 8080)
+    assert_equal('http://foo:bar@zab:8080', uri.to_s)
+    assert_equal('/', uri.path = '/')
+    assert_equal('http://foo:bar@zab:8080/', uri.to_s)
+    assert_equal('a=1', uri.query = 'a=1')
+    assert_equal('http://foo:bar@zab:8080/?a=1', uri.to_s)
+    assert_equal('b123', uri.fragment = 'b123')
+    assert_equal('http://foo:bar@zab:8080/?a=1#b123', uri.to_s)
+
+    uri = URI.parse('http://example.com')
+    assert_raises(URI::InvalidURIError) { uri.password = 'bar' }
+    uri.userinfo = 'foo:bar'
+    assert_equal('http://foo:bar example.com', uri.to_s)
+    assert_raises(URI::InvalidURIError) { uri.registry = 'bar' }
+    assert_raises(URI::InvalidURIError) { uri.opaque = 'bar' }
+
+    uri = URI.parse('mailto:foo example.com')
+    assert_raises(URI::InvalidURIError) { uri.user = 'bar' }
+    assert_raises(URI::InvalidURIError) { uri.password = 'bar' }
+    assert_raises(URI::InvalidURIError) { uri.userinfo = ['bar', 'baz'] }
+    assert_raises(URI::InvalidURIError) { uri.host = 'bar' }
+    assert_raises(URI::InvalidURIError) { uri.port = 'bar' }
+    assert_raises(URI::InvalidURIError) { uri.path = 'bar' }
+    assert_raises(URI::InvalidURIError) { uri.query = 'bar' }
+  end
+end
+
+
+end

Added: trunk/test/uri/test_http.rb
===================================================================
--- trunk/test/uri/test_http.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/uri/test_http.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,63 @@
+require 'test/unit'
+require 'uri/http'
+
+module URI
+
+
+class TestHTTP < Test::Unit::TestCase
+  def setup
+  end
+
+  def teardown
+  end
+
+  def uri_to_ary(uri)
+    uri.class.component.collect {|c| uri.send(c)}
+  end
+
+  def test_parse
+    u = URI.parse('http://a')
+    assert_kind_of(URI::HTTP, u)
+    assert_equal(['http', 
+		   nil, 'a', URI::HTTP.default_port,
+		   '', nil, nil], uri_to_ary(u))
+  end
+
+  def test_normalize
+    host = 'aBcD'
+    u1 = URI.parse('http://' + host          + '/eFg?HiJ')
+    u2 = URI.parse('http://' + host.downcase + '/eFg?HiJ')
+    assert(u1.normalize.host == 'abcd')
+    assert(u1.normalize.path == u1.path)
+    assert(u1.normalize == u2.normalize)
+    assert(!u1.normalize.host.equal?(u1.host))
+    assert( u2.normalize.host.equal?(u2.host))
+
+    assert_equal('http://abc/', URI.parse('http://abc').normalize.to_s)
+  end
+
+  def test_equal
+    assert(URI.parse('http://abc') == URI.parse('http://ABC'))
+    assert(URI.parse('http://abc/def') == URI.parse('http://ABC/def'))
+    assert(URI.parse('http://abc/def') != URI.parse('http://ABC/DEF'))
+  end
+
+  def test_request_uri
+    assert_equal('/',         URI.parse('http://a.b.c/').request_uri)
+    assert_equal('/?abc=def', URI.parse('http://a.b.c/?abc=def').request_uri)
+    assert_equal('/',         URI.parse('http://a.b.c').request_uri)
+    assert_equal('/?abc=def', URI.parse('http://a.b.c?abc=def').request_uri)
+  end
+
+  def test_select
+    assert_equal(['http', 'a.b.c', 80], URI.parse('http://a.b.c/').select(:scheme, :host, :port))
+    u = URI.parse('http://a.b.c/')
+    assert_equal(uri_to_ary(u), u.select(*u.component))
+    assert_raises(ArgumentError) do
+      u.select(:scheme, :host, :not_exist, :port)
+    end
+  end
+end
+
+
+end

Added: trunk/test/uri/test_ldap.rb
===================================================================
--- trunk/test/uri/test_ldap.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/uri/test_ldap.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,100 @@
+require 'test/unit'
+require 'uri/ldap'
+
+module URI
+
+
+class TestLDAP < Test::Unit::TestCase
+  def setup
+  end
+
+  def teardown
+  end
+
+  def uri_to_ary(uri)
+    uri.class.component.collect {|c| uri.send(c)}
+  end
+
+  def test_parse
+    url = 'ldap://ldap.jaist.ac.jp/o=JAIST,c=JP?sn?base?(sn=ttate*)'
+    u = URI.parse(url)
+    assert_kind_of(URI::LDAP, u)
+    assert_equal(url, u.to_s)
+    assert_equal('o=JAIST,c=JP', u.dn)
+    assert_equal('sn', u.attributes)
+    assert_equal('base', u.scope)
+    assert_equal('(sn=ttate*)', u.filter)
+    assert_equal(nil, u.extensions)
+
+    u.scope = URI::LDAP::SCOPE_SUB
+    u.attributes = 'sn,cn,mail'
+    assert_equal('ldap://ldap.jaist.ac.jp/o=JAIST,c=JP?sn,cn,mail?sub?(sn=ttate*)', u.to_s)
+    assert_equal('o=JAIST,c=JP', u.dn)
+    assert_equal('sn,cn,mail', u.attributes)
+    assert_equal('sub', u.scope)
+    assert_equal('(sn=ttate*)', u.filter)
+    assert_equal(nil, u.extensions)
+
+    # from RFC2255, section 6.
+    urls = {
+      'ldap:///o=University%20of%20Michigan,c=US' =>
+      ['ldap', nil, URI::LDAP::DEFAULT_PORT, 
+	'o=University%20of%20Michigan,c=US', 
+	nil, nil, nil, nil],
+
+      'ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US' =>
+      ['ldap', 'ldap.itd.umich.edu', URI::LDAP::DEFAULT_PORT, 
+	'o=University%20of%20Michigan,c=US', 
+	nil, nil, nil, nil],
+
+      'ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US?postalAddress' =>
+      ['ldap', 'ldap.itd.umich.edu', URI::LDAP::DEFAULT_PORT, 
+	'o=University%20of%20Michigan,c=US',
+	'postalAddress', nil, nil, nil],
+
+      'ldap://host.com:6666/o=University%20of%20Michigan,c=US??sub?(cn=Babs%20Jensen)' =>
+      ['ldap', 'host.com', 6666, 
+	'o=University%20of%20Michigan,c=US',
+	nil, 'sub', '(cn=Babs%20Jensen)', nil],
+
+      'ldap://ldap.itd.umich.edu/c=GB?objectClass?one' =>
+      ['ldap', 'ldap.itd.umich.edu', URI::LDAP::DEFAULT_PORT, 
+	'c=GB', 
+	'objectClass', 'one', nil, nil],
+
+      'ldap://ldap.question.com/o=Question%3f,c=US?mail' =>
+      ['ldap', 'ldap.question.com', URI::LDAP::DEFAULT_PORT, 
+	'o=Question%3f,c=US',
+	'mail', nil, nil, nil],
+
+      'ldap://ldap.netscape.com/o=Babsco,c=US??(int=%5c00%5c00%5c00%5c04)' =>
+      ['ldap', 'ldap.netscape.com', URI::LDAP::DEFAULT_PORT, 
+	'o=Babsco,c=US',
+	nil, '(int=%5c00%5c00%5c00%5c04)', nil, nil],
+
+      'ldap:///??sub??bindname=cn=Manager%2co=Foo' =>
+      ['ldap', nil, URI::LDAP::DEFAULT_PORT, 
+	'',
+	nil, 'sub', nil, 'bindname=cn=Manager%2co=Foo'],
+
+      'ldap:///??sub??!bindname=cn=Manager%2co=Foo' =>
+      ['ldap', nil, URI::LDAP::DEFAULT_PORT, 
+	'',
+	nil, 'sub', nil, '!bindname=cn=Manager%2co=Foo'],
+    }.each do |url, ary|
+      u = URI.parse(url)
+      assert_equal(ary, uri_to_ary(u))
+    end
+  end
+
+  def test_select
+    u = URI.parse('ldap:///??sub??!bindname=cn=Manager%2co=Foo')
+    assert_equal(uri_to_ary(u), u.select(*u.component))
+    assert_raises(ArgumentError) do
+      u.select(:scheme, :host, :not_exist, :port)
+    end
+  end
+end
+
+
+end

Added: trunk/test/uri/test_mailto.rb
===================================================================
--- trunk/test/uri/test_mailto.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test/uri/test_mailto.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -0,0 +1,122 @@
+require 'test/unit'
+require 'uri/mailto'
+
+module URI
+
+
+class TestMailTo < Test::Unit::TestCase
+  def setup
+    @u = URI::MailTo
+  end
+
+  def teardown
+  end
+
+  def uri_to_ary(uri)
+    uri.class.component.collect {|c| uri.send(c)}
+  end
+
+  def test_build
+    ok = []
+    bad = []
+
+    # RFC2368, 6. Examples
+    # mailto:chris example.com
+    ok << ["mailto:chris example.com"]
+    ok[-1] << ["chris example.com", nil]
+    ok[-1] << {:to => "chris example.com"}
+
+    # mailto:infobot example.com?subject=current-issue
+    ok << ["mailto:infobot example.com?subject=current-issue"]
+    ok[-1] << ["infobot example.com", ["subject=current-issue"]]
+    ok[-1] << {:to => "infobot example.com", 
+      :headers => ["subject=current-issue"]}
+
+    # mailto:infobot example.com?body=send%20current-issue
+    ok << ["mailto:infobot example.com?body=send%20current-issue"]
+    ok[-1] << ["infobot example.com", ["body=send%20current-issue"]]
+    ok[-1] << {:to => "infobot example.com", 
+      :headers => ["body=send%20current-issue"]}
+
+    # mailto:infobot example.com?body=send%20current-issue%0D%0Asend%20index
+    ok << ["mailto:infobot example.com?body=send%20current-issue%0D%0Asend%20index"]
+    ok[-1] << ["infobot example.com", 
+      ["body=send%20current-issue%0D%0Asend%20index"]]
+    ok[-1] << {:to => "infobot example.com", 
+      :headers => ["body=send%20current-issue%0D%0Asend%20index"]}
+
+    # mailto:foobar example.com?In-Reply-To=%3c3469A91.D10AF4C example.com
+    ok << ["mailto:foobar example.com?In-Reply-To=%3c3469A91.D10AF4C example.com"]
+    ok[-1] << ["foobar example.com", 
+      ["In-Reply-To=%3c3469A91.D10AF4C example.com"]]
+    ok[-1] << {:to => "foobar example.com", 
+      :headers => ["In-Reply-To=%3c3469A91.D10AF4C example.com"]}
+
+    # mailto:majordomo example.com?body=subscribe%20bamboo-l
+    ok << ["mailto:majordomo example.com?body=subscribe%20bamboo-l"]
+    ok[-1] << ["majordomo example.com", ["body=subscribe%20bamboo-l"]]
+    ok[-1] << {:to => "majordomo example.com", 
+      :headers => ["body=subscribe%20bamboo-l"]}
+
+    # mailto:joe example.com?cc=bob example.com&body=hello
+    ok << ["mailto:joe example.com?cc=bob example.com&body=hello"]
+    ok[-1] << ["joe example.com", ["cc=bob example.com", "body=hello"]]
+    ok[-1] << {:to => "joe example.com", 
+      :headers => ["cc=bob example.com", "body=hello"]}
+
+    # mailto:?to=joe example.com&cc=bob example.com&body=hello
+    ok << ["mailto:?to=joe example.com&cc=bob example.com&body=hello"]
+    ok[-1] << [nil, 
+      ["to=joe example.com", "cc=bob example.com", "body=hello"]]
+    ok[-1] << {:headers => ["to=joe example.com", 
+	"cc=bob example.com", "body=hello"]}
+
+    # mailto:gorby%25kremvax example.com
+    ok << ["mailto:gorby%25kremvax example.com"]
+    ok[-1] << ["gorby%25kremvax example.com", nil]
+    ok[-1] << {:to => "gorby%25kremvax example.com"}
+
+    # mailto:unlikely%3Faddress example.com?blat=foop
+    ok << ["mailto:unlikely%3Faddress example.com?blat=foop"]
+    ok[-1] << ["unlikely%3Faddress example.com", ["blat=foop"]]
+    ok[-1] << {:to => "unlikely%3Faddress example.com", 
+      :headers => ["blat=foop"]}
+
+    ok_all = ok.flatten.join("\0")
+
+    # mailto:joe example.com?cc=bob example.com?body=hello   ; WRONG!
+    bad << ["joe example.com", ["cc=bob example.com?body=hello"]]
+
+    # mailto:javascript:alert()
+    bad << ["javascript:alert()", []]
+
+    # '=' which is in hname or hvalue is wrong.
+    bad << ["foo example.jp?subject=1+1=2", []]
+
+    ok.each do |x|
+      assert_equal(x[0],
+		   @u.build(x[1]).to_s)
+      assert_equal(x[0],
+		   @u.build(x[2]).to_s)
+    end
+
+    bad.each do |x|
+      assert_raises(URI::InvalidComponentError) {
+	@u.build(x)
+      }
+    end
+
+    assert_equal(ok_all, ok.flatten.join("\0"))
+  end
+
+  def test_select
+    u = URI.parse('mailto:joe example.com?cc=bob example.com&body=hello')
+    assert_equal(uri_to_ary(u), u.select(*u.component))
+    assert_raises(ArgumentError) do
+      u.select(:scheme, :host, :not_exist, :port)
+    end
+  end
+end
+
+
+end

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/test.rb	2006-02-14 09:20:57 UTC (rev 417)
@@ -1,3 +1,27 @@
+require 'test/unit'
+class TestFoo < Test::Unit::TestCase
+  define_method(:test_foo){
+  }
+end
+
+
+__END__
+
+p Proc.new{}
+
+__END__
+require "rexml/document"
+include REXML  # so that we don't have to prefix everything with REXML::...
+string = <<EOF
+  <mydoc>
+    <someelement attribute="nanoo">Text, text, text</someelement>
+  </mydoc>
+EOF
+doc = Document.new string
+p doc
+
+__END__
+
 #!/usr/local/bin/ruby
 require 'webrick'
 include WEBrick

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2006-02-14 09:20:41 UTC (rev 416)
+++ trunk/yarvcore.c	2006-02-14 09:20:57 UTC (rev 417)
@@ -909,7 +909,13 @@
     }
 }
 
+int
+rb_proc_arity(VALUE proc)
+{
+    return FIX2INT(proc_arity(proc));
+}
 
+
 /***************/
 /* YarvBinding */
 /***************/


-- 
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]