add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/matchers.rb
File: matchers.rb
===================================================================
--- [no source file]
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/matchers.rb;netinterop1
@@ -1,0 +1,48 @@
+class BeAbleToLoadMatcher
+  def initialize(assembly)
+    @assembly = assembly
+    @loaders = []
+  end
+
+  def with(method, success = true)
+    @loaders << [method, success]
+    self
+  end
+
+  alias followed_by with 
+  
+  def twice
+    @loaders << @loaders.last
+    self
+  end
+
+  def once
+    flip = @loaders.last.dup
+    flip[1] = !flip[1]
+    @loaders << flip
+    self
+  end
+
+  def matches?(engine)
+    @result = []
+    @loaders.each do |loader|
+      @result = [(engine.execute("#{loader[0].to_s} '#{@assembly}'") == loader[1]), loader]
+      break unless @result.all?
+    end
+    @result.all?
+  end
+
+  def failure_message
+    ["Expected to be able to #{@result.last[0]}", "the assembly #{@assembly}"]
+  end
+
+  def negative_failure_message
+    ["Expected not to be able to #{@result.last[0]}", "the assembly #{@assembly}"]
+  end
+end
+
+class Object
+  def be_able_to_load(assembly)
+    BeAbleToLoadMatcher.new(assembly)
+  end
+end
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/spec_helper.rb;C645339
File: spec_helper.rb
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/spec_helper.rb;C645339  (server)    2/5/2009 2:23 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/spec_helper.rb;netinterop1
@@ -13,6 +13,26 @@
     require 'mspec/matchers/equal_utf16'
     require 'mspec/matchers/match_yaml'
 
+    # Code to setup HOME directory correctly on Windows
+    # This duplicates Ruby 1.9 semantics for defining HOME
+    platform_is :windows do
+      if ENV['HOME']
+        ENV['HOME'] = ENV['HOME'].tr '\\', '/'
+      elsif ENV['HOMEDIR'] && ENV['HOMEDRIVE']
+        ENV['HOME'] = File.join(ENV['HOMEDRIVE'], ENV['HOMEDIR'])
+      elsif ENV['HOMEDIR']
+        ENV['HOME'] = ENV['HOMEDIR']
+      elsif ENV['HOMEDRIVE']
+        ENV['HOME'] = ENV['HOMEDRIVE']
+      elsif ENV['USERPROFILE']
+        ENV['HOME'] = ENV['USERPROFILE']
+      else
+        puts "No suitable HOME environment found. This means that all of"
+        puts "HOME, HOMEDIR, HOMEDRIVE, and USERPROFILE are not set"
+        exit 1
+      end
+    end
+
     TOLERANCE = 0.00003 unless Object.const_defined?(:TOLERANCE)
   rescue LoadError
     puts "Please install the MSpec gem to run the specs."
@@ -20,18 +40,13 @@
   end
 end
 
-v = MSpec::VERSION.split('.').collect { |d| "1%02d" % d.to_i }.join.to_i
-unless v >= 101104100
-  puts "Please install MSpec version >= 1.4.0 to run the specs"
+minimum_version = "1.5.6"
+unless MSpec::VERSION >= minimum_version
+  puts "Please install MSpec version >= #{minimum_version} to run the specs"
   exit 1
 end
 
 $VERBOSE = nil unless ENV['OUTPUT_WARNINGS']
+require 'matchers'
 
-def has_tty?
-  if STDOUT.tty? then
-    yield
-  end
-end
-
 $: << (ENV["MERLIN_ROOT"] + "\\Bin\\Debug")
