/* * 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 OpenSimulator 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 System.IO; using System.Reflection; using System.Threading; using NUnit.Framework; using OpenMetaverse; using OpenSim.Data; using OpenSim.Framework; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; using OpenSim.Framework.Communications; using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { [TestFixture] public class InventoryArchiveSaveTests : InventoryArchiveTestCase { protected TestScene m_scene; protected InventoryArchiverModule m_archiverModule; [SetUp] public override void SetUp() { base.SetUp(); SerialiserModule serialiserModule = new SerialiserModule(); m_archiverModule = new InventoryArchiverModule(); m_scene = new SceneHelpers().SetupScene(); SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); } /// /// Test that the IAR has the required files in the right order. /// /// /// At the moment, the only thing that matters is that the control file is the very first one. /// [Test] public void TestOrder() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); MemoryStream archiveReadStream = new MemoryStream(m_iarStreamBytes); TarArchiveReader tar = new TarArchiveReader(archiveReadStream); string filePath; TarArchiveReader.TarEntryType tarEntryType; byte[] data = tar.ReadEntry(out filePath, out tarEntryType); Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); InventoryArchiveReadRequest iarr = new InventoryArchiveReadRequest(null, null, null, null, null, (Stream)null, false); iarr.LoadControlFile(filePath, data); Assert.That(iarr.ControlFileLoaded, Is.True); } [Test] public void TestSaveRootFolderToIar() { TestHelpers.InMethod(); // TestHelpers.EnableLogging(); string userFirstName = "Jock"; string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = TestHelpers.ParseTail(0x20); UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); MemoryStream archiveWriteStream = new MemoryStream(); m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; mre.Reset(); m_archiverModule.ArchiveInventory( Guid.NewGuid(), userFirstName, userLastName, "/", archiveWriteStream); mre.WaitOne(60000, false); // Test created iar byte[] archive = archiveWriteStream.ToArray(); MemoryStream archiveReadStream = new MemoryStream(archive); TarArchiveReader tar = new TarArchiveReader(archiveReadStream); // InventoryArchiveUtils. bool gotObjectsFolder = false; string objectsFolderName = string.Format( "{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName( UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, userId, "Objects"))); string filePath; TarArchiveReader.TarEntryType tarEntryType; while (tar.ReadEntry(out filePath, out tarEntryType) != null) { // Console.WriteLine("Got {0}", filePath); // Lazily, we only bother to look for the system objects folder created when we call CreateUserWithInventory() // XXX: But really we need to stop all that stuff being created in tests or check for such folders // more thoroughly if (filePath == objectsFolderName) gotObjectsFolder = true; } Assert.That(gotObjectsFolder, Is.True); } [Test] public void TestSaveNonRootFolderToIar() { TestHelpers.InMethod(); // TestHelpers.EnableLogging(); string userFirstName = "Jock"; string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = TestHelpers.ParseTail(0x20); UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); // Create base folder InventoryFolderBase f1 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1", true); // Create item1 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Dog Object", 0x5); InventoryItemBase i1 = UserInventoryHelpers.AddInventoryItem(m_scene, so1, 0x50, 0x60, "f1"); // Create embedded folder InventoryFolderBase f1_1 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1/f1.1", true); // Create embedded item SceneObjectGroup so1_1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Cat Object", 0x6); InventoryItemBase i2 = UserInventoryHelpers.AddInventoryItem(m_scene, so1_1, 0x500, 0x600, "f1/f1.1"); MemoryStream archiveWriteStream = new MemoryStream(); m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; mre.Reset(); m_archiverModule.ArchiveInventory( Guid.NewGuid(), userFirstName, userLastName, "f1", archiveWriteStream); mre.WaitOne(60000, false); // Test created iar byte[] archive = archiveWriteStream.ToArray(); MemoryStream archiveReadStream = new MemoryStream(archive); TarArchiveReader tar = new TarArchiveReader(archiveReadStream); // InventoryArchiveUtils. bool gotf1 = false, gotf1_1 = false, gotso1 = false, gotso2 = false; string f1FileName = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1)); string f1_1FileName = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1_1)); string so1FileName = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i1)); string so2FileName = string.Format("{0}{1}", f1_1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i2)); string filePath; TarArchiveReader.TarEntryType tarEntryType; while (tar.ReadEntry(out filePath, out tarEntryType) != null) { // Console.WriteLine("Got {0}", filePath); if (filePath == f1FileName) gotf1 = true; else if (filePath == f1_1FileName) gotf1_1 = true; else if (filePath == so1FileName) gotso1 = true; else if (filePath == so2FileName) gotso2 = true; } // Assert.That(gotControlFile, Is.True, "No control file in archive"); Assert.That(gotf1, Is.True); Assert.That(gotf1_1, Is.True); Assert.That(gotso1, Is.True); Assert.That(gotso2, Is.True); // TODO: Test presence of more files and contents of files. } /// /// Test saving a single inventory item to an IAR /// (subject to change since there is no fixed format yet). /// [Test] public void TestSaveItemToIar() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); // Create user string userFirstName = "Jock"; string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); // Create asset UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); m_scene.AssetService.Store(asset1); // Create item UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); string item1Name = "My Little Dog"; InventoryItemBase item1 = new InventoryItemBase(); item1.Name = item1Name; item1.AssetID = asset1.FullID; item1.ID = item1Id; InventoryFolderBase objsFolder = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0]; item1.Folder = objsFolder.ID; m_scene.AddInventoryItem(item1); MemoryStream archiveWriteStream = new MemoryStream(); m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; mre.Reset(); m_archiverModule.ArchiveInventory( Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, archiveWriteStream); mre.WaitOne(60000, false); byte[] archive = archiveWriteStream.ToArray(); MemoryStream archiveReadStream = new MemoryStream(archive); TarArchiveReader tar = new TarArchiveReader(archiveReadStream); //bool gotControlFile = false; bool gotObject1File = false; //bool gotObject2File = false; string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); string expectedObject1FilePath = string.Format( "{0}{1}", ArchiveConstants.INVENTORY_PATH, expectedObject1FileName); string filePath; TarArchiveReader.TarEntryType tarEntryType; // Console.WriteLine("Reading archive"); while (tar.ReadEntry(out filePath, out tarEntryType) != null) { Console.WriteLine("Got {0}", filePath); // if (ArchiveConstants.CONTROL_FILE_PATH == filePath) // { // gotControlFile = true; // } if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) { // string fileName = filePath.Remove(0, "Objects/".Length); // // if (fileName.StartsWith(part1.Name)) // { Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); gotObject1File = true; // } // else if (fileName.StartsWith(part2.Name)) // { // Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); // gotObject2File = true; // } } } // Assert.That(gotControlFile, Is.True, "No control file in archive"); Assert.That(gotObject1File, Is.True, "No item1 file in archive"); // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); // TODO: Test presence of more files and contents of files. } /// /// Test saving a single inventory item to an IAR without its asset /// [Test] public void TestSaveItemToIarNoAssets() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); // Create user string userFirstName = "Jock"; string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); // Create asset UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); m_scene.AssetService.Store(asset1); // Create item UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); string item1Name = "My Little Dog"; InventoryItemBase item1 = new InventoryItemBase(); item1.Name = item1Name; item1.AssetID = asset1.FullID; item1.ID = item1Id; InventoryFolderBase objsFolder = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0]; item1.Folder = objsFolder.ID; m_scene.AddInventoryItem(item1); MemoryStream archiveWriteStream = new MemoryStream(); Dictionary options = new Dictionary(); options.Add("noassets", true); // When we're not saving assets, archiving is being done synchronously. m_archiverModule.ArchiveInventory( Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, archiveWriteStream, options); byte[] archive = archiveWriteStream.ToArray(); MemoryStream archiveReadStream = new MemoryStream(archive); TarArchiveReader tar = new TarArchiveReader(archiveReadStream); //bool gotControlFile = false; bool gotObject1File = false; //bool gotObject2File = false; string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); string expectedObject1FilePath = string.Format( "{0}{1}", ArchiveConstants.INVENTORY_PATH, expectedObject1FileName); string filePath; TarArchiveReader.TarEntryType tarEntryType; // Console.WriteLine("Reading archive"); while (tar.ReadEntry(out filePath, out tarEntryType) != null) { Console.WriteLine("Got {0}", filePath); // if (ArchiveConstants.CONTROL_FILE_PATH == filePath) // { // gotControlFile = true; // } if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) { // string fileName = filePath.Remove(0, "Objects/".Length); // // if (fileName.StartsWith(part1.Name)) // { Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); gotObject1File = true; // } // else if (fileName.StartsWith(part2.Name)) // { // Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); // gotObject2File = true; // } } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { Assert.Fail("Found asset path in TestSaveItemToIarNoAssets()"); } } // Assert.That(gotControlFile, Is.True, "No control file in archive"); Assert.That(gotObject1File, Is.True, "No item1 file in archive"); // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); // TODO: Test presence of more files and contents of files. } } }