mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11708 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			591 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			591 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
#
 | 
						|
# This test program is contributed by   George Marrows
 | 
						|
# Re: [Yarv-devel] Some tests	for test_jump.rb
 | 
						|
#
 | 
						|
 | 
						|
require 'yarvtest/yarvtest'
 | 
						|
 | 
						|
class TestFlow < YarvTestBase
 | 
						|
  def ae_flow(src, for_value=true)
 | 
						|
    # Tracks flow through the code
 | 
						|
    # A test like
 | 
						|
    #   begin
 | 
						|
    #   ensure
 | 
						|
    #   end
 | 
						|
    # gets transformed into
 | 
						|
    #   a = []
 | 
						|
    #   begin
 | 
						|
    #     begin; a << 1
 | 
						|
    #     ensure; a << 2
 | 
						|
    #     end; a << 3
 | 
						|
    #   rescue Exception
 | 
						|
    #     a << 99
 | 
						|
    #   end
 | 
						|
    #   a
 | 
						|
    # before being run. This tracks control flow through the code.
 | 
						|
    
 | 
						|
    cnt = 0
 | 
						|
    src = src.gsub(/(\n|$)/) { "; $a << #{cnt+=1}\n" }
 | 
						|
    src = "$a = []; begin; #{src}; rescue Exception; $a << 99; end; $a"
 | 
						|
    
 | 
						|
    if false#||true
 | 
						|
      STDERR.puts
 | 
						|
      STDERR.puts '#----'
 | 
						|
      STDERR.puts src
 | 
						|
      STDERR.puts '#----'
 | 
						|
    end
 | 
						|
    
 | 
						|
    ae(src)
 | 
						|
  end
 | 
						|
 | 
						|
  def test_while_with_ensure
 | 
						|
    ae %q{
 | 
						|
      a = []
 | 
						|
      i = 0
 | 
						|
      begin
 | 
						|
        while i < 1
 | 
						|
          i+=1
 | 
						|
          begin
 | 
						|
            begin
 | 
						|
              next
 | 
						|
            ensure
 | 
						|
              a << :ok
 | 
						|
            end
 | 
						|
          ensure
 | 
						|
            a << :ok2
 | 
						|
          end
 | 
						|
        end
 | 
						|
      ensure
 | 
						|
        a << :last
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae %q{
 | 
						|
      a = []
 | 
						|
      i = 0
 | 
						|
      begin
 | 
						|
        while i < 1
 | 
						|
          i+=1
 | 
						|
          begin
 | 
						|
            begin
 | 
						|
              break
 | 
						|
            ensure
 | 
						|
              a << :ok
 | 
						|
            end
 | 
						|
          ensure
 | 
						|
            a << :ok2
 | 
						|
          end
 | 
						|
        end
 | 
						|
      ensure
 | 
						|
        a << :last
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae %q{
 | 
						|
      a = []
 | 
						|
      i = 0
 | 
						|
      begin
 | 
						|
        while i < 1
 | 
						|
          if i>0
 | 
						|
            break
 | 
						|
          end
 | 
						|
          i+=1
 | 
						|
          begin
 | 
						|
            begin
 | 
						|
              redo
 | 
						|
            ensure
 | 
						|
              a << :ok
 | 
						|
            end
 | 
						|
          ensure
 | 
						|
            a << :ok2
 | 
						|
          end
 | 
						|
        end
 | 
						|
      ensure
 | 
						|
        a << :last
 | 
						|
      end
 | 
						|
   }
 | 
						|
  end
 | 
						|
  
 | 
						|
  def test_ensure_normal_flow
 | 
						|
    ae_flow %{ 
 | 
						|
      begin
 | 
						|
      ensure
 | 
						|
      end }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_ensure_exception
 | 
						|
    ae_flow %{
 | 
						|
      begin
 | 
						|
        raise StandardError
 | 
						|
      ensure
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_break_in_block_runs_ensure
 | 
						|
    ae_flow %{ 
 | 
						|
      [1,2].each do
 | 
						|
        begin
 | 
						|
          break
 | 
						|
        ensure
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_next_in_block_runs_ensure
 | 
						|
    ae_flow %{ 
 | 
						|
      [1,2].each do
 | 
						|
        begin
 | 
						|
          next
 | 
						|
        ensure
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
  def test_return_from_method_runs_ensure
 | 
						|
    ae_flow %{ 
 | 
						|
      o = "test"
 | 
						|
      def o.test(a)
 | 
						|
        return a
 | 
						|
      ensure
 | 
						|
      end
 | 
						|
      o.test(123)
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_break_from_ifunc
 | 
						|
    ae %q{
 | 
						|
      ["a"].inject("ng"){|x,y|
 | 
						|
        break :ok
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ae %q{
 | 
						|
      unless ''.respond_to? :lines
 | 
						|
        class String
 | 
						|
          def lines
 | 
						|
            self
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
      
 | 
						|
      ('a').lines.map{|e|
 | 
						|
        break :ok
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      ["a"].inject("ng"){|x,y|
 | 
						|
        break :ok
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      ('a'..'b').map{|e|
 | 
						|
        break :ok
 | 
						|
      }
 | 
						|
    }
 | 
						|
  end
 | 
						|
  
 | 
						|
  def test_break_ensure_interaction1
 | 
						|
    # make sure that any 'break state' set up in the VM is c
 | 
						|
    # the time of the ensure
 | 
						|
    ae_flow %{ 
 | 
						|
      [1,2].each{
 | 
						|
        break
 | 
						|
      }
 | 
						|
      begin
 | 
						|
      ensure
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
  
 | 
						|
  def test_break_ensure_interaction2
 | 
						|
    # ditto, different arrangement
 | 
						|
    ae_flow %{ 
 | 
						|
      begin
 | 
						|
        [1,2].each do
 | 
						|
          break
 | 
						|
        end
 | 
						|
      ensure
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
  
 | 
						|
  def test_break_through_2_ensures
 | 
						|
    ae_flow %{ 
 | 
						|
      [1,2].each do
 | 
						|
        begin
 | 
						|
          begin
 | 
						|
            break
 | 
						|
          ensure
 | 
						|
          end
 | 
						|
        ensure
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
  
 | 
						|
  def test_ensure_break_ensure
 | 
						|
    # break through an ensure; run 2nd normally
 | 
						|
    ae_flow %{ 
 | 
						|
      begin
 | 
						|
        [1,2].each do
 | 
						|
          begin
 | 
						|
            break
 | 
						|
          ensure
 | 
						|
          end
 | 
						|
        end
 | 
						|
      ensure
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
  
 | 
						|
  def test_exception_overrides_break
 | 
						|
    ae_flow %{ 
 | 
						|
      [1,2].each do
 | 
						|
        begin
 | 
						|
          break
 | 
						|
        ensure
 | 
						|
          raise StandardError
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_break_overrides_exception
 | 
						|
    ae_flow %{ 
 | 
						|
      [1,2].each do
 | 
						|
        begin
 | 
						|
          raise StandardError
 | 
						|
        ensure
 | 
						|
          break
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %{ 
 | 
						|
      [1,2].each do
 | 
						|
        begin
 | 
						|
          raise StandardError
 | 
						|
        rescue
 | 
						|
          break
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_break_in_exception
 | 
						|
    ae_flow %q{
 | 
						|
      i=0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        begin
 | 
						|
        ensure
 | 
						|
          break
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      i=0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        begin
 | 
						|
          raise
 | 
						|
        ensure
 | 
						|
          break
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      i=0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        begin
 | 
						|
          raise
 | 
						|
        rescue
 | 
						|
          break
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_next_in_exception
 | 
						|
    return
 | 
						|
    ae_flow %q{
 | 
						|
      i=0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        begin
 | 
						|
        ensure
 | 
						|
          next
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      i=0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        begin
 | 
						|
          raise
 | 
						|
        ensure
 | 
						|
          next
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      i=0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        begin
 | 
						|
          raise
 | 
						|
        rescue
 | 
						|
          next
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_complex_break
 | 
						|
    ae_flow %q{
 | 
						|
      i = 0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        j = 0
 | 
						|
        while j<3
 | 
						|
          j+=1
 | 
						|
          begin
 | 
						|
            raise
 | 
						|
          rescue
 | 
						|
            break
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      i = 0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        j = 0
 | 
						|
        while j<3
 | 
						|
          j+=1
 | 
						|
          1.times{
 | 
						|
            begin
 | 
						|
              raise
 | 
						|
            rescue
 | 
						|
              break
 | 
						|
            end
 | 
						|
          }
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      i = 0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        j = 0
 | 
						|
        while j<3
 | 
						|
          j+=1
 | 
						|
          begin
 | 
						|
            raise
 | 
						|
          ensure
 | 
						|
            break
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      i = 0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        j = 0
 | 
						|
        while j<3
 | 
						|
          j+=1
 | 
						|
          1.times{
 | 
						|
            begin
 | 
						|
              raise
 | 
						|
            ensure
 | 
						|
              break
 | 
						|
            end
 | 
						|
          }
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      while true
 | 
						|
        begin
 | 
						|
          break
 | 
						|
        ensure
 | 
						|
          break
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      while true
 | 
						|
        begin
 | 
						|
          break
 | 
						|
        ensure
 | 
						|
          raise
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_jump_from_class
 | 
						|
    ae_flow %q{
 | 
						|
      3.times{
 | 
						|
        class C
 | 
						|
          break
 | 
						|
        end
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      3.times{
 | 
						|
        class A
 | 
						|
          class B
 | 
						|
            break
 | 
						|
          end
 | 
						|
        end
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      3.times{
 | 
						|
        class C
 | 
						|
          next
 | 
						|
        end
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      3.times{
 | 
						|
        class C
 | 
						|
          class D
 | 
						|
            next
 | 
						|
          end
 | 
						|
        end
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      while true
 | 
						|
        class C
 | 
						|
          break
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      while true
 | 
						|
        class C
 | 
						|
          class D
 | 
						|
            break
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      i=0
 | 
						|
      while i<3
 | 
						|
        i+=1
 | 
						|
        class C
 | 
						|
          next 10
 | 
						|
        end
 | 
						|
      end
 | 
						|
    }
 | 
						|
    ae %q{
 | 
						|
      1.times{
 | 
						|
        while true
 | 
						|
          class C
 | 
						|
            begin
 | 
						|
              break
 | 
						|
            ensure
 | 
						|
              break
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
      }
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_flow_with_cont_sp
 | 
						|
    ae %q{
 | 
						|
      def m a, b
 | 
						|
        a + b
 | 
						|
      end
 | 
						|
      m(1,
 | 
						|
        while true
 | 
						|
          break 2
 | 
						|
        end
 | 
						|
        )
 | 
						|
    }
 | 
						|
    ae %q{
 | 
						|
      def m a, b
 | 
						|
        a + b
 | 
						|
      end
 | 
						|
      m(1,
 | 
						|
        (i=0; while i<2
 | 
						|
           i+=1
 | 
						|
           class C
 | 
						|
             next 2
 | 
						|
           end
 | 
						|
         end; 3)
 | 
						|
        )
 | 
						|
    }
 | 
						|
    ae %q{
 | 
						|
      def m a, b
 | 
						|
        a+b
 | 
						|
      end
 | 
						|
      m(1, 1.times{break 3}) +
 | 
						|
      m(10, (1.times{next 3}; 20))
 | 
						|
    }
 | 
						|
  end
 | 
						|
 | 
						|
  def test_return_in_deep_stack
 | 
						|
    ae_flow %q{
 | 
						|
      def m1 *args
 | 
						|
        
 | 
						|
      end
 | 
						|
      def m2
 | 
						|
        m1(:a, :b, (return 1; :c))
 | 
						|
      end
 | 
						|
      m2
 | 
						|
    }
 | 
						|
  end
 | 
						|
  
 | 
						|
  def test_return_in_ensure
 | 
						|
    ae_flow %q{
 | 
						|
      def m()
 | 
						|
        begin
 | 
						|
          2
 | 
						|
        ensure
 | 
						|
          return 3
 | 
						|
        end
 | 
						|
      end
 | 
						|
      m
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      def m2
 | 
						|
      end
 | 
						|
      def m()
 | 
						|
        m2(begin
 | 
						|
             2
 | 
						|
           ensure
 | 
						|
             return 3
 | 
						|
           end)
 | 
						|
        4
 | 
						|
      end
 | 
						|
      m()
 | 
						|
    }
 | 
						|
    ae_flow %q{
 | 
						|
      def m
 | 
						|
        1
 | 
						|
        1.times{
 | 
						|
          2
 | 
						|
          begin
 | 
						|
            3
 | 
						|
            return
 | 
						|
            4
 | 
						|
          ensure
 | 
						|
            5
 | 
						|
          end
 | 
						|
          6
 | 
						|
        }
 | 
						|
        7
 | 
						|
      end
 | 
						|
      m()
 | 
						|
    }
 | 
						|
  end
 | 
						|
end
 | 
						|
 |