/IronPython_Main/Runtime/Tests/SiteTest/SiteTestScenarios.Tests.Dynamic.cs
C# | 1750 lines | 1223 code | 315 blank | 212 comment | 33 complexity | 3b67d3bda5b9a4bb5bd510a67cdb4813 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
Large files files are truncated, but you can click here to view the full file
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
-
- #if !CLR2
- using System.Linq.Expressions;
- #else
- using Microsoft.Scripting.Ast;
- using Microsoft.Scripting.Utils;
- #endif
-
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Dynamic;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.Threading;
- using SiteTest.Actions;
- using System.IO;
-
- namespace SiteTest {
- partial class SiteTestScenarios {
- [Test("Remoted IDO")]
- private void Scenario_Remoted() {
-
- #region CallSite for each action
- var setMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("__code__"));
- var getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("__code__"));
- #endregion
-
-
- // run locally
- object mbro = new MBRODynamicObject();
- Assert.AreEqual("MBRO_GetMember", getMember.Target(getMember, mbro));
-
- // run remotely
- var domain = AppDomain.CreateDomain("remote");
- mbro = domain.CreateInstanceAndUnwrap(typeof(MBRODynamicObject).Assembly.FullName, typeof(MBRODynamicObject).FullName);
-
- getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("__code__"));
- Assert.AreEqual("123", getMember.Target(getMember, mbro));
-
- // run in current domain
- domain = AppDomain.CurrentDomain;
- mbro = domain.CreateInstanceAndUnwrap(typeof(MBRODynamicObject).Assembly.FullName, typeof(MBRODynamicObject).FullName);
-
- getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("__code__"));
- Assert.AreEqual("MBRO_GetMember", getMember.Target(getMember, mbro));
-
- ClearRuleCache(getMember);
-
- // run remotely after clearing cache.
- domain = AppDomain.CreateDomain("remote");
- mbro = domain.CreateInstanceAndUnwrap(typeof(MBRODynamicObject).Assembly.FullName, typeof(MBRODynamicObject).FullName);
-
- getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("__code__"));
- Assert.AreEqual("123", getMember.Target(getMember, mbro));
-
- // run locally again
- mbro = new MBRODynamicObject();
- Assert.AreEqual("MBRO_GetMember", getMember.Target(getMember, mbro));
-
- }
-
- #if CLR45
- [Test("Remoted IDO2")]
- private void Scenario_Remoted2() {
-
- #region CallSite for each action
- var getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("Name"));
- #endregion
-
- object sdo = new SerializableDO();
-
- MemoryStream ms = new MemoryStream();
- BinaryFormatter formatter = new BinaryFormatter();
-
- formatter.Serialize(ms, sdo);
- ms.Seek(0, SeekOrigin.Begin);
- object sdo2 = formatter.Deserialize(ms);
-
- Assert.AreEqual("SerializableDO", getMember.Target(getMember, sdo2));
- }
- #endif
-
- // Support for remoted COM is NYI
-
- //[Test(TestState.COM, "Remoted COM")]
- //private void Scenario_RemotedCom() {
-
- // #region CallSite for each action
- // var getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("pLong"));
- // #endregion
-
- // // run locally
- // MBRODynamicObject mbro = new MBRODynamicObject();
- // Assert.AreEqual(0, getMember.Target(getMember, mbro.GetComObj()));
-
- // // run remotely
- // var domain = AppDomain.CreateDomain("remote");
- // mbro = (MBRODynamicObject)domain.CreateInstanceAndUnwrap(typeof(MBRODynamicObject).Assembly.FullName, typeof(MBRODynamicObject).FullName);
-
- // getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("pLong"));
- // Assert.AreEqual("777", getMember.Target(getMember, mbro.GetComObj()));
- // // need to clear after TestGetMemberBinder.
- // ClearRuleCache(getMember);
-
-
- // // run in current domain
- // domain = AppDomain.CurrentDomain;
- // mbro = (MBRODynamicObject)domain.CreateInstanceAndUnwrap(typeof(MBRODynamicObject).Assembly.FullName, typeof(MBRODynamicObject).FullName);
-
- // getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("pLong"));
- // Assert.AreEqual(0, getMember.Target(getMember, mbro.GetComObj()));
- //}
-
-
- #region Add new Dynamic (IDO Helper) tests here.
- /* Call
- * Convert
- * Create
- * DeleteIndex
- * DeleteMember
- * GetIndex
- * GetMember
- * Invoke
- * Operation
- * SetIndex
- * SetMember
- */
- [Test("Simple cases for a basic derivation Dynamic")]
- private void Scenario_DynamicIDO_Simple() {
- //Get a simple Dynamic IDO
- TestDynamicObject dyn = new TestDynamicObject();
-
- #region CallSite for each MetaAction on this IDO
- var call = CallSite<Func<CallSite, object, object>>.Create(new TestInvokeMemberBinder("member"));
- var convert = CallSite<Func<CallSite, object, string>>.Create(new TestConvertBinder(typeof(String), true));
- var create = CallSite<Func<CallSite, object, object>>.Create(new TestCreateBinder());
- var deleteIndex = CallSite<Action<CallSite, object>>.Create(new TestDeleteIndexBinder());
- var deleteMember = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("member"));
- var getIndex = CallSite<Func<CallSite, object, object>>.Create(new TestGetIndexBinder());
- var getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("member"));
- var invoke = CallSite<Func<CallSite, object, object>>.Create(new TestInvokeBinder());
- var binaryOperation = CallSite<Func<CallSite, object, object, object>>.Create(new TestBinaryOperationBinder(ExpressionType.Add));
- var unaryOperation = CallSite<Func<CallSite, object, object>>.Create(new TestUnaryOperationBinder(ExpressionType.Increment));
- var setIndex = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetIndexBinder());
- var setIndex2 = CallSite<Func<CallSite, object, object, object, object>>.Create(new TestSetIndexBinder());
- var setMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member"));
- #endregion
-
- /* Invoke each CallSite. We're using a basic derivation of Dynamic which applies no binding
- * logic of its own. The default binding of Dynamic is to fallback to the supplied CallSiteBinder
- * every time.
- *
- * We're also using fairly basic derivations of the basic StandardActions for our CallSiteBinders
- * that return a Rule that throws a special BindingException when invoked. This is enough to
- * let us know that the basic binding mechanism worked from end-to-end.
- */
- AssertExceptionThrown<BindingException>(() => call.Target(call, dyn));
- AssertExceptionThrown<BindingException>(() => convert.Target(convert, dyn));
- AssertExceptionThrown<BindingException>(() => create.Target(create, dyn));
- AssertExceptionThrown<BindingException>(() => deleteIndex.Target(deleteIndex, dyn));
- AssertExceptionThrown<BindingException>(() => deleteMember.Target(deleteMember, dyn));
- AssertExceptionThrown<BindingException>(() => getIndex.Target(getIndex, dyn));
- AssertExceptionThrown<BindingException>(() => getMember.Target(getMember, dyn));
- AssertExceptionThrown<BindingException>(() => invoke.Target(invoke, dyn));
- AssertExceptionThrown<BindingException>(() => binaryOperation.Target(binaryOperation, dyn, 5));
- AssertExceptionThrown<BindingException>(() => unaryOperation.Target(unaryOperation, dyn));
- AssertExceptionThrown<ArgumentException>(() => setIndex.Target(setIndex, dyn, 3));
- AssertExceptionThrown<BindingException>(() => setIndex2.Target(setIndex2, dyn, 3, 10));
- AssertExceptionThrown<BindingException>(() => setMember.Target(setMember, dyn, 5));
- }
-
- [Test("Simple cases for a derivation DynamicObject that fails each operation")]
- private void Scenario_FailingDynamicObject() {
- //Get a simple Dynamic IDO
- TestDynamicObject3 dyn = new TestDynamicObject3();
-
- #region CallSite for each MetaAction on this IDO
- var call = CallSite<Func<CallSite, object, object>>.Create(new TestInvokeMemberBinder("member"));
- var convert = CallSite<Func<CallSite, object, string>>.Create(new TestConvertBinder(typeof(String), true));
- var create = CallSite<Func<CallSite, object, object>>.Create(new TestCreateBinder());
- var deleteIndex = CallSite<Action<CallSite, object>>.Create(new TestDeleteIndexBinder());
- var deleteMember = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("member"));
- var getIndex = CallSite<Func<CallSite, object, object>>.Create(new TestGetIndexBinder());
- var getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("member"));
- var invoke = CallSite<Func<CallSite, object, object>>.Create(new TestInvokeBinder());
- var binaryOperation = CallSite<Func<CallSite, object, object, object>>.Create(new TestBinaryOperationBinder(ExpressionType.Add));
- var unaryOperation = CallSite<Func<CallSite, object, object>>.Create(new TestUnaryOperationBinder(ExpressionType.Increment));
- var setIndex = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetIndexBinder());
- var setIndex2 = CallSite<Func<CallSite, object, object, object, object>>.Create(new TestSetIndexBinder());
- var setMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member"));
- #endregion
-
- AssertExceptionThrown<BindingException>(() => call.Target(call, dyn));
- AssertExceptionThrown<BindingException>(() => convert.Target(convert, dyn));
- AssertExceptionThrown<BindingException>(() => create.Target(create, dyn));
- AssertExceptionThrown<BindingException>(() => deleteIndex.Target(deleteIndex, dyn));
- AssertExceptionThrown<BindingException>(() => deleteMember.Target(deleteMember, dyn));
- AssertExceptionThrown<BindingException>(() => getIndex.Target(getIndex, dyn));
- AssertExceptionThrown<BindingException>(() => getMember.Target(getMember, dyn));
- AssertExceptionThrown<BindingException>(() => invoke.Target(invoke, dyn));
- AssertExceptionThrown<BindingException>(() => binaryOperation.Target(binaryOperation, dyn, 5));
- AssertExceptionThrown<BindingException>(() => unaryOperation.Target(unaryOperation, dyn));
- AssertExceptionThrown<ArgumentException>(() => setIndex.Target(setIndex, dyn, 3));
- AssertExceptionThrown<BindingException>(() => setIndex2.Target(setIndex2, dyn, 3, 10));
- AssertExceptionThrown<BindingException>(() => setMember.Target(setMember, dyn, 5));
- }
-
- [Test("Simple cases for a basic Expando IDO")]
- private void Scenario_ExpandoObject() {
- //ExpandoObject is a real IDO implementing several actions
- var exp = new ExpandoObject();
-
- #region CallSite for each action
- var invokeMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestInvokeMemberBinder("member"));
- var deleteIndex = CallSite<Action<CallSite, object>>.Create(new TestDeleteIndexBinder());
- var deleteMember = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("member"));
- var deleteMemberUCase = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("MEMBER"));
- var setIndex = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetIndexBinder());
- var setMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member"));
- var setMemberUCase = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("MEMBER"));
- var setIndex2 = CallSite<Func<CallSite, object, object, object, object>>.Create(new TestSetIndexBinder());
- var convert = CallSite<Func<CallSite, object, string>>.Create(new TestConvertBinder(typeof(String), true));
- var create = CallSite<Func<CallSite, object, object>>.Create(new TestCreateBinder());
- var getIndex = CallSite<Func<CallSite, object, object>>.Create(new TestGetIndexBinder());
- var getMember = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("member"));
- var getMemberUCase = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("MEMBER"));
- var getMember2 = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("__code__")); //GetMember2 gets a member in the language binder.
- var invoke = CallSite<Func<CallSite, object, object>>.Create(new TestInvokeBinder());
- var unaryOperationNeg = CallSite<Func<CallSite, object, object>>.Create(new TestUnaryOperationBinder(ExpressionType.Increment));
- var binaryOperationNeg = CallSite<Func<CallSite, object, object, object>>.Create(new TestBinaryOperationBinder(ExpressionType.Add));
- #endregion
-
- //Those actions implemented by ExpandoObject should succeed (SetMember, GetMember, etc).
- //The others should fall back to the CallSiteBinder and trigger a BindingException.
-
- Assert.AreEqual(getMember.Target(getMember2, exp), "123");
-
- //deleting a non-existing member results in falling back to the language's binder
- AssertExceptionThrown<BindingException>(() => deleteMember.Target(deleteMember, exp));
-
- //Actions implemented by ExpandoObject (GetMember, SetMember, DeleteMember)
- AssertExceptionThrown<BindingException>(() => getMember.Target(getMember, exp));
- AssertExceptionThrown<BindingException>(() => getMemberUCase.Target(getMemberUCase, exp));
- AssertExceptionThrown<BindingException>(() => deleteMember.Target(deleteMember, exp));
-
- setMember.Target(setMember, exp, 52);
-
- Assert.AreEqual(getMember.Target(getMember, exp), 52);
- AssertExceptionThrown<BindingException>(() => getMemberUCase.Target(getMemberUCase, exp));
-
- setMemberUCase.Target(setMemberUCase, exp, 9);
-
- Assert.AreEqual(getMember.Target(getMember, exp), 52);
- Assert.AreEqual(getMemberUCase.Target(getMemberUCase, exp), 9);
-
- deleteMember.Target(deleteMember, exp);
-
- AssertExceptionThrown<BindingException>(() => getMember.Target(getMember, exp));
- Assert.AreEqual(getMemberUCase.Target(getMemberUCase, exp), 9);
-
- deleteMemberUCase.Target(deleteMemberUCase, exp);
-
- AssertExceptionThrown<BindingException>(() => getMember.Target(getMember, exp));
- AssertExceptionThrown<BindingException>(() => getMemberUCase.Target(getMemberUCase, exp));
-
- //assign a delegate value to the member
- setMember.Target(setMember, exp, (Func<int, int>)(x => x + 1));
-
- //invokeMember should work since the member value is invokable now.
- Assert.AreEqual(invokeMember.Target(invokeMember, exp, 100), 101);
-
- setMember.Target(setMember, exp, 52);
-
- //Actions not implemented by ExpandoObject (which default to our basic MetaActions, which return rules throwing BindingErrors)
- //the member value is not invokable so invokeMember will result in exception
- AssertExceptionThrown<BindingException>(() => invokeMember.Target(invokeMember, exp, 100));
- AssertExceptionThrown<BindingException>(() => convert.Target(convert, exp));
- AssertExceptionThrown<BindingException>(() => create.Target(create, exp));
- AssertExceptionThrown<BindingException>(() => deleteIndex.Target(deleteIndex, exp));
- AssertExceptionThrown<BindingException>(() => getIndex.Target(getIndex, exp));
- AssertExceptionThrown<BindingException>(() => invoke.Target(invoke, exp));
- AssertExceptionThrown<BindingException>(() => binaryOperationNeg.Target(binaryOperationNeg, exp, 7));
- AssertExceptionThrown<BindingException>(() => unaryOperationNeg.Target(unaryOperationNeg, exp));
- AssertExceptionThrown<ArgumentException>(() => setIndex.Target(setIndex, exp, 3));
- AssertExceptionThrown<BindingException>(() => setIndex2.Target(setIndex2, exp, 3, 10));
- }
-
- [Test("Basic tests for INotifyPropertyChanged on ExpandoObject")]
- private void Scenario_ExpandoObject_NotifyPropertyChanged() {
- var expando = new ExpandoObject();
- var inpc = expando as INotifyPropertyChanged;
- var dict = expando as IDictionary<string, object>;
-
- string changed = "";
- PropertyChangedEventHandler handler = (s, e) => {
- Assert.AreEqual(expando, s);
- changed += e.PropertyName;
- };
-
- inpc.PropertyChanged += handler;
-
- Assert.AreEqual(changed, "");
- SetMember(expando, "foo", 123);
- Assert.AreEqual(changed, "foo"); changed = "";
- SetMemberIgnoreCase(expando, "FOO", 456);
- Assert.AreEqual(changed, "foo"); changed = "";
- DeleteMember(expando, "foo");
- Assert.AreEqual(changed, "foo"); changed = "";
- AssertExceptionThrown<BindingException>(() => DeleteMember(expando, "foo"));
- Assert.AreEqual(changed, "");
- SetMember(expando, "foo", 123);
- Assert.AreEqual(changed, "foo"); changed = "";
- SetMember(expando, "bar", 456);
- Assert.AreEqual(changed, "bar"); changed = "";
- SetMember(expando, "zed", 456);
- Assert.AreEqual(changed, "zed"); changed = "";
- SetMember(expando, "red", 789);
- Assert.AreEqual(changed, "red"); changed = "";
- DeleteMemberIgnoreCase(expando, "ZeD");
- Assert.AreEqual(changed, "zed"); changed = "";
- dict.Clear();
- Assert.AreEqual(changed, "foobarred"); changed = "";
-
- dict.Add("baz", "555");
- Assert.AreEqual(changed, "baz"); changed = "";
- dict["baz"] = "555";
- // We detect duplicates, so we don't fire it.
- // It would be okay to fire here, though.
- Assert.AreEqual(changed, "");
-
- dict["baz"] = "abc";
- Assert.AreEqual(changed, "baz"); changed = "";
- dict.Remove(new KeyValuePair<string, object>("baz", "zzz"));
- Assert.AreEqual(changed, "");
- dict.Remove(new KeyValuePair<string, object>("baz", "abc"));
- Assert.AreEqual(changed, "baz"); changed = "";
- dict["baz"] = "abc";
- dict.Remove("baz");
- Assert.AreEqual(changed, "bazbaz"); changed = "";
-
- // Add and remove handlers
- inpc.PropertyChanged += handler;
- dict["quux"] = 1;
- Assert.AreEqual(changed, "quuxquux"); changed = "";
-
- inpc.PropertyChanged -= handler;
-
- dict["quux"] = 2;
- Assert.AreEqual(changed, "quux"); changed = "";
-
- inpc.PropertyChanged -= handler;
-
- dict["quux"] = 3;
- Assert.AreEqual(changed, "");
- }
-
- private static void SetMember(ExpandoObject expando, string name, object value) {
- var site = CallSite<Action<CallSite, ExpandoObject, object>>.Create(new TestSetMemberBinder(name));
- site.Target(site, expando, value);
- }
-
- private static void SetMemberIgnoreCase(ExpandoObject expando, string name, object value) {
- var site = CallSite<Action<CallSite, ExpandoObject, object>>.Create(new TestSetMemberBinder(name, true));
- site.Target(site, expando, value);
- }
-
- private static void DeleteMember(ExpandoObject expando, string name) {
- var site = CallSite<Action<CallSite, ExpandoObject>>.Create(new TestDeleteMemberBinder(name));
- site.Target(site, expando);
- }
-
- private static void DeleteMemberIgnoreCase(ExpandoObject expando, string name) {
- var site = CallSite<Action<CallSite, ExpandoObject>>.Create(new TestDeleteMemberBinder(name, true));
- site.Target(site, expando);
- }
-
- private static object GetMember(ExpandoObject expando, string name) {
- var site = CallSite<Func<CallSite, ExpandoObject, object>>.Create(new TestGetMemberBinder(name));
- return site.Target(site, expando);
- }
-
- [Test("Test GetDynamicMemberNames for a basic Expando IDO")]
- private void Scenario_ExpandoObjectGetDynamicMemberNames() {
- var exp = new ExpandoObject();
- var setMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member1"));
- setMember.Target(setMember, exp, 10);
-
- var mo = ((IDynamicMetaObjectProvider)exp).GetMetaObject(Expression.Parameter(typeof(object), "arg0"));
-
- List<string> memberNames = new List<string>(mo.GetDynamicMemberNames());
- Assert.AreEqual(1, memberNames.Count);
- Assert.AreEqual("member1", memberNames[0]);
-
- setMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member2"));
- setMember.Target(setMember, exp, 20);
- setMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member3"));
- setMember.Target(setMember, exp, 30);
-
- memberNames = new List<string>(mo.GetDynamicMemberNames());
- Assert.AreEqual(3, memberNames.Count);
-
- var deleteMember = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("member1"));
- deleteMember.Target(deleteMember, exp);
-
- memberNames = new List<string>(mo.GetDynamicMemberNames());
- Assert.AreEqual(2, memberNames.Count);
-
- //Add the deleted member back. Since ExpandoObject didn't really deleted the member from the class
- //(only the value got deleted), the added member should be at the original index.
- setMember = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member1"));
- setMember.Target(setMember, exp, 100);
- memberNames = new List<string>(mo.GetDynamicMemberNames());
- Assert.AreEqual(3, memberNames.Count);
- }
-
- #region Testing case-insensitive behavior of ExpandoObject
-
- [Test("Test ExpandoObject when used with case-insensitive get binders-1")]
- private void Senario_ExpandoObjectCaseInsensitiveGet1() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- var getMemberIgnoreCase = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("FoO", true));
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase.Target(getMemberIgnoreCase, exp));
-
- ((IDictionary<string, object>)exp).Remove("foo");
- Assert.AreEqual(getMemberIgnoreCase.Target(getMemberIgnoreCase, exp), 2);
-
- ((IDictionary<string, object>)exp).Remove("FOO");
- AssertExceptionThrown<BindingException>(() => getMemberIgnoreCase.Target(getMemberIgnoreCase, exp));
- }
-
- [Test("Test ExpandoObject when used with case-insensitive set binders-1")]
- private void Senario_ExpandoObjectCaseInsensitiveSet1() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- var setMemberIgnoreCase = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("FoO", true));
- AssertExceptionThrown<AmbiguousMatchException>(() => setMemberIgnoreCase.Target(setMemberIgnoreCase, exp, 100));
-
- ((IDictionary<string, object>)exp).Remove("foo");
- setMemberIgnoreCase.Target(setMemberIgnoreCase, exp, 100);
- Assert.AreEqual(((IDictionary<string, object>)exp)["FOO"], 100);
-
- ((IDictionary<string, object>)exp).Remove("FOO");
- setMemberIgnoreCase.Target(setMemberIgnoreCase, exp, 101);
- Assert.AreEqual(((IDictionary<string, object>)exp)["FoO"], 101);
- }
-
- [Test("Test ExpandoObject when used with case-insensitive delete binders-1")]
- private void Senario_ExpandoObjectCaseInsensitiveDelete1() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- var deleteMemberIgnoreCase = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("FoO", true));
-
- AssertExceptionThrown<AmbiguousMatchException>(() => deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp));
-
- ((IDictionary<string, object>)exp).Remove("foo");
- Assert.IsTrue(((IDictionary<string, object>)exp).ContainsKey("FOO"));
- deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp);
- Assert.IsFalse(((IDictionary<string, object>)exp).ContainsKey("FOO"));
-
- AssertExceptionThrown<BindingException>(() => deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp));
- }
-
-
- [Test("Test ExpandoObject when used with case-insensitive get binders-2")]
- private void Senario_ExpandoObjectCaseInsensitiveGet2() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- ((IDictionary<string, object>)exp).Remove("foo");
- ((IDictionary<string, object>)exp).Remove("FOO");
-
- var getMemberIgnoreCase = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("FoO", true));
-
- AssertExceptionThrown<BindingException>(() => getMemberIgnoreCase.Target(getMemberIgnoreCase, exp));
-
- ((IDictionary<string, object>)exp)["foo"] = 1;
- Assert.AreEqual(getMemberIgnoreCase.Target(getMemberIgnoreCase, exp), 1);
-
- ((IDictionary<string, object>)exp)["FOO"] = 2;
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase.Target(getMemberIgnoreCase, exp));
- }
-
- [Test("Test ExpandoObject when used with case-insensitive set binders-2")]
- private void Senario_ExpandoObjectCaseInsensitiveSet2() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- ((IDictionary<string, object>)exp).Remove("foo");
- ((IDictionary<string, object>)exp).Remove("FOO");
-
- var setMemberIgnoreCase = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("FoO", true));
-
- Assert.IsFalse(((IDictionary<string, object>)exp).ContainsKey("foO"));
- setMemberIgnoreCase.Target(setMemberIgnoreCase, exp, 101);
- Assert.AreEqual(((IDictionary<string, object>)exp)["FoO"], 101);
-
- ((IDictionary<string, object>)exp)["foo"] = 1;
- AssertExceptionThrown<AmbiguousMatchException>(() => setMemberIgnoreCase.Target(setMemberIgnoreCase, exp, 100));
- }
-
- [Test("Test ExpandoObject when used with case-insensitive delete binders-2")]
- private void Senario_ExpandoObjectCaseInsensitiveDelete2() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- ((IDictionary<string, object>)exp).Remove("foo");
- ((IDictionary<string, object>)exp).Remove("FOO");
-
- var deleteMemberIgnoreCase = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("FoO", true));
-
- AssertExceptionThrown<BindingException>(() => deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp));
-
- ((IDictionary<string, object>)exp)["foo"] = 1;
- Assert.IsTrue(((IDictionary<string, object>)exp).ContainsKey("foo"));
- deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp);
- Assert.IsFalse(((IDictionary<string, object>)exp).ContainsKey("foo"));
-
- ((IDictionary<string, object>)exp)["foo"] = 1;
- ((IDictionary<string, object>)exp)["FOO"] = 2;
- AssertExceptionThrown<AmbiguousMatchException>(() => deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp));
- }
-
- [Test("Test ExpandoObject when used with case-insensitive get binders-3")]
- private void Senario_ExpandoObjectCaseInsensitiveGet3() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- ((IDictionary<string, object>)exp).Remove("FOO");
-
- var getMemberIgnoreCase = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("FoO", true));
-
- Assert.AreEqual(getMemberIgnoreCase.Target(getMemberIgnoreCase, exp), 1);
-
- ((IDictionary<string, object>)exp).Remove("foo");
- AssertExceptionThrown<BindingException>(() => getMemberIgnoreCase.Target(getMemberIgnoreCase, exp));
-
- ((IDictionary<string, object>)exp)["foo"] = 1;
- ((IDictionary<string, object>)exp)["FOO"] = 2;
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase.Target(getMemberIgnoreCase, exp));
- }
-
- [Test("Test ExpandoObject when used with case-insensitive set binders-3")]
- private void Senario_ExpandoObjectCaseInsensitiveSet3() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- ((IDictionary<string, object>)exp).Remove("foo");
-
- var setMemberIgnoreCase = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("FoO", true));
-
- Assert.AreEqual(((IDictionary<string, object>)exp)["FOO"], 2);
- setMemberIgnoreCase.Target(setMemberIgnoreCase, exp, 101);
- Assert.AreEqual(((IDictionary<string, object>)exp)["FOO"], 101);
-
- ((IDictionary<string, object>)exp)["foo"] = 1;
- AssertExceptionThrown<AmbiguousMatchException>(() => setMemberIgnoreCase.Target(setMemberIgnoreCase, exp, 100));
- }
-
- [Test("Test ExpandoObject when used with case-insensitive delete binders-3")]
- private void Senario_ExpandoObjectCaseInsensitiveDelete3() {
- var exp = new ExpandoObject();
- ((IDictionary<string, object>)exp).Add("foo", 1);
- ((IDictionary<string, object>)exp).Add("FOO", 2);
-
- ((IDictionary<string, object>)exp).Remove("FOO");
-
- var deleteMemberIgnoreCase = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("FoO", true));
-
- Assert.IsTrue(((IDictionary<string, object>)exp).ContainsKey("foo"));
- deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp);
- Assert.IsFalse(((IDictionary<string, object>)exp).ContainsKey("foo"));
-
- AssertExceptionThrown<BindingException>(() => deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp));
-
- ((IDictionary<string, object>)exp)["foo"] = 1;
- ((IDictionary<string, object>)exp)["FOO"] = 2;
- AssertExceptionThrown<AmbiguousMatchException>(() => deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp));
- }
-
- [Test("Test ExpandoObject when used with binders that mix case sensitivity")]
- private void Scenario_ExpandoObjectMixCaseSensitivity() {
- var exp = new ExpandoObject();
- var setMember1 = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("Member"));
- var setMember2 = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member"));
- var setMember3 = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("MEMBER"));
- var setMemberIgnoreCase1 = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("member", true));
- var setMemberIgnoreCase2 = CallSite<Func<CallSite, object, object, object>>.Create(new TestSetMemberBinder("MEMBER", true));
- var getMember1 = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("Member"));
- var getMember2 = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("member"));
- var getMemberIgnoreCase1 = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("member", true));
- var getMemberIgnoreCase2 = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("Member", true));
- var getMemberIgnoreCase3 = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("MEMBER", true));
- var deleteMember = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("member"));
- var deleteMemberIgnoreCase = CallSite<Action<CallSite, object>>.Create(new TestDeleteMemberBinder("member", true));
-
-
- //Verify that ignore case get can fall back correctly when no match
- var getMemberIgnoreCase = CallSite<Func<CallSite, object, object>>.Create(new TestGetMemberBinder("__cOdE__", true));
- Assert.AreEqual("123", getMemberIgnoreCase.Target(getMemberIgnoreCase, exp));
-
- AssertExceptionThrown<BindingException>(() => getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp));
-
- //exp.member = 1 (ignore case)
- setMemberIgnoreCase1.Target(setMemberIgnoreCase1, exp, 100);
-
- //If case insensitive, get the match if there is only one.
- //get exp.Member = 100, found the only match
- Assert.AreEqual(getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp), 100);
- Assert.AreEqual(getMemberIgnoreCase2.Target(getMemberIgnoreCase2, exp), 100);
-
- deleteMember.Target(deleteMember, exp);
- AssertExceptionThrown<BindingException>(() => getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp));
- ((IDictionary<string, object>)exp).Add("member", 1001);
- Assert.AreEqual(getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp), 1001);
- ((IDictionary<string, object>)exp)["member"] = 1;
-
- //exp.Member = 1 (case insensitive) overwrites the matching member
- setMemberIgnoreCase2.Target(setMemberIgnoreCase2, exp, 1);
- Assert.AreEqual(getMember2.Target(getMember2, exp), 1);
- Assert.AreEqual(getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp), 1);
- Assert.AreEqual(getMemberIgnoreCase2.Target(getMemberIgnoreCase2, exp), 1);
-
- //exp.Member = 2 (case sensitive)
- setMember1.Target(setMember1, exp, 2);
-
- //get exp.member (ignore case) results in AmbigousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp));
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase2.Target(getMemberIgnoreCase2, exp));
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase3.Target(getMemberIgnoreCase3, exp));
-
- //Delete exp.member (case sensitive)
- deleteMember.Target(deleteMember, exp);
- Assert.AreEqual(getMember1.Target(getMember1, exp), 2);
- AssertExceptionThrown<BindingException>(() => getMember2.Target(getMember2, exp));
- Assert.AreEqual(getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp), 2);
- Assert.AreEqual(getMemberIgnoreCase2.Target(getMemberIgnoreCase1, exp), 2);
-
- //exp.member = 1 (case sensitive)
- setMember2.Target(setMember2, exp, 1);
-
- //exp.MEMBER = 3 (ignore case) results in AmbiguousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => setMemberIgnoreCase2.Target(setMemberIgnoreCase2, exp, 3));
-
- //set exp.MEMBER = 3, case-sensitive
- setMember3.Target(setMember3, exp, 3);
-
- //get exp.MEMBER (ignore case) AmbiguousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase3.Target(getMemberIgnoreCase3, exp));
-
- //Get exp.Member case sensitively
- Assert.AreEqual(getMember1.Target(getMember1, exp), 2);
- //Get exp.member case sensitively
- Assert.AreEqual(getMember2.Target(getMember2, exp), 1);
-
- //Delete exp.member (case sensitive)
- deleteMember.Target(deleteMember, exp);
-
- //Get exp.member (case sensitive) results in BindingException
- AssertExceptionThrown<BindingException>(() => getMember2.Target(getMember2, exp));
- //Get exp.Member case sensitively
- Assert.AreEqual(getMember1.Target(getMember1, exp), 2);
-
- //Get exp.member (case insensitive) results in AmbiguousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp));
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase2.Target(getMemberIgnoreCase2, exp));
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase3.Target(getMemberIgnoreCase3, exp));
-
- //add the deleted expt.member back (case sensitive)
- setMember2.Target(setMember2, exp, 1);
-
- //get exp.member (case insensitive) results in AmbiguousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp));
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase2.Target(getMemberIgnoreCase2, exp));
-
- //apply a case insensitive delete binder results in AmbigousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp));
- //Delete exp.member (case sensitive)
- deleteMember.Target(deleteMember, exp);
-
- //delete exp.member case insensitively results in AmbiguousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => deleteMemberIgnoreCase.Target(deleteMemberIgnoreCase, exp));
-
- //Get exp.member case sensitively results in exception
- AssertExceptionThrown<BindingException>(() => getMember2.Target(getMember2, exp));
- //Set exp.member case insensitively results in AmbiguousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => setMemberIgnoreCase2.Target(setMemberIgnoreCase2, exp, 100));
- //Get exp.member case insensitively results in AmbiguousMatchException
- AssertExceptionThrown<AmbiguousMatchException>(() => getMemberIgnoreCase1.Target(getMemberIgnoreCase1, exp));
- }
-
- #endregion
-
- [Test("Test the IDictionary<string, object> members of ExpandoObject")]
- private void Scenario_ExpandoObjectIDictionaryMembers() {
- var exp = (IDictionary<string, object>)(new ExpandoObject());
-
- Assert.IsFalse(exp.IsReadOnly);
-
- KeyValuePair<string, object> kv1 = new KeyValuePair<string, object>("a", 1);
- KeyValuePair<string, object> kv2 = new KeyValuePair<string, object>("b", 2);
- KeyValuePair<string, object> kv3 = new KeyValuePair<string, object>("c", 3);
- KeyValuePair<string, object> kv4 = new KeyValuePair<string, object>("c", 4);
- KeyValuePair<string, object> kv5 = new KeyValuePair<string, object>("d", 5);
-
- exp.Add("a", 1);
- exp.Add("b", 2);
- exp.Add(kv3);
-
- Assert.IsTrue(exp.Contains(kv1));
- Assert.IsTrue(exp.Contains(kv2));
- Assert.IsTrue(exp.Contains(kv3));
- Assert.IsFalse(exp.Contains(kv5));
- Assert.IsTrue(exp.ContainsKey("a"));
- Assert.IsTrue(exp.ContainsKey("b"));
- Assert.IsTrue(exp.ContainsKey("c"));
-
- Assert.IsTrue(exp.Remove(kv3));
- Assert.IsFalse(exp.ContainsKey("c"));
- Assert.IsFalse(exp.Remove(kv3)); //Try to remove non-existant
- exp.Add(kv3);
-
- Assert.IsFalse(exp.Remove(kv4)); //Remove KVP with same key, but different value
- Assert.AreEqual(3, exp.Count); //Nothing should be removed
-
- //adding the same key causes exception
- AssertExceptionThrown<ArgumentException>(() => exp.Add("a", 100));
-
- Assert.AreEqual(3, exp.Count);
- List<string> keys = new List<string>(exp.Keys);
- Assert.AreEqual(keys[0], "a");
- List<object> values = new List<object>(exp.Values);
- Assert.AreEqual(values[2], 3);
-
- // Various valid/invalid cases with KeyCollection
- AssertExceptionThrown<NotSupportedException>(() => exp.Keys.Add("x"));
- AssertExceptionThrown<NotSupportedException>(() => exp.Keys.Clear());
- Assert.IsTrue(exp.Keys.Contains("a"));
- Assert.IsFalse(exp.Keys.Contains("blah"));
- Assert.IsTrue(exp.Keys.IsReadOnly);
- AssertExceptionThrown<NotSupportedException>(() => exp.Keys.Remove("HI"));
- Assert.IsTrue(exp.Keys.Contains("b"));
- Assert.IsFalse(exp.Keys.Contains("foo"));
-
- // Various valid/invalid cases with ValueCollection
- AssertExceptionThrown<NotSupportedException>(() => exp.Values.Add(2));
- AssertExceptionThrown<NotSupportedException>(() => exp.Values.Clear());
- Assert.IsTrue(exp.Values.Contains(2));
- Assert.IsFalse(exp.Values.Contains(-2));
- Assert.IsFalse(exp.Values.Contains(-2));
- Assert.IsTrue(exp.Values.IsReadOnly);
- AssertExceptionThrown<NotSupportedException>(() => exp.Values.Remove(1));
- Assert.IsFalse(exp.Values.Contains("foo"));
-
- //Iterate the Keys or Values collection and the expando changes will
- //cause InvalidOperationException
- AssertExceptionThrown<InvalidOperationException>(() => IterateAndModifyKeyCollection(exp));
- AssertExceptionThrown<InvalidOperationException>(() => IterateAndModifyValueCollection(exp));
-
- // Additional iterator cases
- IterateAndModifyKeyCollection2(exp);
- IterateAndModifyValueCollection2(exp);
- IterateAndModifyKeyCollection3(exp);
- IterateAndModifyValueCollection3(exp);
- IterateAndModifyKeyCollection4(exp);
- IterateAndModifyValueCollection4(exp);
-
-
- object value;
- Assert.IsTrue(exp.TryGetValue("b", out value));
- Assert.AreEqual(2, value);
-
- Assert.IsFalse(exp.TryGetValue("x", out value));
-
- KeyValuePair<string, object>[] arr = new KeyValuePair<string, object>[10];
- exp.CopyTo(arr, 0);
- Assert.AreEqual(arr[2].Value, 3);
-
- AssertExceptionThrown<ArgumentOutOfRangeException>(() => exp.CopyTo(arr, 8));
-
- foreach (var kv in exp) {
- Assert.IsTrue(kv.Value != null);
- }
-
- // Use non-generic collection
- var exp2 = (System.Collections.IEnumerable)(exp);
- int cnt = 0;
- foreach (var kv in exp2) {
- cnt++;
- }
- Assert.AreEqual(exp.Count, cnt);
-
- //iterate and modify the expando will cause exception
- AssertExceptionThrown<InvalidOperationException>(() => IterateAndModifyExpando(exp));
-
- Assert.IsTrue(exp.Remove("a"));
-
- Assert.IsFalse(exp.Remove("a")); //the 2nd time will fail.
- //Assert.AreEqual(2, exp.Count);
-
- //add ["a", 100]
- exp.Add("a", 100);
- Assert.AreEqual(100, exp["a"]);
- exp["a"] = 1;
- Assert.AreEqual(1, exp["a"]);
-
- AssertExceptionThrown<KeyNotFoundException>(() => value = exp["e"]);
- exp["e"] = 5;
- Assert.AreEqual(exp["e"], 5);
- exp["e"] = 6;
- Assert.AreEqual(exp["e"], 6);
- Assert.AreEqual(exp.Remove(new KeyValuePair<string, object>("e", 5)), false);
- Assert.AreEqual(exp.Remove(new KeyValuePair<string, object>("e", 6)), true);
- AssertExceptionThrown<KeyNotFoundException>(() => value = exp["e"]);
-
- exp.Clear();
-
- Assert.AreEqual(0, exp.Count);
- Assert.AreEqual(0, exp.Values.Count);
- Assert.AreEqual(0, exp.Keys.Count);
-
- // Some additional cases around null
- var expnull = (IDictionary<string, object>)(new ExpandoObject());
- expnull.Add("a", null);
- AssertExceptionThrown<ArgumentNullException>(() => expnull.Add(null, "SDF"));
- KeyValuePair<string, object> kvnull = new KeyValuePair<string, object>();
- AssertExceptionThrown<ArgumentNullException>(() => expnull.Add(kvnull));
- Assert.IsFalse(expnull.Contains(kvnull));
-
- ExpandoObject expando = new ExpandoObject();
- exp = (IDictionary<string, object>)expando;
- // thread safety, multiple threads adding to the same object.
- // All values should be added
- Thread t1 = new Thread(() => ExpandoThreadAdder(expando, "Thread1_"));
- Thread t2 = new Thread(() => ExpandoThreadAdder(expando, "Thread2_"));
- Thread t3 = new Thread(() => ExpandoThreadAdder(expando, "Thread3_"));
- Thread t4 = new Thread(() => ExpandoThreadAdder(expando, "Thread4_"));
-
- t1.Start();
- t2.Start();
- t3.Start();
- t4.Start();
-
- t1.Join();
- t2.Join();
- t3.Join();
- t4.Join();
-
- // all values should be set
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 1000; j++) {
- Assert.AreEqual(exp["Thread" + (i + 1) + "_" + j.ToString("0000")], j);
- }
- }
-
- t1 = new Thread(() => ExpandoThreadAdderRemover(expando, "Thread1_"));
- t2 = new Thread(() => ExpandoThreadAdderRemover(expando, "Thread2_"));
- t3 = new Thread(() => ExpandoThreadAdderRemover(expando, "Thread3_"));
- t4 = new Thread(() => ExpandoThreadAdderRemover(expando, "Thread4_"));
-
- t1.Start();
- t2.Start();
- t3.Start();
- t4.Start();
-
- t1.Join();
- t2.Join();
- t3.Join();
- t4.Join();
-
- // all values should have been set and removed
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 1000; j++) {
- Assert.AreEqual(exp.ContainsKey("Thread" + (i + 1) + "_" + j.ToString("0000")), false);
- }
- }
- }
-
- [Test("Test the Contains member of ExpandoObject containing a null value")]
- private void Scenario_ExpandoObjectWithNullValue() {
- var exp = (IDictionary<string, object>)(new ExpandoObject());
-
- exp.Add("a", null);
- Assert.IsTrue(exp.Values.…
Large files files are truncated, but you can click here to view the full file