edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/IronRuby.Tests.csproj;C785561 File: IronRuby.Tests.csproj =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/IronRuby.Tests.csproj;C785561 (server) 3/16/2009 10:24 AM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/IronRuby.Tests.csproj;iridmop @@ -2,7 +2,7 @@ Debug AnyCPU - 9.0.21022 + 9.0.30729 2.0 {8103D91B-89D8-4A18-9A40-426992602EA2} Exe @@ -65,6 +65,7 @@ + =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C798493 File: RubyTests.cs =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C798493 (server) 3/16/2009 11:29 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;iridmop @@ -531,6 +531,18 @@ Backtrace2, Backtrace3, Backtrace4, + + Dlr_ClrSubtype, + Dlr_MethodMissing, + Dlr_Miscellaneous, + Dlr_Convertible, + Dlr_Indexable, + Dlr_Number, + Dlr_Enumerable, + Dlr_Comparable, + Dlr_RubyObjects, + Dlr_Methods, + Dlr_Languages }; } } =================================================================== add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/DlrInteropTests.cs File: DlrInteropTests.cs =================================================================== --- [no source file] +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/DlrInteropTests.cs;iridmop @@ -1,0 +1,762 @@ +?/* **************************************************************************** + * + * Copyright (c) Microsoft Corporation. + * + * This source code is subject to terms and conditions of the Microsoft Public License. A + * copy of the license can be found in the License.html file at the root of this distribution. If + * you cannot locate the Microsoft Public License, please send an email to + * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound + * by the terms of the Microsoft Public License. + * + * You must not remove this notice, or any other, from this software. + * + * + * ***************************************************************************/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.Serialization; +using Microsoft.Scripting.Runtime; +using IronRuby.Runtime; +using IronRuby.Builtins; +using System.IO; +using System.Linq.Expressions; +using System.Dynamic; +using Microsoft.Scripting.Utils; +using Microsoft.Scripting.Hosting; +using System.Runtime.CompilerServices; +using Microsoft.Scripting; + +namespace IronRuby.Tests { + #region Custom binders + + class MyInvokeMemberBinder : InvokeMemberBinder { + public MyInvokeMemberBinder(string name, CallInfo callInfo) + : base(name, false, callInfo) { + } + + public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Constant("FallbackInvokeMember"), + target.Restrictions.Merge(BindingRestrictions.Combine(args)) + ); + } + + public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Dynamic(new MyInvokeBinder(CallInfo), typeof(object), DynamicUtils.GetExpressions(ArrayUtils.Insert(target, args))), + target.Restrictions.Merge(BindingRestrictions.Combine(args)) + ); + } + + internal static object Invoke(object obj, string methodName) { + var site = CallSite>.Create(new MyInvokeMemberBinder(methodName, new CallInfo(0))); + return site.Target(site, obj); + } + + internal static object Invoke(object obj, string methodName, object arg) { + var site = CallSite>.Create(new MyInvokeMemberBinder(methodName, new CallInfo(1))); + return site.Target(site, obj, arg); + } + } + + class MyInvokeBinder : InvokeBinder { + public MyInvokeBinder(CallInfo callInfo) + : base(callInfo) { + } + + public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Call( + typeof(String).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }), + Expression.Constant("FallbackInvoke"), + target.Expression + ), + BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) + ); + } + + internal static object Invoke(object obj) { + var site = CallSite>.Create(new MyInvokeBinder(new CallInfo(0))); + return site.Target(site, obj); + } + + internal static object Invoke(object obj, object arg) { + var site = CallSite>.Create(new MyInvokeBinder(new CallInfo(1))); + return site.Target(site, obj, arg); + } + } + + class MyGetIndexBinder : GetIndexBinder { + public MyGetIndexBinder(CallInfo args) + : base(args) { + } + + public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Call( + typeof(String).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }), + Expression.Constant("FallbackGetIndex:"), + indexes[0].Expression + ), + BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) + ); + } + + internal static object Invoke(object obj, object index) { + var site = CallSite>.Create(new MyGetIndexBinder(new CallInfo(1))); + return site.Target(site, obj, index); + } + } + + class MySetIndexBinder : SetIndexBinder { + public MySetIndexBinder(CallInfo args) + : base(args) { + } + + public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Call( + typeof(String).GetMethod("Concat", new Type[] { typeof(object), typeof(object), typeof(object) }), + Expression.Constant("FallbackSetIndex:"), + indexes[0].Expression, + value.Expression + ), + BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) + ); + } + + internal static object Invoke(object obj, object index, object arg) { + var site = CallSite>.Create(new MySetIndexBinder(new CallInfo(1))); + return site.Target(site, obj, index, arg); + } + } + + class MyGetMemberBinder : GetMemberBinder { + public MyGetMemberBinder(string name) + : base(name, false) { + } + + public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Constant("FallbackGetMember"), + BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) + ); + } + + internal static object Invoke(object obj, string memberName) { + var site = CallSite>.Create(new MyGetMemberBinder(memberName)); + return site.Target(site, obj); + } + } + + class MySetMemberBinder : SetMemberBinder { + public MySetMemberBinder(string name) + : base(name, false) { + } + + public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Constant("FallbackSetMember"), + BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) + ); + } + + internal static object Invoke(object obj, string memberName, object val) { + var site = CallSite>.Create(new MySetMemberBinder(memberName)); + return site.Target(site, obj, val); + } + } + + class MyInvokeBinder2 : InvokeBinder { + public MyInvokeBinder2(CallInfo args) + : base(args) { + } + + public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { + Expression[] exprs = new Expression[args.Length + 1]; + exprs[0] = Expression.Constant("FallbackInvoke"); + for (int i = 0; i < args.Length; i++) { + exprs[i + 1] = args[i].Expression; + } + + return new DynamicMetaObject( + Expression.Call( + typeof(String).GetMethod("Concat", new Type[] { typeof(object[]) }), + Expression.NewArrayInit( + typeof(object), + exprs + ) + ), + BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) + ); + } + + internal static object Invoke(object obj, object arg) { + var site = CallSite>.Create(new MyInvokeBinder2(new CallInfo(1))); + return site.Target(site, obj, arg); + } + } + + class MyConvertBinder : ConvertBinder { + private object _result; + public MyConvertBinder(Type type) + : this(type, "FallbackConvert") { + } + public MyConvertBinder(Type type, object result) + : base(type, true) { + _result = result; + } + + public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Constant(_result), + BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) + ); + + } + + internal static object Invoke(object obj, Type targetType) { + var site = CallSite>.Create(new MyConvertBinder(targetType)); + return site.Target(site, obj); + } + } + + class MyBinaryOperationBinder : BinaryOperationBinder { + public MyBinaryOperationBinder(ExpressionType operation) + : base(operation) { + } + + public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) { + return new DynamicMetaObject( + Expression.Call( + typeof(String).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }), + Expression.Constant("FallbackInvoke:"), + arg.Expression + ), + BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target) + ); + } + + internal static object Invoke(ExpressionType operation, object obj, object arg) { + var site = CallSite>.Create(new MyBinaryOperationBinder(operation)); + return site.Target(site, obj, arg); + } + } + + #endregion + + public partial class Tests { + + #region Ruby snippet + + const string RubySnippet = @" +require 'mscorlib' +ArrayList = System::Collections::ArrayList + +#------------------------------------------------------------------------------ +# Mixin which allows responding to arbitrary methods, properties, and indexing + +module DynamicAttributes + def initialize *args + @attrs = Hash.new + @elems = Hash.new + super + end + + def explicit_attribute + 'explicit_attribute'.to_clr_string + end + + def method_missing *args + case args.size + when 1 + attr_name = args[0].to_s + if @attrs.key? attr_name + @attrs[attr_name] + else + ('dynamic_' + attr_name).to_clr_string + end + when 2 + if args[0] == :[] then + if @elems.key? args[1] then + @elems[args[1]] + else + ('dynamic_element_' + args[1].to_s).to_clr_string + end + else + attr_name = args[0].to_s[0..-2] # Strip the trailing '=' + @attrs[attr_name] = args[1] + end + when 3 + # args[0] will be :[]= + @elems[args[1]] = args[2] + end + end +end + +#------------------------------------------------------------------------------ +# If the file is run from the command-line as 'ir.exe test.rb', +# some extra initialization needs to be done so that the rest of the code +# works both from the command-line and in a hosted ScriptRuntime. + +if $0 == __FILE__ then + # Mimic DynamicAttributes#initialize + self.instance_variable_set(:@attrs, Hash.new) + self.instance_variable_set(:@elems, Hash.new) + class << self + include DynamicAttributes + end +end + +#------------------------------------------------------------------------------ +# Inherit from a CLR type + +class RubyArrayList < ArrayList + def initialize *args + super(*args) + end + + def ruby_method + 'Hi from Ruby'.to_clr_string + end + + # override a CLR virtual method + def IndexOf obj + 123456789 + end +end + +self.ruby_array_list = RubyArrayList.new() +self.ruby_array_list.Add(100) +self.ruby_array_list.Add(200) + +#------------------------------------------------------------------------------ +class DynamicObject + include DynamicAttributes +end + +self.dynamic_object = DynamicObject.new + +#------------------------------------------------------------------------------ +class DynamicArrayList < RubyArrayList + include DynamicAttributes +end + +self.dynamic_array_list = DynamicArrayList.new + +#------------------------------------------------------------------------------ +class Miscellaneous + def self.static_method + 'static_method'.to_clr_string + end + + #self.class_instance_method = static_method + + attr :callable_called + def get_a_callable + @callable_called = false + System::Action[Object].new { @callable_called = true } + end + + def to_s + 'to_s'.to_clr_string + end +end + +self.misc = Miscellaneous.new + +#------------------------------------------------------------------------------ +class Convertible + def initialize v + @val = v + end + + def to_i + @val.to_i + end + + def to_f + @val.to_f + end + + def to_str + @val.to_str.to_clr_string + end +end + +self.convertible = Convertible.new('0') + +#------------------------------------------------------------------------------ +class Indexable + def initialize a=nil + if a then + @array = a + else + @array = [] + end + end + + def [](index) + @array[index] + end + + def []=(index, value) + @array[index] = value + end +end + +self.indexable = Indexable.new [0, 1, 2] + +#------------------------------------------------------------------------------ +class Number + def initialize(v) + @val = v + end + + def +(other) + @val + other + end + + def -(other) + @val - other + end + + def *(other) + @val * other + end + + def /(other) + @val / other + end +end + +self.number = Number.new(100) + +#------------------------------------------------------------------------------ +class Helpers + def self.get_ruby_array + [100, 200] + end + + def self.get_ruby_string + 'Ruby string'.to_clr_string + end + + def self.get_ruby_hash + { 'Ruby'.to_clr_string => 'keyed by Ruby'.to_clr_string, 'C#'.to_clr_string => 'keyed by C#'.to_clr_string } + end + + def self._a_method + 'Ruby method'.to_clr_string + end + + def self.get_ruby_callable + self.method(:_a_method) + end + + def self.get_singleton_string + s = 'Hello'.to_clr_string + class<(other) + @val <=> other + end +end + +self.ruby_comparable = RubyComparable.new(100) + +#------------------------------------------------------------------------------ +class Methods + def self.named_params(a, b) + %Q(a:#{a} b:#{b}).to_clr_string + end + + def self.default_values(a = 1, b = 2) + %Q(a:#{a} b:#{b}).to_clr_string + end + + def self.varargs(*args) + args.collect {|elem| elem.to_s }.join(' ').to_clr_string + end + + def self.multiple_return_values + return 100, 200 + end + + def self.with_block + yield 100 + end +end + +#------------------------------------------------------------------------------ + +class SanityTest + def self.assert_equal o1, o2 + if not o1 == o2 then raise %Q(Fail: Expected #{o1} to equal #{o2}) end + end + + def self.assert_error l, exception_type + begin + l.call + raise 'Unreachable' + rescue Exception => e + if not e.kind_of? exception_type then raise %Q(Expected #{e.class} to equal #{exception_type}) end + end + end + + def self.sanity_test main + # $ruby_array_list + assert_equal main.ruby_array_list.Count, 2 + assert_equal main.ruby_array_list[0], 100 + assert_error lambda { main.ruby_array_list.Count = 1 }, NoMethodError + assert_equal main.ruby_array_list.ruby_method, 'Hi from Ruby'.to_clr_string + assert_equal main.ruby_array_list.IndexOf(nil), 123456789 + + # main.dynamic_object + assert_equal main.dynamic_object.foo, 'dynamic_foo'.to_clr_string + main.dynamic_object.bar = 'my bar' + assert_equal main.dynamic_object.bar, 'my bar' + assert_equal main.dynamic_object.explicit_attribute, 'explicit_attribute'.to_clr_string + assert_equal main.dynamic_object[:hello], 'dynamic_element_hello'.to_clr_string + main.dynamic_object[:hello] = 1 + assert_equal main.dynamic_object[:hello], 1 + + # main.dynamic_array_list + assert_equal main.dynamic_array_list.foo, 'dynamic_foo'.to_clr_string + main.dynamic_array_list.bar = 'my bar' + assert_equal main.dynamic_array_list.bar, 'my bar' + assert_equal main.dynamic_array_list.explicit_attribute, 'explicit_attribute'.to_clr_string + main.dynamic_array_list.Count = 1 + assert_equal main.dynamic_array_list.Count, 0 + assert_equal main.dynamic_array_list.IndexOf(0), 123456789 + + # main.misc + assert_equal Miscellaneous.static_method, 'static_method'.to_clr_string + assert_error lambda { main.misc.static_method }, NoMethodError + c = main.misc.get_a_callable() + assert_equal main.misc.callable_called, false + c.Invoke(nil) + assert_equal main.misc.callable_called, true + # assert_equal main.misc.ToString(), 'to_s' # Bug!!!!!!!!!!!!!!!!! + + # main.convertible + assert_error lambda { System::GC.Collect(main.convertible) }, TypeError # convert to int - Bug!!!!!!!!!! + assert_equal System::Exception.new(main.convertible).class, Exception + # need to convert to float + + # main.indexable + assert_equal main.indexable[2], 2 + main.indexable[10] = 100 + assert_equal main.indexable[10], 100 + assert_equal main.indexable[9], nil + + # main.number + assert_equal((main.number + 1), 101) + assert_equal((main.number - 1), 99) + assert_equal((main.number * 2), 200) + assert_equal((main.number / 2), 50) + + # RubyEnumerable + assert_equal main.ruby_enumerable.min, 1 + + # RubyComparable + assert_equal((main.ruby_comparable == 100), true) + assert_equal((main.ruby_comparable > 100), false) + assert_equal((main.ruby_comparable >= 100), true) + + # Helpers + assert_equal Helpers.get_ruby_array()[0], 100 + assert_equal System::Exception.new(Helpers.get_ruby_string).class, Exception + assert_equal Helpers.get_ruby_hash()['Ruby'.to_clr_string], 'keyed by Ruby'.to_clr_string + assert_equal Helpers.get_ruby_callable().call(), 'Ruby method'.to_clr_string + # assert_equal Helpers.get_singleton_string.ToString, 'Singleton' # Bug!!! - this hangs the process + + # Methods + assert_equal Methods.default_values(100), 'a:100 b:2'.to_clr_string + assert_equal Methods.varargs(100, 200), '100 200'.to_clr_string + assert_equal Methods.multiple_return_values, [100, 200] + assert_equal Methods.with_block {|x| x + 1000}, 1100 + + # Features to try from other languages + # Pass in ref/out params + # Named arguments + end +end + +if $0 == __FILE__ then + SanityTest.sanity_test self +end +"; + #endregion + + private ScriptScope _rubyInteropScope; + private ScriptScope RubyInteropScope { + get { + if (_rubyInteropScope == null) { + _rubyInteropScope = Runtime.CreateScope(); + Engine.Execute(RubySnippet, _rubyInteropScope); +#if DEBUG + // Delete me + object ruby_array_list = _rubyInteropScope.GetVariable("ruby_array_list"); + Console.WriteLine("RubyArrayList: " + ruby_array_list); +#endif + } + return _rubyInteropScope; + } + } + + [DebuggerHiddenAttribute] + internal void AreEqualBug(object x, object y, object buggyResult) { + AreEqual(x, buggyResult); + } + + [DebuggerHiddenAttribute] + internal void AreEqualBug(Action f, object y) where T : Exception { + AssertExceptionThrown(f); + } + + [DebuggerHiddenAttribute] + internal void AssertExceptionThrownBug(Action f) where T : Exception { + f(); + } + + public void Dlr_ClrSubtype() { + object ruby_array_list = RubyInteropScope.GetVariable("ruby_array_list"); + + // CLR member + AreEqualBug(MyInvokeMemberBinder.Invoke(ruby_array_list, "Count"), "FallbackInvokeMember", 2); + // Overriden CLR member + AreEqualBug(MyInvokeMemberBinder.Invoke(ruby_array_list, "IndexOf", null), "FallbackInvokeMember", 123456789); + // CLR indexer + AreEqual(MySetIndexBinder.Invoke(ruby_array_list, 10, 100), "FallbackSetIndex:10100"); + AreEqual(MyGetIndexBinder.Invoke(ruby_array_list, 10), "FallbackGetIndex:10"); + + AreEqual(MyInvokeMemberBinder.Invoke(ruby_array_list, "ruby_method"), "Hi from Ruby"); + + AreEqual(MyInvokeMemberBinder.Invoke(ruby_array_list, "non_existent"), "FallbackInvokeMember"); + AreEqual(MySetMemberBinder.Invoke(ruby_array_list, "Count", 100000), "FallbackSetMember"); + } + + public void Dlr_MethodMissing() { + object dynamic_object = RubyInteropScope.GetVariable("dynamic_object"); + + AreEqual(MyInvokeMemberBinder.Invoke(dynamic_object, "non_existent_method"), "dynamic_non_existent_method"); + + AreEqualBug(MySetMemberBinder.Invoke(dynamic_object, "non_existent_member", 100), 100, "FallbackSetMember"); + AreEqualBug(MyGetMemberBinder.Invoke(dynamic_object, "non_existent_member"), 100, "FallbackGetMember"); + + AreEqualBug(MyGetIndexBinder.Invoke(dynamic_object, "non_existent_index"), "dynamic_element_non_existent_index", "FallbackGetIndex:non_existent_index"); + AreEqual(MySetIndexBinder.Invoke(dynamic_object, "non_existent_index", 100), "FallbackSetIndex:non_existent_index100"); + AreEqualBug(MyGetIndexBinder.Invoke(dynamic_object, "non_existent_index"), 100, "FallbackGetIndex:non_existent_index"); + + AreEqual(MyInvokeMemberBinder.Invoke(dynamic_object, "explicit_attribute"), "explicit_attribute"); + } + + public void Dlr_Miscellaneous() { + object misc_object = RubyInteropScope.GetVariable("misc"); + + object misc_class = MyInvokeMemberBinder.Invoke(misc_object, "class"); + AreEqualBug(delegate() { RubyInteropScope.GetVariable("Miscellaneous"); }, misc_class); + + AreEqual(MyInvokeMemberBinder.Invoke(misc_class, "static_method"), "static_method"); + AssertExceptionThrownBug(delegate() { MyInvokeMemberBinder.Invoke(misc_object, "static_method"); }); + + object callable = MyInvokeMemberBinder.Invoke(misc_object, "get_a_callable"); + AreEqual(MyInvokeMemberBinder.Invoke(misc_object, "callable_called"), false); + MyInvokeBinder.Invoke(callable); + AreEqualBug(MyInvokeMemberBinder.Invoke(misc_object, "callable_called"), true, false); + + AreEqualBug(MyInvokeMemberBinder.Invoke(misc_class, "ToString"), "to_s", "FallbackInvokeMember"); + } + + public void Dlr_Convertible() { + object convertible = RubyInteropScope.GetVariable("convertible"); + AreEqualBug(MyConvertBinder.Invoke(convertible, typeof(int)), 0, "FallbackConvert"); + AreEqualBug(MyConvertBinder.Invoke(convertible, typeof(string)), "0", "FallbackConvert"); + AreEqualBug(MyConvertBinder.Invoke(convertible, typeof(float)), 0.0, "FallbackConvert"); + } + + public void Dlr_Indexable() { + object indexable = RubyInteropScope.GetVariable("indexable"); + AreEqualBug(MyGetIndexBinder.Invoke(indexable, 2), 2, "FallbackGetIndex:2"); + AreEqual(MySetIndexBinder.Invoke(indexable, 10, 100), "FallbackSetIndex:10100"); + AreEqualBug(MyGetIndexBinder.Invoke(indexable, 10), 100, "FallbackGetIndex:10"); + AreEqualBug(MyGetIndexBinder.Invoke(indexable, 9), null, "FallbackGetIndex:9"); + } + + public void Dlr_Number() { + object number = RubyInteropScope.GetVariable("number"); + AreEqualBug(MyBinaryOperationBinder.Invoke(ExpressionType.Add, number, 1), 101, "FallbackInvoke:1"); + AreEqualBug(MyBinaryOperationBinder.Invoke(ExpressionType.Subtract, number, 1), 99, "FallbackInvoke:1"); + AreEqualBug(MyBinaryOperationBinder.Invoke(ExpressionType.Multiply, number, 2), 200, "FallbackInvoke:2"); + AreEqualBug(MyBinaryOperationBinder.Invoke(ExpressionType.Divide, number, 2), 50, "FallbackInvoke:2"); + } + public void Dlr_Enumerable() { + object ruby_enumerable = RubyInteropScope.GetVariable("ruby_enumerable"); + IEnumerable e = MyConvertBinder.Invoke(ruby_enumerable, typeof(IEnumerable)) as IEnumerable; + AreEqual(e != null, true); + IEnumerable e2 = MyConvertBinder.Invoke(ruby_enumerable, typeof(IEnumerable)) as IEnumerable; + AreEqualBug(e2 != null, true, false); + } + + public void Dlr_Comparable() { + object ruby_comparable = RubyInteropScope.GetVariable("ruby_comparable"); + AreEqualBug(MyBinaryOperationBinder.Invoke(ExpressionType.Equal, ruby_comparable, 100), true, "FallbackInvoke:100"); + AreEqualBug(MyBinaryOperationBinder.Invoke(ExpressionType.GreaterThan, ruby_comparable, 100), false, "FallbackInvoke:100"); + AreEqualBug(MyBinaryOperationBinder.Invoke(ExpressionType.LessThanOrEqual, ruby_comparable, 100), true, "FallbackInvoke:100"); + } + + public void Dlr_RubyObjects() { + //assert_equal Helpers.get_ruby_array()[0], 100 + //assert_equal System::Exception.new(Helpers.get_ruby_string).class, Exception + //assert_equal Helpers.get_ruby_hash()[:ruby], 'Ruby' + //assert_equal Helpers.get_ruby_callable().call(), 'Ruby method' + //# assert_equal Helpers.get_singleton_string.ToString, 'Singleton' # Bug!!! - this hangs the process + } + + public void Dlr_Methods() { + //assert_equal Methods.default_values(100), 'a:100 b:2' + //assert_equal Methods.varargs(100, 200), '100 200' + //assert_equal Methods.multiple_return_values, [100, 200] + //assert_equal Methods.with_block {|x| x + 1000}, 1100 + } + + public void Dlr_Languages() { + //# Pass in ref/out params + //# Named arguments + } + } +} + =================================================================== add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Scripts/ir_wrap.cmd File: ir_wrap.cmd =================================================================== --- [no source file] +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Scripts/ir_wrap.cmd;iridmop @@ -1,0 +1,25 @@ +@echo off + +REM The purpose of this file is to have a level of indirection for testing purposes. +REM It allows setting of different command-line options without having to create +REM new test cases for the different command-line options. + +setlocal + +if "%ROWAN_BIN%" == "" ( + set TEMP_IR_PATH=%MERLIN_ROOT%\bin\debug +) else ( + set TEMP_IR_PATH=%ROWAN_BIN% +) + +if "%IR_OPTIONS%" == "" ( + set IR_OPTIONS=-X:Interpret +) + +set HOME=%USERPROFILE% +set RUBY_EXE=%TEMP_IR_PATH%\ir.exe + +%TEMP_IR_PATH%\ir.exe %IR_OPTIONS% %* +:: +:: There should be no operations after this point so that the exitcode or ir.exe will be avilable as ERRORLEVEL +:: \ No newline at end of file =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/common.rb;C782965 File: common.rb =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/common.rb;C782965 (server) 3/25/2009 4:52 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/common.rb;iridmop @@ -36,15 +36,8 @@ # assume we are running inside snap if ROWAN_BIN - IRUBY_EXE = MERLIN_ROOT + "/Test/Scripts/ir.cmd" IPYTHON_EXE = ROWAN_BIN + "/ipy.exe" else - ir_cmd = MERLIN_ROOT + "/Test/Scripts/ir.cmd" - if File.exists? ir_cmd then - IRUBY_EXE = ir_cmd - else - IRUBY_EXE = MERLIN_ROOT + "/bin/debug/ir.exe" # ir.cmd does not exist in GIT - end IPYTHON_EXE = MERLIN_ROOT + "/bin/debug/ipy.exe" end @@ -52,12 +45,12 @@ else TEST_DIR = File.expand_path(File.dirname(__FILE__)) MERLIN_ROOT = File.dirname(File.dirname(TEST_DIR)) - IRUBY_EXE = MERLIN_ROOT + "/Test/Scripts/ir.cmd" CRUBY_EXE = "ruby.exe" IPYTHON_EXE = nil PARSEONLY_EXE = nil end + IRUBY_EXE = MERLIN_ROOT + "/Languages/Ruby/Scripts/ir_wrap.cmd" # generate logs to TestResults directory, so they will be copied to the snap server TEMP = get_environment_variable("INSTALLROOT") =================================================================== edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/run_builtin.rb;C533700 File: run_builtin.rb =================================================================== --- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/run_builtin.rb;C533700 (server) 3/26/2009 12:56 PM +++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Tests/run_builtin.rb;iridmop @@ -25,7 +25,7 @@ system("ruby #{path}") puts print path, '(ir): ' - system("..\\..\\..\\Test\\Scripts\\ir.cmd #{path}") + system("..\\..\\..\\Languages\\Ruby\\Scripts\\ir_wrap.cmd #{path}") puts end end =================================================================== edit: $/Merlin_External/Languages/IronRuby/mspec/default.mspec;C782072 File: default.mspec =================================================================== --- $/Merlin_External/Languages/IronRuby/mspec/default.mspec;C782072 (server) 3/25/2009 4:54 PM +++ Shelved Change: $/Merlin_External/Languages/IronRuby/mspec/default.mspec;iridmop @@ -131,7 +131,7 @@ ] # The default implementation to run the specs. # TODO: change this to rely on an environment variable - set :target, "#{ENV['MERLIN_ROOT']}\\Test\\Scripts\\ir.cmd" + set :target, "#{ENV['MERLIN_ROOT']}\\Languages\\Ruby\\Scripts\\ir_wrap.cmd" set :prefix, "#{ENV['MERLIN_ROOT']}\\..\\External\\Languages\\IronRuby\\mspec\\rubyspec" end ===================================================================