diff --git a/OpenSim/Framework/Servers/BaseGetAssetStreamHandler.cs b/OpenSim/Framework/Servers/BaseGetAssetStreamHandler.cs index fc4eed7d2e..9eacf2469a 100644 --- a/OpenSim/Framework/Servers/BaseGetAssetStreamHandler.cs +++ b/OpenSim/Framework/Servers/BaseGetAssetStreamHandler.cs @@ -60,7 +60,7 @@ namespace OpenSim.Framework.Servers if (p.Length > 0) { - UUID assetID = UUID.Zero; + UUID assetID; if (!UUID.TryParse(p[0], out assetID)) { @@ -70,16 +70,14 @@ namespace OpenSim.Framework.Servers } if (StatsManager.AssetStats != null) + { StatsManager.AssetStats.AddRequest(); + } AssetBase asset = GetAsset(assetID); if (asset != null) { -// if (asset.ContainsReferences) -// { -// asset.Data = ProcessOutgoingAssetData(asset.Data); -// } if (p.Length > 1 && p[1] == "data") { httpResponse.StatusCode = (int)HttpStatusCode.OK; @@ -88,25 +86,15 @@ namespace OpenSim.Framework.Servers } else { - XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); - MemoryStream ms = new MemoryStream(); - XmlTextWriter xw = new XmlTextWriter(ms, Encoding.UTF8); - xw.Formatting = Formatting.Indented; - xs.Serialize(xw, asset); - xw.Flush(); - - ms.Seek(0, SeekOrigin.Begin); - //StreamReader sr = new StreamReader(ms); - - result = ms.GetBuffer(); - - Array.Resize(ref result, (int)ms.Length); + result = GetXml(asset); } } else { if (StatsManager.AssetStats != null) + { StatsManager.AssetStats.AddNotFoundRequest(); + } m_log.InfoFormat("[REST]: GET:/asset failed to find {0}", assetID); } @@ -115,6 +103,25 @@ namespace OpenSim.Framework.Servers return result; } + public static byte[] GetXml(AssetBase asset) + { + byte[] result; + XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, Encoding.UTF8); + xw.Formatting = Formatting.Indented; + xs.Serialize(xw, asset); + xw.Flush(); + + ms.Seek(0, SeekOrigin.Begin); + //StreamReader sr = new StreamReader(ms); + + result = ms.GetBuffer(); + + Array.Resize(ref result, (int)ms.Length); + return result; + } + public string ProcessAssetDataString(string data) { Regex regex = new Regex("(creator_id|owner_id)\\s+(\\S+)"); diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs index 210d122797..6ea95b1172 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs @@ -45,7 +45,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// Setting this property will also set IsContentTypeSet to /// true. /// - public string ContentType + public virtual string ContentType { get { @@ -226,7 +226,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// /// HTTP status code. /// - public int StatusCode + public virtual int StatusCode { get { diff --git a/OpenSim/Framework/Servers/Tests/CachedGetAssetStreamHandlerTests.cs b/OpenSim/Framework/Servers/Tests/CachedGetAssetStreamHandlerTests.cs index dbb877d1d3..b3cccfde7a 100644 --- a/OpenSim/Framework/Servers/Tests/CachedGetAssetStreamHandlerTests.cs +++ b/OpenSim/Framework/Servers/Tests/CachedGetAssetStreamHandlerTests.cs @@ -4,7 +4,10 @@ using System.Text; using NUnit.Framework; using OpenSim.Data; using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; namespace OpenSim.Framework.Servers.Tests { @@ -59,14 +62,34 @@ namespace OpenSim.Framework.Servers.Tests BaseRequestHandlerTestHelper.BaseTestHandleMalformedGuid(handler, ASSETS_PATH); } - //[Test] - //public void TestHandleFetchMissingAsset() - //{ + [Test] + public void TestHandleFetchMissingAsset() + { + IAssetCache assetCache = new TestAssetCache(); + CachedGetAssetStreamHandler handler = new CachedGetAssetStreamHandler(assetCache); - // byte[] emptyResult = new byte[] { }; - // CachedGetAssetStreamHandler handler = new CachedGetAssetStreamHandler(null); + GetAssetStreamHandlerTestHelpers.BaseFetchMissingAsset(handler); + } - // Assert.AreEqual(new string[] { }, handler.Handle("/assets/badGuid", null, null, null), "Failed on bad guid."); - //} + [Test] + public void TestHandleFetchExistingAssetData() + { + CachedGetAssetStreamHandler handler; + OSHttpResponse response; + AssetBase asset = CreateTestEnvironment(out handler, out response); + + GetAssetStreamHandlerTestHelpers.BaseFetchExistingAssetDataTest(asset, handler, response); + } + + private static AssetBase CreateTestEnvironment(out CachedGetAssetStreamHandler handler, out OSHttpResponse response) + { + AssetBase asset = GetAssetStreamHandlerTestHelpers.CreateCommonTestResources(out response); + + IAssetCache assetDataPlugin = new TestAssetCache(); + handler = new CachedGetAssetStreamHandler(assetDataPlugin); + + assetDataPlugin.AddAsset(asset); + return asset; + } } } diff --git a/OpenSim/Framework/Servers/Tests/GetAssetStreamHandlerTests.cs b/OpenSim/Framework/Servers/Tests/GetAssetStreamHandlerTests.cs index 091a94464d..51dd79dd3a 100644 --- a/OpenSim/Framework/Servers/Tests/GetAssetStreamHandlerTests.cs +++ b/OpenSim/Framework/Servers/Tests/GetAssetStreamHandlerTests.cs @@ -1,10 +1,14 @@ using System; using System.Collections.Generic; +using System.Net; using System.Text; +using HttpServer; using NUnit.Framework; using OpenSim.Data; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; namespace OpenSim.Framework.Servers.Tests { @@ -59,13 +63,44 @@ namespace OpenSim.Framework.Servers.Tests BaseRequestHandlerTestHelper.BaseTestHandleMalformedGuid(handler, ASSETS_PATH); } - //[Test] - //public void TestHandleFetchMissingAsset() - //{ - // byte[] emptyResult = new byte[] { }; - // GetAssetStreamHandler handler = new GetAssetStreamHandler(null); + [Test] + public void TestHandleFetchMissingAsset() + { + IAssetDataPlugin assetDataPlugin = new TestAssetDataPlugin(); + GetAssetStreamHandler handler = new GetAssetStreamHandler(assetDataPlugin); - // Assert.AreEqual(new string[] { }, handler.Handle("/assets/badGuid", null, null, null), "Failed on bad guid."); - //} + GetAssetStreamHandlerTestHelpers.BaseFetchMissingAsset(handler); + } + + [Test] + public void TestHandleFetchExistingAssetData() + { + GetAssetStreamHandler handler; + OSHttpResponse response; + AssetBase asset = CreateTestEnvironment(out handler, out response); + + GetAssetStreamHandlerTestHelpers.BaseFetchExistingAssetDataTest(asset, handler, response); + } + + [Test] + public void TestHandleFetchExistingAssetXml() + { + GetAssetStreamHandler handler; + OSHttpResponse response; + AssetBase asset = CreateTestEnvironment(out handler, out response); + + GetAssetStreamHandlerTestHelpers.BaseFetchExistingAssetXmlTest(asset, handler, response); + } + + private static AssetBase CreateTestEnvironment(out GetAssetStreamHandler handler, out OSHttpResponse response) + { + AssetBase asset = GetAssetStreamHandlerTestHelpers.CreateCommonTestResources(out response); + + IAssetDataPlugin assetDataPlugin = new TestAssetDataPlugin(); + handler = new GetAssetStreamHandler(assetDataPlugin); + + assetDataPlugin.CreateAsset(asset); + return asset; + } } } diff --git a/OpenSim/Tests/Common/BaseRequestHandlerTestHelper.cs b/OpenSim/Tests/Common/BaseRequestHandlerTestHelper.cs index 8f96fb3963..6c506443c6 100644 --- a/OpenSim/Tests/Common/BaseRequestHandlerTestHelper.cs +++ b/OpenSim/Tests/Common/BaseRequestHandlerTestHelper.cs @@ -1,9 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.Text; using NUnit.Framework; +using OpenSim.Framework; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Tests.Common.Mock; namespace OpenSim.Tests.Common { diff --git a/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs b/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs new file mode 100644 index 0000000000..acfe4fe25d --- /dev/null +++ b/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Tests.Common.Mock +{ + public class BaseAssetRepository + { + protected Dictionary Assets = new Dictionary(); + + public AssetBase FetchAsset(UUID uuid) + { + if (ExistsAsset(uuid)) + return Assets[uuid]; + else + return null; + } + + public void CreateAsset(AssetBase asset) + { + Assets[asset.FullID] = asset; + } + + public void UpdateAsset(AssetBase asset) + { + CreateAsset(asset); + } + + public bool ExistsAsset(UUID uuid) + { + return Assets.ContainsKey(uuid); + } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestAssetCache.cs b/OpenSim/Tests/Common/Mock/TestAssetCache.cs new file mode 100644 index 0000000000..d6217635e1 --- /dev/null +++ b/OpenSim/Tests/Common/Mock/TestAssetCache.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; +using OpenMetaverse.Packets; +using OpenSim.Framework; + +namespace OpenSim.Tests.Common.Mock +{ + public class TestAssetCache : BaseAssetRepository, IAssetCache + { + public void AssetReceived(AssetBase asset, bool IsTexture) + { + throw new NotImplementedException(); + } + + public void AssetNotFound(UUID assetID, bool IsTexture) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public string Version + { + get { throw new NotImplementedException(); } + } + + public string Name + { + get { throw new NotImplementedException(); } + } + + public void Initialise() + { + throw new NotImplementedException(); + } + + public IAssetServer AssetServer + { + get { throw new NotImplementedException(); } + } + + public void Initialise(ConfigSettings cs, IAssetServer server) + { + throw new NotImplementedException(); + } + + public void ShowState() + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool TryGetCachedAsset(UUID assetID, out AssetBase asset) + { + throw new NotImplementedException(); + } + + public void GetAsset(UUID assetID, AssetRequestCallback callback, bool isTexture) + { + throw new NotImplementedException(); + } + + public AssetBase GetAsset(UUID assetID, bool isTexture) + { + return FetchAsset(assetID); + } + + public void AddAsset(AssetBase asset) + { + CreateAsset( asset ); + } + + public void ExpireAsset(UUID assetID) + { + throw new NotImplementedException(); + } + + public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) + { + throw new NotImplementedException(); + } + } +} diff --git a/OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs index 80b9ae3651..b639cc9015 100644 --- a/OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/TestAssetDataPlugin.cs @@ -37,40 +37,15 @@ namespace OpenSim.Tests.Common.Mock /// mono addin plugin system starts co-operating with the unit test system. Currently no locking since unit /// tests are single threaded. /// - public class TestAssetDataPlugin : IAssetDataPlugin + public class TestAssetDataPlugin : BaseAssetRepository, IAssetDataPlugin { public string Version { get { return "0"; } } public string Name { get { return "TestAssetDataPlugin"; } } - - protected Dictionary Assets = new Dictionary(); public void Initialise() {} public void Initialise(string connect) {} public void Dispose() {} - public AssetBase FetchAsset(UUID uuid) - { - if (ExistsAsset(uuid)) - return Assets[uuid]; - else - return null; - } - - public void CreateAsset(AssetBase asset) - { - Assets[asset.FullID] = asset; - } - - public void UpdateAsset(AssetBase asset) - { - CreateAsset(asset); - } - - public bool ExistsAsset(UUID uuid) - { - return Assets.ContainsKey(uuid); - } - public List FetchAssetMetadataSet(int start, int count) { return new List(count); } } } \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestAssetService.cs b/OpenSim/Tests/Common/Mock/TestAssetService.cs new file mode 100644 index 0000000000..23a1137362 --- /dev/null +++ b/OpenSim/Tests/Common/Mock/TestAssetService.cs @@ -0,0 +1,78 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Data; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Tests.Common.Mock +{ + public class TestAssetService : IAssetService + { + private readonly Dictionary Assets = new Dictionary(); + + public AssetBase Get(string id) + { + return Assets[ id ]; + } + + public AssetMetadata GetMetadata(string id) + { + throw new System.NotImplementedException(); + } + + public byte[] GetData(string id) + { + throw new System.NotImplementedException(); + } + + public bool Get(string id, object sender, AssetRetrieved handler) + { + throw new NotImplementedException(); + } + + public string Store(AssetBase asset) + { + Assets[asset.ID] = asset; + + return asset.ID; + } + + public bool UpdateContent(string id, byte[] data) + { + throw new System.NotImplementedException(); + } + + public bool Delete(string id) + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestOSHttpResponse.cs b/OpenSim/Tests/Common/Mock/TestOSHttpResponse.cs new file mode 100644 index 0000000000..d9c96f440f --- /dev/null +++ b/OpenSim/Tests/Common/Mock/TestOSHttpResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; +using OpenSim.Framework.Servers.HttpServer; + +namespace OpenSim.Tests.Common.Mock +{ + public class TestOSHttpResponse : OSHttpResponse + { + public override int StatusCode { get; set; } + public override string ContentType { get; set; } + } +} diff --git a/OpenSim/Tests/Common/Setup/GetAssetStreamHandlerTestHelpers.cs b/OpenSim/Tests/Common/Setup/GetAssetStreamHandlerTestHelpers.cs new file mode 100644 index 0000000000..593beae061 --- /dev/null +++ b/OpenSim/Tests/Common/Setup/GetAssetStreamHandlerTestHelpers.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Xml; +using System.Xml.Serialization; +using NUnit.Framework; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Tests.Common.Setup +{ + public class GetAssetStreamHandlerTestHelpers + { + public static void BaseFetchExistingAssetXmlTest(AssetBase asset, BaseGetAssetStreamHandler handler, OSHttpResponse response) + { + byte[] expected = BaseGetAssetStreamHandler.GetXml(asset); + + byte[] actual = handler.Handle("/assets/" + asset.ID , null, null, response); + + Assert.Greater(actual.Length, 10, "Too short xml on fetching xml without trailing slash."); + Assert.AreEqual(expected, actual, "Failed on fetching xml without trailing slash."); + // Assert.AreEqual((int)HttpStatusCode.OK, response.StatusCode, "Wrong http response code on first fetch."); + + byte[] actual1 = handler.Handle("/assets/" + asset.ID + "/", null, null, response); + Assert.Greater(actual1.Length, 10, "Too short xml on fetching xml with trailing slash."); + Assert.AreEqual(expected, actual1, "Failed on fetching xml with trailing slash."); + // Assert.AreEqual((int)HttpStatusCode.OK, response.StatusCode, "Wrong http response code on second fetch."); + } + + public static void BaseFetchExistingAssetDataTest(AssetBase asset, BaseGetAssetStreamHandler handler, OSHttpResponse response) + { + Assert.AreEqual(asset.Data, handler.Handle("/assets/" + asset.ID + "/data", null, null, response), "Failed on fetching data without trailing slash."); + Assert.AreEqual((int)HttpStatusCode.OK, response.StatusCode, "Wrong http response code on first fetch."); + + Assert.AreEqual(asset.Data, handler.Handle("/assets/" + asset.ID + "/data/", null, null, response), "Failed on fetching data with trailing slash."); + Assert.AreEqual((int)HttpStatusCode.OK, response.StatusCode, "Wrong http response code on second fetch."); + } + + public static AssetBase CreateCommonTestResources(out OSHttpResponse response) + { + AssetBase asset = CreateTestAsset(); + response = new TestOSHttpResponse(); + return asset; + } + + public static AssetBase CreateTestAsset() + { + byte[] expected = new byte[] { 1,2,3 }; + AssetBase asset = new AssetBase( ); + asset.ID = Guid.NewGuid().ToString(); + asset.Data = expected; + return asset; + } + + public static void BaseFetchMissingAsset(BaseGetAssetStreamHandler handler) + { + Assert.AreEqual(BaseRequestHandlerTestHelper.EmptyByteArray, handler.Handle("/assets/" + Guid.NewGuid(), null, null, null), "Failed on bad guid."); + } + } +} diff --git a/prebuild.xml b/prebuild.xml index 081e166d68..87e8643bd3 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -3133,6 +3133,7 @@ + @@ -3330,6 +3331,7 @@ ../../../../bin/ +