===================================================================
add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/load/custom_assembly_spec.rb
File: custom_assembly_spec.rb
===================================================================
--- [no source file]
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/load/custom_assembly_spec.rb;netinterop1
@@ -1,0 +1,150 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+require File.dirname(__FILE__) + '/shared/load'
+require 'ironruby'
+
+describe "Custom Assembly" do
+  before :each do
+    @engine = IronRuby.create_engine
+    str = "$: << '#{ENV["MERLIN_ROOT"] + "\\Bin\\Debug\\"}'".gsub("\\", "/")
+    @engine.execute(str)
+    @assembly = 'rowantest.baseclasscs.dll'
+  end
+
+  after :each do
+    #TODO: Does this release the engine enough to allow GC? We don't want a
+    #ton of wasted interpreters hanging around.
+    @engine = nil
+  end
+
+  describe "single load" do
+    it "works via require" do
+      @engine.execute("require '#{@assembly}'")
+      @engine.execute("$\"").should == [@assembly]
+    end
+
+    it "works via load" do
+      @engine.execute("load '#{@assembly}'")
+      lambda {@engine.execute("Merlin::Testing::BaseClass::EmptyClass")}.should_not raise_error(NameError)
+    end
+
+    it "works via load_assembly" do
+      lambda {@engine.execute("load_assembly '#{@assembly}'")}.should raise_error(LoadError)
+    end
+  end
+
+  describe "Repeated loading" do
+    it "only loads once with require followed by require" do
+      @engine.should be_able_to_load(@assembly).with('require').once
+    end
+
+    it "loads twice with require followed by load" do
+      @engine.should be_able_to_load(@assembly).with('require').followed_by('load')
+    end
+
+    it "loads twice with load followed by require" do
+      @engine.should be_able_to_load(@assembly).with('load').followed_by('require')
+    end
+    
+    it "loads twice with load followed by load" do
+      @engine.should be_able_to_load(@assembly).with('load').twice
+    end
+  end
+end
+
+describe "Custom Assembly with StrongName" do
+  before :each do
+    @engine = IronRuby.create_engine
+    str = "$: << '#{ENV["MERLIN_ROOT"] + "\\Bin\\Debug\\"}'".gsub("\\", "/")
+    @engine.execute(str)
+    @assembly = 'rowantest.baseclasscs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
+  end
+
+  after :each do
+    #TODO: Does this release the engine enough to allow GC? We don't want a
+    #ton of wasted interpreters hanging around.
+    @engine = nil
+  end
+
+  describe "single time loading" do
+    it "works via require" do
+      @engine.execute("require '#{@assembly}'")
+      @engine.execute("$\"").should == [@assembly]
+    end
+
+    it "works via load" do
+      @engine.execute("load '#{@assembly}'")
+      lambda {@engine.execute("Merlin::Testing::BaseClass::EmptyClass")}.should_not raise_error(NameError)
+    end
+
+    it "works via load_assembly" do
+      @engine.execute("load_assembly '#{@assembly}'")
+      lambda {@engine.execute("Merlin::Testing::BaseClass::EmptyClass")}.should_not raise_error(NameError)
+    end
+  end
+
+  describe "Repeated loading" do
+    it_behaves_like :repeated_net_assembly, nil
+  end
+end
+
+describe "Loading of custom assembly outside of the load path" do
+  it "raises a LoadError" do
+    engine = IronRuby.create_engine
+    lambda {engine.execute("require 'rowantest.baseclasscs'")}.should raise_error(LoadError)
+    lambda {engine.execute("load 'rowantest.baseclasscs.dll'")}.should raise_error(LoadError)
+    lambda {engine.execute("load_assembly 'rowantest.baseclasscs.dll'")}.should raise_error(LoadError)
+  end
+
+  it "doesn't raise LoadError for strong names" do 
+    engine = IronRuby.create_engine
+    lambda {engine.execute("require 'rowantest.baseclasscs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'")}.should_not raise_error(LoadError)
+    lambda {engine.execute("load 'rowantest.baseclasscs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'")}.should_not raise_error(LoadError)
+    lambda {engine.execute("load_assembly 'rowantest.baseclasscs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'")}.should_not raise_error(LoadError)
+  end
+end
+
+
+describe "Modifying and reloading custom assembly" do 
+  before :each do
+    @engine = IronRuby.create_engine
+    @scope = @engine.create_scope
+    str = "$: << '#{ENV["MERLIN_ROOT"] + "\\Bin\\Debug\\"}'".gsub("\\", "/")
+    @engine.execute(str, @scope)
+    @engine.execute("require 'rowantest.baseclasscs'", @scope)
+    str = <<-EOL
+      class Merlin::Testing::BaseClass::EmptyClass
+        def foo
+          :foo
+        end
+      end
+    EOL
+    @engine.execute str, @scope
+    @engine.execute "ec = Merlin::Testing::BaseClass::EmptyClass.new", @scope
+  end
+
+  after :each do
+    @engine = nil
+  end
+  
+  it "is allowed" do
+    @engine.execute("ec.foo", @scope).should == :foo
+  end
+  
+  it "doesn't reload with require" do
+    @engine.execute("ec.foo", @scope).should == :foo
+    @engine.execute("require 'rowantest.baseclasscs'", @scope).should == false
+    @engine.execute("ec.foo", @scope).should == :foo
+  end
+
+  it "reloads with load, without rewriting the class or module" do
+    @engine.execute("ec.foo", @scope).should == :foo
+    @engine.execute("load 'rowantest.baseclasscs.dll'", @scope).should == true
+    @engine.execute("ec.foo", @scope).should == :foo
+  end
+
+  it "reloads with load_assembly, without rewriting the class or module" do
+    @engine.execute("ec.foo", @scope).should == :foo
+    @engine.execute("load_assembly 'rowantest.baseclasscs'", @scope).should == true
+    @engine.execute("ec.foo", @scope).should == :foo
+  end
+end
===================================================================
add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/load/mscorlib_spec.rb
File: mscorlib_spec.rb
===================================================================
--- [no source file]
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/load/mscorlib_spec.rb;netinterop1
@@ -1,0 +1,119 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+require File.dirname(__FILE__) + '/shared/load'
+require 'ironruby'
+
+describe "mscorlib" do
+  before :each do
+    @engine = IronRuby.create_engine
+  end
+
+  after :each do
+    #TODO: Does this release the engine enough to allow GC? We don't want a
+    #ton of wasted interpreters hanging around.
+    @engine = nil
+  end
+
+  describe "single load" do
+    it "works via require" do
+      @engine.execute("require 'mscorlib'")
+      @engine.execute("$\"").should == ['mscorlib']
+    end
+
+    it "works via load" do
+      @engine.execute("load 'mscorlib'")
+      lambda {@engine.execute("System")}.should_not raise_error(NameError)
+    end
+
+    it "works via load_assembly" do
+      @engine.execute("load_assembly 'mscorlib'")
+      lambda {@engine.execute("System")}.should_not raise_error(NameError)
+    end
+  end
+
+  describe "Repeated loading" do
+    before :each do
+      @assembly = 'mscorlib'
+    end
+
+    it_behaves_like :repeated_net_assembly, nil
+  end
+end
+
+describe "mscorlib with Strong name" do
+  before :each do
+    @engine = IronRuby.create_engine
+  end
+
+  after :each do
+    #TODO: Does this release the engine enough to allow GC? We don't want a
+    #ton of wasted interpreters hanging around.
+    @engine = nil
+  end
+  describe "single load" do
+    it "works via require" do
+      @engine.execute("require 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'")
+      @engine.execute("$\"").should == ['mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089']
+    end
+
+    it "works via load" do
+      @engine.execute("load 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'")
+      lambda {@engine.execute("System")}.should_not raise_error(NameError)
+    end
+
+    it "works via load_assembly" do
+      @engine.execute("load_assembly 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'")
+      lambda {@engine.execute("System")}.should_not raise_error(NameError)
+    end
+  end
+
+  describe "Repeated loading" do
+    before :each do
+      @assembly = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
+    end
+    
+    it_behaves_like :repeated_net_assembly, nil
+  end
+end
+
+describe "Modifying and reloading mscorlib" do 
+  before :each do
+    @engine = IronRuby.create_engine
+    @scope = @engine.create_scope
+    @engine.execute("require 'mscorlib'", @scope)
+    str = <<-EOL
+      class System::Collections::ArrayList
+        def foo
+          :foo
+        end
+      end
+    EOL
+    @engine.execute str, @scope
+    @engine.execute "al = System::Collections::ArrayList.new", @scope
+  end
+
+  after :each do
+    @engine = nil
+  end
+  
+  it "is allowed" do
+    @engine.execute("al.foo", @scope).should == :foo
+  end
+  
+  it "doesn't reload with require" do
+    @engine.execute("al.foo", @scope).should == :foo
+    @engine.execute("require 'mscorlib'", @scope).should == false
+    @engine.execute("al.foo", @scope).should == :foo
+  end
+
+  it "reloads with load, without rewriting the class or module" do
+    @engine.execute("al.foo", @scope).should == :foo
+    @engine.execute("load 'mscorlib'", @scope).should == true
+    @engine.execute("al.foo", @scope).should == :foo
+  end
+
+  it "reloads with load_assembly, without rewriting the class or module" do
+    @engine.execute("al.foo", @scope).should == :foo
+    @engine.execute("load_assembly 'mscorlib'", @scope).should == true
+    @engine.execute("al.foo", @scope).should == :foo
+  end
+end
===================================================================
add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/load/net_bcl_spec.rb
File: net_bcl_spec.rb
===================================================================
--- [no source file]
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/Interop/load/net_bcl_spec.rb;netinterop1
@@ -1,0 +1,105 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+require File.dirname(__FILE__) + '/../spec_helper'
+require 'ironruby'
+
+describe "Single time loading of a .NET BCL assembly without Strong Name" do
+  before :each do
+    @engine = IronRuby.create_engine
+  end
+
+  after :each do
+    #TODO: Does this release the engine enough to allow GC? We don't want a
+    #ton of wasted interpreters hanging around.
+    @engine = nil
+  end
+
+  it "raises LoadError via require" do
+    lambda {@engine.execute("require 'System.Core'")}.should raise_error(LoadError)
+  end
+
+  it "raises LoadError via load" do
+    lambda {@engine.execute("load 'System.Core'")}.should raise_error(LoadError)
+  end
+
+  it "raises LoadError via load_assembly" do
+    lambda {@engine.execute("load_assembly 'System.Core'")}.should raise_error(LoadError)
+  end
+end
+
+describe ".NET BCL Assembly with Strong name" do
+  before :each do
+    @engine = IronRuby.create_engine
+  end
+
+  after :each do
+    #TODO: Does this release the engine enough to allow GC? We don't want a
+    #ton of wasted interpreters hanging around.
+    @engine = nil
+  end
+  describe "single load" do
+    it "works via require" do
+      @engine.execute("require 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'")
+      @engine.execute("$\"").should == ['System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089']
+    end
+
+    it "works via load" do
+      @engine.execute("load 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'")
+      lambda {@engine.execute("System::Linq")}.should_not raise_error(NameError)
+    end
+
+    it "works via load_assembly" do
+      @engine.execute("load_assembly 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'")
+      lambda {@engine.execute("System::Linq")}.should_not raise_error(NameError)
+    end
+  end
+
+  describe "repeated loading" do
+    before :each do
+      @assembly = 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
+    end
+    it_behaves_like :repeated_net_assembly, nil
+  end
+end
+
+describe "Modifying and reloading a .NET BCL Assembly" do 
+  before :each do
+    @engine = IronRuby.create_engine
+    @scope = @engine.create_scope
+    @engine.execute("require 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'", @scope)
+    str = <<-EOL
+      class System::Web::HttpApplication
+        def foo
+          :foo
+        end
+      end
+    EOL
+    @engine.execute str, @scope
+    @engine.execute "ha = System::Web::HttpApplication.new", @scope
+  end
+
+  after :each do
+    @engine = nil
+  end
+  
+  it "is allowed" do
+    @engine.execute("ha.foo", @scope).should == :foo
+  end
+  
+  it "doesn't reload with require" do
+    @engine.execute("ha.foo", @scope).should == :foo
+    @engine.execute("require 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'", @scope).should == false
+    @engine.execute("ha.foo", @scope).should == :foo
+  end
+
+  it "reloads with load, without rewriting the class or module" do
+    @engine.execute("ha.foo", @scope).should == :foo
+    @engine.execute("load 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'", @scope).should == true
+    @engine.execute("ha.foo", @scope).should == :foo
+  end
+
+  it "reloads with load_assembly, without rewriting the class or module" do
+    @engine.execute("ha.foo", @scope).should == :foo
+    @engine.execute("load_assembly 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'", @scope).should == true
+    @engine.execute("ha.foo", @scope).should == :foo
+  end
+end
===================================================================
