From 7a2a2e68e7e235b9d79c09d98a4cf0b6f87a2a85 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 14 Aug 2009 14:18:56 +0100 Subject: [PATCH 1/6] Remove the script sponsor logic because scripts are timing out again. This needs to be looked into. This commit, unfortunately, reinstates a memory leak in regions that see significant script fluctuation, e.g. lots of scripted attachments, or script development. --- .../Shared/Api/Implementation/LSL_Api.cs | 6 +++--- .../Shared/Api/Implementation/OSSL_Api.cs | 6 +++--- .../ScriptEngine/Shared/Api/Runtime/ScriptBase.cs | 15 ++++++++------- .../Shared/Instance/ScriptInstance.cs | 7 +------ 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ff85b96d50..691732aa75 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -125,9 +125,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (lease.CurrentState == LeaseState.Initial) { - lease.InitialLeaseTime = TimeSpan.FromMinutes(1.0); - lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); - lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); + lease.InitialLeaseTime = TimeSpan.FromMinutes(0); +// lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); +// lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); } return lease; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 6539bda958..6e3a3abb61 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -166,9 +166,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (lease.CurrentState == LeaseState.Initial) { - lease.InitialLeaseTime = TimeSpan.FromMinutes(1.0); - lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); - lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); + lease.InitialLeaseTime = TimeSpan.FromMinutes(0); +// lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); +// lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); } return lease; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs index d119a7739d..838cafb820 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs @@ -42,16 +42,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public partial class ScriptBaseClass : MarshalByRefObject, IScript { private Dictionary inits = new Dictionary(); - private ScriptSponsor m_sponser; +// private ScriptSponsor m_sponser; public override Object InitializeLifetimeService() { ILease lease = (ILease)base.InitializeLifetimeService(); if (lease.CurrentState == LeaseState.Initial) { - lease.InitialLeaseTime = TimeSpan.FromMinutes(1.0); - lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); - lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); + // Infinite + lease.InitialLeaseTime = TimeSpan.FromMinutes(0); +// lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); +// lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); } return lease; } @@ -79,7 +80,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase } } - m_sponser = new ScriptSponsor(); +// m_sponser = new ScriptSponsor(); } private Executor m_Executor = null; @@ -112,7 +113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return; ILease lease = (ILease)RemotingServices.GetLifetimeService(data as MarshalByRefObject); - lease.Register(m_sponser); +// lease.Register(m_sponser); MethodInfo mi = inits[api]; @@ -126,7 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public void Close() { - m_sponser.Close(); +// m_sponser.Close(); } public Dictionary GetVars() diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 4211cedaa5..7bbaac0a0e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -53,7 +53,7 @@ using OpenSim.Region.ScriptEngine.Interfaces; namespace OpenSim.Region.ScriptEngine.Shared.Instance { - public class ScriptInstance : MarshalByRefObject, IScriptInstance, ISponsor + public class ScriptInstance : MarshalByRefObject, IScriptInstance { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -1006,10 +1006,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { return true; } - - public TimeSpan Renewal(ILease lease) - { - return lease.InitialLeaseTime; - } } } From a851b68333756d11be2c5afe2aa76c58ae771b4b Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 14 Aug 2009 14:27:56 +0100 Subject: [PATCH 2/6] Remove one more sponsor reference --- OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 7bbaac0a0e..225126dcd5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -261,7 +261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance "SecondLife.Script"); ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); - lease.Register(this); +// lease.Register(this); } catch (Exception) { From c18f7560d9ab13c0c7a73c679383ceee13d1b1e3 Mon Sep 17 00:00:00 2001 From: Kunnis Date: Sun, 9 Aug 2009 02:05:21 -0500 Subject: [PATCH 3/6] Adding in Reflection-based testing, to ensure that all properties are covered. --- .../Data/Tests/PropertyCompareConstraint.cs | 298 ++++++++++++++++++ OpenSim/Data/Tests/ScrambleForTesting.cs | 102 ++++++ 2 files changed, 400 insertions(+) create mode 100644 OpenSim/Data/Tests/PropertyCompareConstraint.cs create mode 100644 OpenSim/Data/Tests/ScrambleForTesting.cs diff --git a/OpenSim/Data/Tests/PropertyCompareConstraint.cs b/OpenSim/Data/Tests/PropertyCompareConstraint.cs new file mode 100644 index 0000000000..678501e842 --- /dev/null +++ b/OpenSim/Data/Tests/PropertyCompareConstraint.cs @@ -0,0 +1,298 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using NUnit.Framework; +using NUnit.Framework.Constraints; +using NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.Tests +{ + public static class Constraints + { + //This is here because C# has a gap in the language, you can't infer type from a constructor + public static PropertyCompareConstraint PropertyCompareConstraint(T expected) + { + return new PropertyCompareConstraint(expected); + } + } + + public class PropertyCompareConstraint : NUnit.Framework.Constraints.Constraint + { + private readonly object _expected; + //the reason everywhere uses propertyNames.Reverse().ToArray() is because the stack is backwards of the order we want to display the properties in. + private string failingPropertyName = string.Empty; + private object failingExpected; + private object failingActual; + + public PropertyCompareConstraint(T expected) + { + _expected = expected; + } + + public override bool Matches(object actual) + { + return ObjectCompare(_expected, actual, new Stack()); + } + + private bool ObjectCompare(object expected, object actual, Stack propertyNames) + { + if (actual.GetType() != expected.GetType()) + { + propertyNames.Push("GetType()"); + failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); + propertyNames.Pop(); + failingActual = actual.GetType(); + failingExpected = expected.GetType(); + return false; + } + + if(actual.GetType() == typeof(Color)) + { + Color actualColor = (Color) actual; + Color expectedColor = (Color) expected; + if (actualColor.R != expectedColor.R) + { + propertyNames.Push("R"); + failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); + propertyNames.Pop(); + failingActual = actualColor.R; + failingExpected = expectedColor.R; + return false; + } + if (actualColor.G != expectedColor.G) + { + propertyNames.Push("G"); + failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); + propertyNames.Pop(); + failingActual = actualColor.G; + failingExpected = expectedColor.G; + return false; + } + if (actualColor.B != expectedColor.B) + { + propertyNames.Push("B"); + failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); + propertyNames.Pop(); + failingActual = actualColor.B; + failingExpected = expectedColor.B; + return false; + } + if (actualColor.A != expectedColor.A) + { + propertyNames.Push("A"); + failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); + propertyNames.Pop(); + failingActual = actualColor.A; + failingExpected = expectedColor.A; + return false; + } + return true; + } + + //Skip static properties. I had a nasty problem comparing colors because of all of the public static colors. + PropertyInfo[] properties = expected.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); + foreach (var property in properties) + { + if (ignores.Contains(property.Name)) + continue; + + object actualValue = property.GetValue(actual, null); + object expectedValue = property.GetValue(expected, null); + + //If they are both null, they are equal + if (actualValue == null && expectedValue == null) + continue; + + //If only one is null, then they aren't + if (actualValue == null || expectedValue == null) + { + propertyNames.Push(property.Name); + failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); + propertyNames.Pop(); + failingActual = actualValue; + failingExpected = expectedValue; + return false; + } + + IComparable comp = actualValue as IComparable; + if (comp != null) + { + if (comp.CompareTo(expectedValue) != 0) + { + propertyNames.Push(property.Name); + failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); + propertyNames.Pop(); + failingActual = actualValue; + failingExpected = expectedValue; + return false; + } + continue; + } + + IEnumerable arr = actualValue as IEnumerable; + if (arr != null) + { + List actualList = arr.Cast().ToList(); + List expectedList = ((IEnumerable)expectedValue).Cast().ToList(); + if (actualList.Count != expectedList.Count) + { + propertyNames.Push(property.Name); + propertyNames.Push("Count"); + failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); + failingActual = actualList.Count; + failingExpected = expectedList.Count; + propertyNames.Pop(); + propertyNames.Pop(); + } + //Todo: A value-wise comparison of all of the values. + //Everything seems okay... + continue; + } + + propertyNames.Push(property.Name); + if (!ObjectCompare(expectedValue, actualValue, propertyNames)) + return false; + propertyNames.Pop(); + } + + return true; + } + + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WriteExpectedValue(failingExpected); + } + + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(failingActual); + writer.WriteLine(); + writer.Write(" On Property: " + failingPropertyName); + } + + //These notes assume the lambda: (x=>x.Parent.Value) + //ignores should really contain like a fully dotted version of the property name, but I'm starting with small steps + readonly List ignores = new List(); + public PropertyCompareConstraint IgnoreProperty(Expression> func) + { + Expression express = func.Body; + PullApartExpression(express); + + return this; + } + + private void PullApartExpression(Expression express) + { + //This deals with any casts... like implicit casts to object. Not all UnaryExpression are casts, but this is a first attempt. + if (express is UnaryExpression) + PullApartExpression(((UnaryExpression)express).Operand); + if (express is MemberExpression) + { + //If the inside of the lambda is the access to x, we've hit the end of the chain. + // We should track by the fully scoped parameter name, but this is the first rev of doing this. + if (((MemberExpression)express).Expression is ParameterExpression) + { + ignores.Add(((MemberExpression)express).Member.Name); + } + else + { + //Otherwise there could be more parameters inside... + PullApartExpression(((MemberExpression)express).Expression); + } + } + } + } + + [TestFixture] + public class PropertyCompareConstraintTest + { + public class HasInt + { + public int TheValue { get; set; } + } + + [Test] + public void IntShouldMatch() + { + HasInt actual = new HasInt { TheValue = 5 }; + HasInt expected = new HasInt { TheValue = 5 }; + var constraint = Constraints.PropertyCompareConstraint(expected); + + Assert.That(constraint.Matches(actual), Is.True); + } + + [Test] + public void IntShouldNotMatch() + { + HasInt actual = new HasInt { TheValue = 5 }; + HasInt expected = new HasInt { TheValue = 4 }; + var constraint = Constraints.PropertyCompareConstraint(expected); + + Assert.That(constraint.Matches(actual), Is.False); + } + + + [Test] + public void IntShouldIgnore() + { + HasInt actual = new HasInt { TheValue = 5 }; + HasInt expected = new HasInt { TheValue = 4 }; + var constraint = Constraints.PropertyCompareConstraint(expected).IgnoreProperty(x=>x.TheValue); + + Assert.That(constraint.Matches(actual), Is.True); + } + + [Test] + public void AssetShouldMatch() + { + UUID uuid1 = UUID.Random(); + AssetBase actual = new AssetBase(uuid1, "asset one"); + AssetBase expected = new AssetBase(uuid1, "asset one"); + + var constraint = Constraints.PropertyCompareConstraint(expected); + + Assert.That(constraint.Matches(actual), Is.True); + } + + [Test] + public void AssetShouldNotMatch() + { + UUID uuid1 = UUID.Random(); + AssetBase actual = new AssetBase(uuid1, "asset one"); + AssetBase expected = new AssetBase(UUID.Random(), "asset one"); + + var constraint = Constraints.PropertyCompareConstraint(expected); + + Assert.That(constraint.Matches(actual), Is.False); + } + + [Test] + public void AssetShouldNotMatch2() + { + UUID uuid1 = UUID.Random(); + AssetBase actual = new AssetBase(uuid1, "asset one"); + AssetBase expected = new AssetBase(uuid1, "asset two"); + + var constraint = Constraints.PropertyCompareConstraint(expected); + + Assert.That(constraint.Matches(actual), Is.False); + } + + [Test] + public void TestColors() + { + Color actual = Color.Red; + Color expected = Color.FromArgb(actual.A, actual.R, actual.G, actual.B); + + var constraint = Constraints.PropertyCompareConstraint(expected); + + Assert.That(constraint.Matches(actual), Is.True); + } + } +} \ No newline at end of file diff --git a/OpenSim/Data/Tests/ScrambleForTesting.cs b/OpenSim/Data/Tests/ScrambleForTesting.cs new file mode 100644 index 0000000000..c6e467f60e --- /dev/null +++ b/OpenSim/Data/Tests/ScrambleForTesting.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Text; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.Tests +{ + public static class ScrambleForTesting + { + private static readonly Random random = new Random(); + public static void Scramble(object obj) + { + PropertyInfo[] properties = obj.GetType().GetProperties(); + foreach (var property in properties) + { + //Skip indexers of classes. We will assume that everything that has an indexer + // is also IEnumberable. May not always be true, but should be true normally. + if(property.GetIndexParameters().Length > 0) + continue; + + RandomizeProperty(obj, property, null); + } + //Now if it implments IEnumberable, it's probably some kind of list, so we should randomize + // everything inside of it. + IEnumerable enumerable = obj as IEnumerable; + if(enumerable != null) + { + foreach (object value in enumerable) + { + Scramble(value); + } + } + } + + private static void RandomizeProperty(object obj, PropertyInfo property, object[] index) + { + Type t = property.PropertyType; + if (!property.CanWrite) + return; + object value = property.GetValue(obj, index); + if (value == null) + return; + + if (t == typeof (string)) + property.SetValue(obj, RandomName(), index); + else if (t == typeof (UUID)) + property.SetValue(obj, UUID.Random(), index); + else if (t == typeof (sbyte)) + property.SetValue(obj, (sbyte)random.Next(sbyte.MinValue, sbyte.MaxValue), index); + else if (t == typeof (short)) + property.SetValue(obj, (short)random.Next(short.MinValue, short.MaxValue), index); + else if (t == typeof (int)) + property.SetValue(obj, random.Next(), index); + else if (t == typeof (long)) + property.SetValue(obj, random.Next() * int.MaxValue, index); + else if (t == typeof (byte)) + property.SetValue(obj, (byte)random.Next(byte.MinValue, byte.MaxValue), index); + else if (t == typeof (ushort)) + property.SetValue(obj, (ushort)random.Next(ushort.MinValue, ushort.MaxValue), index); + else if (t == typeof (uint)) + property.SetValue(obj, Convert.ToUInt32(random.Next()), index); + else if (t == typeof (ulong)) + property.SetValue(obj, Convert.ToUInt64(random.Next()) * Convert.ToUInt64(UInt32.MaxValue), index); + else if (t == typeof (bool)) + property.SetValue(obj, true, index); + else if (t == typeof (byte[])) + { + byte[] bytes = new byte[30]; + random.NextBytes(bytes); + property.SetValue(obj, bytes, index); + } + else + Scramble(value); + } + + private static string RandomName() + { + StringBuilder name = new StringBuilder(); + int size = random.Next(5, 12); + for (int i = 0; i < size; i++) + { + char ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))); + name.Append(ch); + } + return name.ToString(); + } + } + + [TestFixture] + public class ScrableForTestingTest + { + [Test] + public void TestScramble() + { + AssetBase actual = new AssetBase(UUID.Random(), "asset one"); + ScrambleForTesting.Scramble(actual); + } + } +} \ No newline at end of file From 31820b002618b773b38ce1c1a073383cec89277b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 14 Aug 2009 18:36:09 +0100 Subject: [PATCH 4/6] minor formatting adjustments --- OpenSim/Data/Tests/BasicUserTest.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/OpenSim/Data/Tests/BasicUserTest.cs b/OpenSim/Data/Tests/BasicUserTest.cs index d3e6f41c27..4e4ddc8572 100644 --- a/OpenSim/Data/Tests/BasicUserTest.cs +++ b/OpenSim/Data/Tests/BasicUserTest.cs @@ -204,8 +204,16 @@ namespace OpenSim.Data.Tests UUID webloginkey = UUID.Random(); uint homeregx = (uint) random.Next(); uint homeregy = (uint) random.Next(); - Vector3 homeloc = new Vector3((float)Math.Round(random.NextDouble(),5),(float)Math.Round(random.NextDouble(),5),(float)Math.Round(random.NextDouble(),5)); - Vector3 homelookat = new Vector3((float)Math.Round(random.NextDouble(),5),(float)Math.Round(random.NextDouble(),5),(float)Math.Round(random.NextDouble(),5)); + Vector3 homeloc + = new Vector3( + (float)Math.Round(random.NextDouble(), 5), + (float)Math.Round(random.NextDouble(), 5), + (float)Math.Round(random.NextDouble(), 5)); + Vector3 homelookat + = new Vector3( + (float)Math.Round(random.NextDouble(), 5), + (float)Math.Round(random.NextDouble(), 5), + (float)Math.Round(random.NextDouble(), 5)); int created = random.Next(); int lastlogin = random.Next(); string userinvuri = RandomName(); From b02f12da78472606034e9edb43bc872286b1347e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 14 Aug 2009 18:57:18 +0100 Subject: [PATCH 5/6] Return minimum mono version in README to 2.0.1 for now (recommended is still 2.4.2) --- README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.txt b/README.txt index e796bb2810..5c34201aea 100644 --- a/README.txt +++ b/README.txt @@ -25,7 +25,7 @@ See configuring OpenSim == Installation on Linux == Prereqs: - * Mono >= 2.4 (>= 2.4.2 is better) + * Mono >= 2.0.1 (>= 2.4.2 is better) * Nant >= 0.86beta * sqlite3 or mysql 5.x (you'll need a back end database) From 957962b48276861948267701159775c2361b235b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 14 Aug 2009 19:06:24 +0100 Subject: [PATCH 6/6] Remove NRE catching on TestReplicateArchivePathToUserInventory() since race failure now appears to have gone --- .../Archiver/Tests/InventoryArchiverTests.cs | 34 +++++-------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 28b4d6496e..2169e36d30 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -395,17 +395,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests userInfo = UserProfileTestUtils.CreateUserWithInventory(commsManager, InventoryReceived); Monitor.Wait(this, 60000); } - - //userInfo.FetchInventory(); - /* - for (int i = 0 ; i < 50 ; i++) - { - if (userInfo.HasReceivedInventory == true) - break; - Thread.Sleep(200); - } - Assert.That(userInfo.HasReceivedInventory, Is.True, "FetchInventory timed out (10 seconds)"); - */ Console.WriteLine("userInfo.RootFolder 1: {0}", userInfo.RootFolder); @@ -429,22 +418,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Console.WriteLine("userInfo.RootFolder 2: {0}", userInfo.RootFolder); - try - { - new InventoryArchiveReadRequest(userInfo, null, (Stream)null, null, null) - .ReplicateArchivePathToUserInventory(itemArchivePath, false, userInfo.RootFolder, foldersCreated, nodesLoaded); + new InventoryArchiveReadRequest(userInfo, null, (Stream)null, null, null) + .ReplicateArchivePathToUserInventory( + itemArchivePath, false, userInfo.RootFolder, foldersCreated, nodesLoaded); - Console.WriteLine("userInfo.RootFolder 3: {0}", userInfo.RootFolder); - InventoryFolderImpl folder1 = userInfo.RootFolder.FindFolderByPath("a"); - Assert.That(folder1, Is.Not.Null, "Could not find folder a"); - InventoryFolderImpl folder2 = folder1.FindFolderByPath("b"); - Assert.That(folder2, Is.Not.Null, "Could not find folder b"); - } - catch (NullReferenceException e) - { - // Non fatal for now until we resolve the race condition - Console.WriteLine("Test failed with {0}", e); - } + Console.WriteLine("userInfo.RootFolder 3: {0}", userInfo.RootFolder); + InventoryFolderImpl folder1 = userInfo.RootFolder.FindFolderByPath("a"); + Assert.That(folder1, Is.Not.Null, "Could not find folder a"); + InventoryFolderImpl folder2 = folder1.FindFolderByPath("b"); + Assert.That(folder2, Is.Not.Null, "Could not find folder b"); } } }