From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Thu, 3 Nov 2016 21:44:39 +1000 Subject: Initial update to OpenSim 0.8.2.1 source code. --- .../Archiver/InventoryArchiveReadRequest.cs | 155 +++---- .../Inventory/Archiver/InventoryArchiveUtils.cs | 86 +++- .../Archiver/InventoryArchiveWriteRequest.cs | 120 +++++- .../Inventory/Archiver/InventoryArchiverModule.cs | 106 +++-- .../Tests/InventoryArchiveLoadPathTests.cs | 360 ++++++++++++++++ .../Archiver/Tests/InventoryArchiveLoadTests.cs | 192 +++++++++ .../Archiver/Tests/InventoryArchiveSaveTests.cs | 422 ++++++++++++++++++ .../Archiver/Tests/InventoryArchiveTestCase.cs | 8 +- .../Archiver/Tests/InventoryArchiverTests.cs | 417 ------------------ .../Avatar/Inventory/Archiver/Tests/PathTests.cs | 477 --------------------- .../Inventory/Transfer/InventoryTransferModule.cs | 166 +++---- .../Transfer/Tests/InventoryTransferModuleTests.cs | 448 +++++++++++++++++++ 12 files changed, 1830 insertions(+), 1127 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs (limited to 'OpenSim/Region/CoreModules/Avatar/Inventory') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index ecbd07f..4a06fd1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -61,16 +61,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver private UserAccount m_userInfo; private string m_invPath; + + /// + /// ID of this request + /// + protected UUID m_id; /// /// Do we want to merge this load with existing inventory? /// protected bool m_merge; - /// - /// We only use this to request modules - /// - protected Scene m_scene; + protected IInventoryService m_InventoryService; + protected IAssetService m_AssetService; + protected IUserAccountService m_UserAccountService; + + private InventoryArchiverModule m_module; /// /// The stream from which the inventory archive will be loaded. @@ -115,12 +121,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids /// after OSP resolution (since OSP creators are only stored in the item /// - protected Dictionary m_creatorIdForAssetId = new Dictionary(); + protected Dictionary m_creatorIdForAssetId = new Dictionary(); + + public InventoryArchiveReadRequest( + IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge) + : this(UUID.Zero, null, + inv, + assets, + uacc, + userInfo, + invPath, + loadPath, + merge) + { + } public InventoryArchiveReadRequest( - Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) + UUID id, InventoryArchiverModule module, IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge) : this( - scene, + id, + module, + inv, + assets, + uacc, userInfo, invPath, new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress), @@ -129,13 +152,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } public InventoryArchiveReadRequest( - Scene scene, UserAccount userInfo, string invPath, Stream loadStream, bool merge) + UUID id, InventoryArchiverModule module, IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, Stream loadStream, bool merge) { - m_scene = scene; + m_id = id; + m_InventoryService = inv; + m_AssetService = assets; + m_UserAccountService = uacc; m_merge = merge; m_userInfo = userInfo; m_invPath = invPath; m_loadStream = loadStream; + m_module = module; // FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things // (I thought they weren't). We will need to bump the version number and perform this check on all @@ -158,11 +185,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { try { + Exception reportedException = null; + string filePath = "ERROR"; List folderCandidates - = InventoryArchiveUtils.FindFolderByPath( - m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); + = InventoryArchiveUtils.FindFoldersByPath( + m_InventoryService, m_userInfo.PrincipalID, m_invPath); if (folderCandidates.Count == 0) { @@ -194,14 +223,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } archive.Close(); - + m_log.DebugFormat( "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", m_successfulAssetRestores, m_failedAssetRestores); - m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", m_successfulItemRestores); + + //Alicia: When this is called by LibraryModule or Tests, m_module will be null as event is not required + if(m_module != null) + m_module.TriggerInventoryArchiveLoaded(m_id, true, m_userInfo, m_invPath, m_loadStream, reportedException, m_successfulItemRestores); return m_loadedNodes; } + catch(Exception Ex) + { + // Trigger saved event with failed result and exception data + if (m_module != null) + m_module.TriggerInventoryArchiveLoaded(m_id, false, m_userInfo, m_invPath, m_loadStream, Ex, 0); + + return m_loadedNodes; + } finally { m_loadStream.Close(); @@ -296,8 +336,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // iar name and try to find that instead. string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); List folderCandidates - = InventoryArchiveUtils.FindFolderByPath( - m_scene.InventoryService, m_userInfo.PrincipalID, plainPath); + = InventoryArchiveUtils.FindFoldersByPath( + m_InventoryService, m_userInfo.PrincipalID, plainPath); if (folderCandidates.Count != 0) { @@ -372,15 +412,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName); UUID newFolderId = UUID.Random(); - // Asset type has to be Unknown here rather than Folder, otherwise the created folder can't be - // deleted once the client has relogged. - // The root folder appears to be labelled AssetType.Folder (shows up as "Category" in the client) - // even though there is a AssetType.RootCategory destFolder = new InventoryFolderBase( - newFolderId, newFolderName, m_userInfo.PrincipalID, - (short)AssetType.Unknown, destFolder.ID, 1); - m_scene.InventoryService.AddFolder(destFolder); + newFolderId, newFolderName, m_userInfo.PrincipalID, + (short)FolderType.None, destFolder.ID, 1); + m_InventoryService.AddFolder(destFolder); // Record that we have now created this folder iarPathExisting += rawDirsToCreate[i] + "/"; @@ -406,7 +442,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Don't use the item ID that's in the file item.ID = UUID.Random(); - UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService); + UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService); if (UUID.Zero != ospResolvedId) // The user exists in this grid { // m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId); @@ -418,7 +454,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver item.CreatorId = ospResolvedId.ToString(); item.CreatorData = string.Empty; } - else if (item.CreatorData == null || item.CreatorData == String.Empty) + else if (string.IsNullOrEmpty(item.CreatorData)) { item.CreatorId = m_userInfo.PrincipalID.ToString(); // item.CreatorIdAsUuid = new UUID(item.CreatorId); @@ -436,7 +472,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // relying on native tar tools. m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid; - m_scene.AddInventoryItem(item); + if (!m_InventoryService.AddItem(item)) + m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder); return item; } @@ -479,52 +516,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { if (m_creatorIdForAssetId.ContainsKey(assetId)) { - string xmlData = Utils.BytesToString(data); - List sceneObjects = new List(); + data = SceneObjectSerializer.ModifySerializedObject(assetId, data, + sog => { + bool modified = false; + + foreach (SceneObjectPart sop in sog.Parts) + { + if (string.IsNullOrEmpty(sop.CreatorData)) + { + sop.CreatorID = m_creatorIdForAssetId[assetId]; + modified = true; + } + } + + return modified; + }); - CoalescedSceneObjects coa = null; - if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) - { -// m_log.DebugFormat( -// "[INVENTORY ARCHIVER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); - - if (coa.Objects.Count == 0) - { - m_log.WarnFormat( - "[INVENTORY ARCHIVE READ REQUEST]: Aborting load of coalesced object from asset {0} as it has zero loaded components", - assetId); - return false; - } - - sceneObjects.AddRange(coa.Objects); - } - else - { - SceneObjectGroup deserializedObject = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - - if (deserializedObject != null) - { - sceneObjects.Add(deserializedObject); - } - else - { - m_log.WarnFormat( - "[INVENTORY ARCHIVE READ REQUEST]: Aborting load of object from asset {0} as deserialization failed", - assetId); - - return false; - } - } - - foreach (SceneObjectGroup sog in sceneObjects) - foreach (SceneObjectPart sop in sog.Parts) - if (sop.CreatorData == null || sop.CreatorData == "") - sop.CreatorID = m_creatorIdForAssetId[assetId]; - - if (coa != null) - data = Utils.StringToBytes(CoalescedSceneObjectsSerializer.ToXml(coa)); - else - data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sceneObjects[0])); + if (data == null) + return false; } } @@ -533,7 +542,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString()); asset.Data = data; - m_scene.AssetService.Store(asset); + m_AssetService.Store(asset); return true; } @@ -546,7 +555,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } } - + /// /// Load control file /// @@ -652,4 +661,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_assetsLoaded = true; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index 0d90a15..dbaf2aa 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs @@ -52,13 +52,82 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// Find a folder given a PATH_DELIMITER delimited path starting from a user's root folder /// + /// + /// This method does not handle paths that contain multiple delimitors + /// + /// FIXME: We have no way of distinguishing folders with the same path /// + /// FIXME: Delimitors which occur in names themselves are not currently escapable. + /// + /// + /// Inventory service to query + /// + /// + /// User id to search + /// + /// + /// The path to the required folder. + /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. + /// + /// The folder found. Please note that if there are multiple folders with the same name then an + /// unspecified one will be returned. If no such folder eixsts then null is returned + public static InventoryFolderBase FindFolderByPath( + IInventoryService inventoryService, UUID userId, string path) + { + List folders = FindFoldersByPath(inventoryService, userId, path); + + if (folders.Count == 0) + return null; + else + return folders[0]; + } + + /// + /// Find a folder given a PATH_DELIMITER delimited path starting from a given folder + /// + /// /// This method does not handle paths that contain multiple delimitors /// /// FIXME: We have no way of distinguishing folders with the same path /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. + /// + /// + /// Inventory service to query + /// + /// + /// The folder from which the path starts + /// + /// + /// The path to the required folder. + /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. + /// + /// The folder found. Please note that if there are multiple folders with the same name then an + /// unspecified one will be returned. If no such folder eixsts then null is returned + public static InventoryFolderBase FindFolderByPath( + IInventoryService inventoryService, InventoryFolderBase startFolder, string path) + { + if (null == startFolder) + return null; + + List folders = FindFoldersByPath(inventoryService, startFolder, path); + + if (folders.Count == 0) + return null; + else + return folders[0]; + } + + /// + /// Find a set of folders given a PATH_DELIMITER delimited path starting from a user's root folder + /// + /// + /// This method does not handle paths that contain multiple delimitors + /// + /// FIXME: We have no way of distinguishing folders with the same path /// + /// FIXME: Delimitors which occur in names themselves are not currently escapable. + /// /// /// Inventory service to query /// @@ -70,7 +139,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. /// /// An empty list if the folder is not found, otherwise a list of all folders that match the name - public static List FindFolderByPath( + public static List FindFoldersByPath( IInventoryService inventoryService, UUID userId, string path) { InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); @@ -78,19 +147,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (null == rootFolder) return new List(); - return FindFolderByPath(inventoryService, rootFolder, path); + return FindFoldersByPath(inventoryService, rootFolder, path); } /// - /// Find a folder given a PATH_DELIMITER delimited path starting from this folder + /// Find a set of folders given a PATH_DELIMITER delimited path starting from this folder /// - /// + /// /// This method does not handle paths that contain multiple delimitors /// /// FIXME: We have no way of distinguishing folders with the same path. /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. - /// + /// /// /// Inventory service to query /// @@ -102,7 +171,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. /// /// An empty list if the folder is not found, otherwise a list of all folders that match the name - public static List FindFolderByPath( + public static List FindFoldersByPath( IInventoryService inventoryService, InventoryFolderBase startFolder, string path) { List foundFolders = new List(); @@ -133,12 +202,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); +// m_log.DebugFormat( +// "Found {0} folders in {1} for {2}", contents.Folders.Count, startFolder.Name, startFolder.Owner); + foreach (InventoryFolderBase folder in contents.Folders) { if (folder.Name == components[0]) { if (components.Length > 1) - foundFolders.AddRange(FindFolderByPath(inventoryService, folder, components[1])); + foundFolders.AddRange(FindFoldersByPath(inventoryService, folder, components[1])); else foundFolders.Add(folder); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d0e88f6..f002ad7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -34,6 +34,7 @@ using System.Xml; using log4net; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; using OpenSim.Region.CoreModules.World.Archiver; @@ -42,6 +43,8 @@ using OpenSim.Services.Interfaces; using Ionic.Zlib; using GZipStream = Ionic.Zlib.GZipStream; using CompressionMode = Ionic.Zlib.CompressionMode; +using CompressionLevel = Ionic.Zlib.CompressionLevel; +using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { @@ -54,6 +57,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public bool SaveAssets { get; set; } + /// + /// Determines which items will be included in the archive, according to their permissions. + /// Default is null, meaning no permission checks. + /// + public string FilterContent { get; set; } + + /// + /// Counter for inventory items saved to archive for passing to compltion event + /// + public int CountItems { get; set; } + + /// + /// Counter for inventory items skipped due to permission filter option for passing to compltion event + /// + public int CountFiltered { get; set; } + /// /// Used to select all inventory nodes in a folder but not the folder itself /// @@ -73,12 +92,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// ID of this request /// - protected Guid m_id; - - /// - /// Used to collect the uuids of the assets that we need to save into the archive - /// - protected Dictionary m_assetUuids = new Dictionary(); + protected UUID m_id; /// /// Used to collect the uuids of the users that we need to save into the archive @@ -94,7 +108,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// Constructor /// public InventoryArchiveWriteRequest( - Guid id, InventoryArchiverModule module, Scene scene, + UUID id, InventoryArchiverModule module, Scene scene, UserAccount userInfo, string invPath, string savePath) : this( id, @@ -110,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// Constructor /// public InventoryArchiveWriteRequest( - Guid id, InventoryArchiverModule module, Scene scene, + UUID id, InventoryArchiverModule module, Scene scene, UserAccount userInfo, string invPath, Stream saveStream) { m_id = id; @@ -122,9 +136,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_assetGatherer = new UuidGatherer(m_scene.AssetService); SaveAssets = true; + FilterContent = null; } - protected void ReceivedAllAssets(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) + protected void ReceivedAllAssets(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids, bool timedOut) { Exception reportedException = null; bool succeeded = true; @@ -143,8 +158,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_saveStream.Close(); } + if (timedOut) + { + succeeded = false; + reportedException = new Exception("Loading assets timed out"); + } + m_module.TriggerInventoryArchiveSaved( - m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); + m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException, CountItems, CountFiltered); } protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary options, IUserAccountService userAccountService) @@ -160,10 +181,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, path); } + + CountFiltered++; + return; } } + // Check For Permissions Filter Flags + if (!CanUserArchiveObject(m_userInfo.PrincipalID, inventoryItem)) + { + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Insufficient permissions, skipping inventory item {0} {1} at {2}", + inventoryItem.Name, inventoryItem.ID, path); + + // Count Items Excluded + CountFiltered++; + + return; + } + if (options.ContainsKey("verbose")) m_log.InfoFormat( "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", @@ -179,9 +216,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver AssetType itemAssetType = (AssetType)inventoryItem.AssetType; + // Count inventory items (different to asset count) + CountItems++; + // Don't chase down link asset items as they actually point to their target item IDs rather than an asset if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) - m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); + m_assetGatherer.AddForInspection(inventoryItem.AssetID); } /// @@ -237,6 +277,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } /// + /// Checks whether the user has permission to export an inventory item to an IAR. + /// + /// The user + /// The inventory item + /// Whether the user is allowed to export the object to an IAR + private bool CanUserArchiveObject(UUID UserID, InventoryItemBase InvItem) + { + if (FilterContent == null) + return true;// Default To Allow Export + + bool permitted = true; + + bool canCopy = (InvItem.CurrentPermissions & (uint)PermissionMask.Copy) != 0; + bool canTransfer = (InvItem.CurrentPermissions & (uint)PermissionMask.Transfer) != 0; + bool canMod = (InvItem.CurrentPermissions & (uint)PermissionMask.Modify) != 0; + + if (FilterContent.Contains("C") && !canCopy) + permitted = false; + + if (FilterContent.Contains("T") && !canTransfer) + permitted = false; + + if (FilterContent.Contains("M") && !canMod) + permitted = false; + + return permitted; + } + + /// /// Execute the inventory write request /// public void Execute(Dictionary options, IUserAccountService userAccountService) @@ -244,6 +313,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (options.ContainsKey("noassets") && (bool)options["noassets"]) SaveAssets = false; + // Set Permission filter if flag is set + if (options.ContainsKey("checkPermissions")) + { + Object temp; + if (options.TryGetValue("checkPermissions", out temp)) + FilterContent = temp.ToString().ToUpper(); + } + try { InventoryFolderBase inventoryFolder = null; @@ -266,6 +343,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver saveFolderContentsOnly = true; maxComponentIndex--; } + else if (maxComponentIndex == -1) + { + // If the user has just specified "/", then don't save the root "My Inventory" folder. This is + // more intuitive then requiring the user to specify "/*" for this. + saveFolderContentsOnly = true; + } m_invPath = String.Empty; for (int i = 0; i <= maxComponentIndex; i++) @@ -283,7 +366,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); List candidateFolders - = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); + = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, rootFolder, m_invPath); if (candidateFolders.Count > 0) inventoryFolder = candidateFolders[0]; } @@ -297,7 +380,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // We couldn't find the path indicated string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); Exception e = new InventoryArchiverException(errorMessage); - m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); + m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0); throw e; } @@ -335,22 +418,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (SaveAssets) { - m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); + m_assetGatherer.GatherAll(); + + m_log.DebugFormat( + "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count); AssetsRequest ar = new AssetsRequest( new AssetsArchiver(m_archiveWriter), - m_assetUuids, m_scene.AssetService, + m_assetGatherer.GatheredUuids, m_scene.AssetService, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, options, ReceivedAllAssets); - Util.FireAndForget(o => ar.Execute()); + WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name)); } else { m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); - ReceivedAllAssets(new List(), new List()); + ReceivedAllAssets(new List(), new List(), false); } } catch (Exception) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 849449b..8847414 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -34,7 +34,6 @@ using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Communications; using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -57,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // public bool DisablePresenceChecks { get; set; } public event InventoryArchiveSaved OnInventoryArchiveSaved; + public event InventoryArchiveLoaded OnInventoryArchiveLoaded; /// /// The file to load and save inventory if no filename has been specified @@ -64,9 +64,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected const string DEFAULT_INV_BACKUP_FILENAME = "user-inventory.iar"; /// - /// Pending save completions initiated from the console + /// Pending save and load completions initiated from the console /// - protected List m_pendingConsoleSaves = new List(); + protected List m_pendingConsoleTasks = new List(); /// /// All scenes that this module knows about @@ -111,6 +111,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { scene.RegisterModuleInterface(this); OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted; + OnInventoryArchiveLoaded += LoadInvConsoleCommandCompleted; scene.AddCommand( "Archiving", this, "load iar", @@ -139,7 +140,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver + "-e|--exclude= don't save the inventory item in archive" + Environment.NewLine + "-f|--excludefolder= don't save contents of the folder in archive" + Environment.NewLine + "-v|--verbose extra debug messages.\n" - + "--noassets stops assets being saved to the IAR.", + + "--noassets stops assets being saved to the IAR." + + "--perm= stops items with insufficient permissions from being saved to the IAR.\n" + + " can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer, \"M\" = Modify.\n", HandleSaveInvConsoleCommand); m_aScene = scene; @@ -175,22 +178,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// Trigger the inventory archive saved event. /// protected internal void TriggerInventoryArchiveSaved( - Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, - Exception reportedException) + UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, + Exception reportedException, int SaveCount, int FilterCount) { InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved; if (handlerInventoryArchiveSaved != null) - handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException); + handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException, SaveCount , FilterCount); + } + + /// + /// Trigger the inventory archive loaded event. + /// + protected internal void TriggerInventoryArchiveLoaded( + UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream loadStream, + Exception reportedException, int LoadCount) + { + InventoryArchiveLoaded handlerInventoryArchiveLoaded = OnInventoryArchiveLoaded; + if (handlerInventoryArchiveLoaded != null) + handlerInventoryArchiveLoaded(id, succeeded, userInfo, invPath, loadStream, reportedException, LoadCount); } public bool ArchiveInventory( - Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) + UUID id, string firstName, string lastName, string invPath, string pass, Stream saveStream) { return ArchiveInventory(id, firstName, lastName, invPath, pass, saveStream, new Dictionary()); } public bool ArchiveInventory( - Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, + UUID id, string firstName, string lastName, string invPath, string pass, Stream saveStream, Dictionary options) { if (m_scenes.Count > 0) @@ -230,7 +245,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } public bool ArchiveInventory( - Guid id, string firstName, string lastName, string invPath, string pass, string savePath, + UUID id, string firstName, string lastName, string invPath, string pass, string savePath, Dictionary options) { // if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath)) @@ -272,13 +287,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream) + public bool DearchiveInventory(UUID id, string firstName, string lastName, string invPath, string pass, Stream loadStream) { - return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary()); + return DearchiveInventory(id, firstName, lastName, invPath, pass, loadStream, new Dictionary()); } public bool DearchiveInventory( - string firstName, string lastName, string invPath, string pass, Stream loadStream, + UUID id, string firstName, string lastName, string invPath, string pass, Stream loadStream, Dictionary options) { if (m_scenes.Count > 0) @@ -294,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver try { - request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream, merge); + request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge); } catch (EntryPointNotFoundException e) { @@ -326,7 +341,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } public bool DearchiveInventory( - string firstName, string lastName, string invPath, string pass, string loadPath, + UUID id, string firstName, string lastName, string invPath, string pass, string loadPath, Dictionary options) { if (m_scenes.Count > 0) @@ -342,7 +357,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver try { - request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge); + request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge); } catch (EntryPointNotFoundException e) { @@ -378,6 +393,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { try { + UUID id = UUID.Random(); + Dictionary options = new Dictionary(); OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); @@ -400,10 +417,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", loadPath, invPath, firstName, lastName); - if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) - m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", - loadPath, firstName, lastName); + lock (m_pendingConsoleTasks) + m_pendingConsoleTasks.Add(id); + + DearchiveInventory(id, firstName, lastName, invPath, pass, loadPath, options); } catch (InventoryArchiverException e) { @@ -417,7 +434,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// protected void HandleSaveInvConsoleCommand(string module, string[] cmdparams) { - Guid id = Guid.NewGuid(); + UUID id = UUID.Random(); Dictionary options = new Dictionary(); @@ -439,6 +456,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver options["excludefolders"] = new List(); ((List)options["excludefolders"]).Add(v); }); + ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); List mainParams = ops.Parse(cmdparams); @@ -464,8 +482,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", savePath, invPath, firstName, lastName); - lock (m_pendingConsoleSaves) - m_pendingConsoleSaves.Add(id); + lock (m_pendingConsoleTasks) + m_pendingConsoleTasks.Add(id); ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, options); } @@ -476,20 +494,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } private void SaveInvConsoleCommandCompleted( - Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, - Exception reportedException) + UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, + Exception reportedException, int SaveCount, int FilterCount) { - lock (m_pendingConsoleSaves) + lock (m_pendingConsoleTasks) { - if (m_pendingConsoleSaves.Contains(id)) - m_pendingConsoleSaves.Remove(id); + if (m_pendingConsoleTasks.Contains(id)) + m_pendingConsoleTasks.Remove(id); else return; } if (succeeded) { - m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive for {0} {1}", userInfo.FirstName, userInfo.LastName); + // Report success and include item count and filter count (Skipped items due to --perm or --exclude switches) + if(FilterCount == 0) + m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive with {0} items for {1} {2}", SaveCount, userInfo.FirstName, userInfo.LastName); + else + m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive with {0} items for {1} {2}. Skipped {3} items due to exclude and/or perm switches", SaveCount, userInfo.FirstName, userInfo.LastName, FilterCount); } else { @@ -499,6 +521,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } } + private void LoadInvConsoleCommandCompleted( + UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream loadStream, + Exception reportedException, int LoadCount) + { + lock (m_pendingConsoleTasks) + { + if (m_pendingConsoleTasks.Contains(id)) + m_pendingConsoleTasks.Remove(id); + else + return; + } + + if (succeeded) + { + m_log.InfoFormat("[INVENTORY ARCHIVER]: Loaded {0} items from archive {1} for {2} {3}", LoadCount, invPath, userInfo.FirstName, userInfo.LastName); + } + else + { + m_log.ErrorFormat( + "[INVENTORY ARCHIVER]: Archive load for {0} {1} failed - {2}", + userInfo.FirstName, userInfo.LastName, reportedException.Message); + } + } + /// /// Get user information for the given name. /// @@ -536,7 +582,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } catch (Exception e) { - m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message); + m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e); return null; } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs new file mode 100644 index 0000000..c2e645f --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs @@ -0,0 +1,360 @@ +/* + * 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.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; + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests +{ + [TestFixture] + public class InventoryArchiveLoadPathTests : InventoryArchiveTestCase + { + /// + /// Test loading an IAR to various different inventory paths. + /// + [Test] + public void TestLoadIarToInventoryPaths() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + SerialiserModule serialiserModule = new SerialiserModule(); + InventoryArchiverModule archiverModule = new InventoryArchiverModule(); + + // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene + Scene scene = new SceneHelpers().SetupScene(); + + SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + + UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); + + archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); + + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); + + // Now try loading to a root child folder + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA", false); + MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); + archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); + + InventoryItemBase foundItem2 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xA/" + m_item1Name); + Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); + + // Now try loading to a more deeply nested folder + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC", false); + archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); + archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); + + InventoryItemBase foundItem3 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC/" + m_item1Name); + Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); + } + + /// + /// Test that things work when the load path specified starts with a slash + /// + [Test] + public void TestLoadIarPathStartsWithSlash() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + SerialiserModule serialiserModule = new SerialiserModule(); + InventoryArchiverModule archiverModule = new InventoryArchiverModule(); + Scene scene = new SceneHelpers().SetupScene(); + SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + + UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); + archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream); + + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath( + scene.InventoryService, m_uaMT.PrincipalID, "/Objects/" + m_item1Name); + + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()"); + } + + [Test] + public void TestLoadIarPathWithEscapedChars() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + string itemName = "You & you are a mean/man/"; + string humanEscapedItemName = @"You & you are a mean\/man\/"; + string userPassword = "meowfood"; + + InventoryArchiverModule archiverModule = new InventoryArchiverModule(); + + Scene scene = new SceneHelpers().SetupScene(); + SceneHelpers.SetupSceneModules(scene, archiverModule); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); + + // Create asset + SceneObjectGroup object1; + SceneObjectPart part1; + { + string partName = "part name"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); + Vector3 groupPosition = new Vector3(10, 20, 30); + Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 offsetPosition = new Vector3(5, 10, 15); + + part1 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Name = partName; + + object1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(object1, false); + } + + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); + scene.AssetService.Store(asset1); + + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = itemName; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + scene.AddInventoryItem(item1); + + MemoryStream archiveWriteStream = new MemoryStream(); + archiverModule.OnInventoryArchiveSaved += SaveCompleted; + + mre.Reset(); + archiverModule.ArchiveInventory( + UUID.Random(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); + mre.WaitOne(60000, false); + + // LOAD ITEM + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + + archiverModule.DearchiveInventory(UUID.Random(), userFirstName, userLastName, "Scripts", userPassword, archiveReadStream); + + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath( + scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName); + + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); +// Assert.That( +// foundItem1.CreatorId, Is.EqualTo(userUuid), +// "Loaded item non-uuid creator doesn't match that of the loading user"); + Assert.That( + foundItem1.Name, Is.EqualTo(itemName), + "Loaded item name doesn't match saved name"); + } + + /// + /// Test replication of an archive path to the user's inventory. + /// + [Test] + public void TestNewIarPath() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = new SceneHelpers().SetupScene(); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); + + Dictionary foldersCreated = new Dictionary(); + HashSet nodesLoaded = new HashSet(); + + string folder1Name = "1"; + string folder2aName = "2a"; + string folder2bName = "2b"; + + string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); + string folder2aArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2aName, UUID.Random()); + string folder2bArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2bName, UUID.Random()); + + string iarPath1 = string.Join("", new string[] { folder1ArchiveName, folder2aArchiveName }); + string iarPath2 = string.Join("", new string[] { folder1ArchiveName, folder2bArchiveName }); + + { + // Test replication of path1 + new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) + .ReplicateArchivePathToUserInventory( + iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + foldersCreated, nodesLoaded); + + List folder1Candidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); + Assert.That(folder1Candidates.Count, Is.EqualTo(1)); + + InventoryFolderBase folder1 = folder1Candidates[0]; + List folder2aCandidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); + Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); + } + + { + // Test replication of path2 + new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) + .ReplicateArchivePathToUserInventory( + iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + foldersCreated, nodesLoaded); + + List folder1Candidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); + Assert.That(folder1Candidates.Count, Is.EqualTo(1)); + + InventoryFolderBase folder1 = folder1Candidates[0]; + + List folder2aCandidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); + Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); + + List folder2bCandidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2bName); + Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); + } + } + + /// + /// Test replication of a partly existing archive path to the user's inventory. This should create + /// a duplicate path without the merge option. + /// + [Test] + public void TestPartExistingIarPath() + { + TestHelpers.InMethod(); + //log4net.Config.XmlConfigurator.Configure(); + + Scene scene = new SceneHelpers().SetupScene(); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); + + string folder1ExistingName = "a"; + string folder2Name = "b"; + + InventoryFolderBase folder1 + = UserInventoryHelpers.CreateInventoryFolder( + scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); + + string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); + string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); + + string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); + + new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) + .ReplicateArchivePathToUserInventory( + itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + new Dictionary(), new HashSet()); + + List folder1PostCandidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); + Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); + + // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. + InventoryFolderBase folder1Post = null; + foreach (InventoryFolderBase folder in folder1PostCandidates) + { + if (folder.ID != folder1.ID) + { + folder1Post = folder; + break; + } + } +// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); + + List folder2PostCandidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1Post, "b"); + Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); + } + + /// + /// Test replication of a partly existing archive path to the user's inventory. This should create + /// a merged path. + /// + [Test] + public void TestMergeIarPath() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = new SceneHelpers().SetupScene(); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); + + string folder1ExistingName = "a"; + string folder2Name = "b"; + + InventoryFolderBase folder1 + = UserInventoryHelpers.CreateInventoryFolder( + scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); + + string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); + string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); + + string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); + + new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true) + .ReplicateArchivePathToUserInventory( + itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + new Dictionary(), new HashSet()); + + List folder1PostCandidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); + Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); + Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); + + List folder2PostCandidates + = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1PostCandidates[0], "b"); + Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); + } + } +} + diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs new file mode 100644 index 0000000..57b4f80 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs @@ -0,0 +1,192 @@ +/* + * 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.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; + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests +{ + [TestFixture] + public class InventoryArchiveLoadTests : 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] + public void TestLoadCoalesecedItem() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); + m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); + + InventoryItemBase coaItem + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); + + Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); + + string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); + + CoalescedSceneObjects coa; + bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); + + Assert.That(readResult, Is.True); + Assert.That(coa.Count, Is.EqualTo(2)); + + List coaObjects = coa.Objects; + Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120"))); + Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45))); + + Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); + Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); + } + + /// + /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized + /// objects. + /// + [Test] + public void TestLoadIarCreatorAccountPresent() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); + + m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name); + + Assert.That( + foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()), + "Loaded item non-uuid creator doesn't match original"); + Assert.That( + foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID), + "Loaded item uuid creator doesn't match original"); + Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID), + "Loaded item owner doesn't match inventory reciever"); + + AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); + string xmlData = Utils.BytesToString(asset1.Data); + SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); + + Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); + } + +// /// +// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where +// /// an account exists with the same name as the creator, though not the same id. +// /// +// [Test] +// public void TestLoadIarV0_1SameNameCreator() +// { +// TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); +// +// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); +// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); +// +// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); +// InventoryItemBase foundItem1 +// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); +// +// Assert.That( +// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), +// "Loaded item non-uuid creator doesn't match original"); +// Assert.That( +// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), +// "Loaded item uuid creator doesn't match original"); +// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), +// "Loaded item owner doesn't match inventory reciever"); +// +// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); +// string xmlData = Utils.BytesToString(asset1.Data); +// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); +// +// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); +// } + + /// + /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where + /// the creator or an account with the creator's name does not exist within the system. + /// + [Test] + public void TestLoadIarV0_1AbsentCreator() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); + m_archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); + + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); + + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); + Assert.That( + foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()), + "Loaded item non-uuid creator doesn't match that of the loading user"); + Assert.That( + foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID), + "Loaded item uuid creator doesn't match that of the loading user"); + + AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); + string xmlData = Utils.BytesToString(asset1.Data); + SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); + + Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs new file mode 100644 index 0000000..7265405 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs @@ -0,0 +1,422 @@ +/* + * 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.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; + +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(UUID.Random(), null, 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( + UUID.Random(), userFirstName, userLastName, "/", userPassword, 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( + UUID.Random(), userFirstName, userLastName, "f1", userPassword, 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( + UUID.Random(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, 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( + UUID.Random(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, 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. + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index db78da9..519c697 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -36,14 +36,12 @@ 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 { @@ -163,14 +161,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests scene.AddInventoryItem(coaItem); archiverModule.ArchiveInventory( - Guid.NewGuid(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream); + UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream); m_iarStreamBytes = archiveWriteStream.ToArray(); } protected void SaveCompleted( - Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, - Exception reportedException) + UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, + Exception reportedException, int SaveCount, int FilterCount) { mre.Set(); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs deleted file mode 100644 index 06f6e49..0000000 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ /dev/null @@ -1,417 +0,0 @@ -/* - * 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 InventoryArchiverTests : 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] - public void TestLoadCoalesecedItem() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); - m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); - - InventoryItemBase coaItem - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); - - Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); - - string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); - - CoalescedSceneObjects coa; - bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); - - Assert.That(readResult, Is.True); - Assert.That(coa.Count, Is.EqualTo(2)); - - List coaObjects = coa.Objects; - Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120"))); - Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45))); - - Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); - Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); - } - - /// - /// 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, (Stream)null, false); - iarr.LoadControlFile(filePath, data); - - Assert.That(iarr.ControlFileLoaded, Is.True); - } - - /// - /// 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.FindFolderByPath(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, userPassword, 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.FindFolderByPath(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, userPassword, 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. - } - - /// - /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized - /// objects. - /// - [Test] - public void TestLoadIarCreatorAccountPresent() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); - - m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name); - - Assert.That( - foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()), - "Loaded item non-uuid creator doesn't match original"); - Assert.That( - foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID), - "Loaded item uuid creator doesn't match original"); - Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID), - "Loaded item owner doesn't match inventory reciever"); - - AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); - string xmlData = Utils.BytesToString(asset1.Data); - SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - - Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); - } - -// /// -// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where -// /// an account exists with the same name as the creator, though not the same id. -// /// -// [Test] -// public void TestLoadIarV0_1SameNameCreator() -// { -// TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); -// -// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); -// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); -// -// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); -// InventoryItemBase foundItem1 -// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); -// -// Assert.That( -// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), -// "Loaded item non-uuid creator doesn't match original"); -// Assert.That( -// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), -// "Loaded item uuid creator doesn't match original"); -// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), -// "Loaded item owner doesn't match inventory reciever"); -// -// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); -// string xmlData = Utils.BytesToString(asset1.Data); -// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); -// -// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); -// } - - /// - /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where - /// the creator or an account with the creator's name does not exist within the system. - /// - [Test] - public void TestLoadIarV0_1AbsentCreator() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); - m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); - - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); - Assert.That( - foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()), - "Loaded item non-uuid creator doesn't match that of the loading user"); - Assert.That( - foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID), - "Loaded item uuid creator doesn't match that of the loading user"); - - AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); - string xmlData = Utils.BytesToString(asset1.Data); - SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - - Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs deleted file mode 100644 index 6eb3605..0000000 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ /dev/null @@ -1,477 +0,0 @@ -/* - * 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 PathTests : InventoryArchiveTestCase - { - /// - /// Test saving an inventory path to a V0.1 OpenSim Inventory Archive - /// (subject to change since there is no fixed format yet). - /// - [Test] - public void TestSavePathToIarV0_1() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, archiverModule); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); - - // Create asset - SceneObjectGroup object1; - SceneObjectPart part1; - { - string partName = "My Little Dog Object"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); - Vector3 offsetPosition = new Vector3(5, 10, 15); - - part1 = new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Name = partName; - - object1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(object1, false); - } - - UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); - AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); - scene.AssetService.Store(asset1); - - // Create item - UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = "My Little Dog"; - item1.AssetID = asset1.FullID; - item1.ID = item1Id; - InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - scene.AddInventoryItem(item1); - - MemoryStream archiveWriteStream = new MemoryStream(); - archiverModule.OnInventoryArchiveSaved += SaveCompleted; - - // Test saving a particular path - mre.Reset(); - archiverModule.ArchiveInventory( - Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, 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}{2}", - ArchiveConstants.INVENTORY_PATH, - InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder), - 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 loading an IAR to various different inventory paths. - /// - [Test] - public void TestLoadIarToInventoryPaths() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SerialiserModule serialiserModule = new SerialiserModule(); - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - - // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene - Scene scene = new SceneHelpers().SetupScene(); - - SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - - UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood"); - UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); - - archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); - - // Now try loading to a root child folder - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA"); - MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); - archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); - - InventoryItemBase foundItem2 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xA/" + m_item1Name); - Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); - - // Now try loading to a more deeply nested folder - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC"); - archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); - archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); - - InventoryItemBase foundItem3 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC/" + m_item1Name); - Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); - } - - /// - /// Test that things work when the load path specified starts with a slash - /// - [Test] - public void TestLoadIarPathStartsWithSlash() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SerialiserModule serialiserModule = new SerialiserModule(); - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - - UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); - archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream); - - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath( - scene.InventoryService, m_uaMT.PrincipalID, "/Objects/" + m_item1Name); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()"); - } - - [Test] - public void TestLoadIarPathWithEscapedChars() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - string itemName = "You & you are a mean/man/"; - string humanEscapedItemName = @"You & you are a mean\/man\/"; - string userPassword = "meowfood"; - - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, archiverModule); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); - - // Create asset - SceneObjectGroup object1; - SceneObjectPart part1; - { - string partName = "part name"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); - Vector3 offsetPosition = new Vector3(5, 10, 15); - - part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Name = partName; - - object1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(object1, false); - } - - UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); - AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); - scene.AssetService.Store(asset1); - - // Create item - UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = itemName; - item1.AssetID = asset1.FullID; - item1.ID = item1Id; - InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - scene.AddInventoryItem(item1); - - MemoryStream archiveWriteStream = new MemoryStream(); - archiverModule.OnInventoryArchiveSaved += SaveCompleted; - - mre.Reset(); - archiverModule.ArchiveInventory( - Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); - mre.WaitOne(60000, false); - - // LOAD ITEM - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - archiverModule.DearchiveInventory(userFirstName, userLastName, "Scripts", userPassword, archiveReadStream); - - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath( - scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); -// Assert.That( -// foundItem1.CreatorId, Is.EqualTo(userUuid), -// "Loaded item non-uuid creator doesn't match that of the loading user"); - Assert.That( - foundItem1.Name, Is.EqualTo(itemName), - "Loaded item name doesn't match saved name"); - } - - /// - /// Test replication of an archive path to the user's inventory. - /// - [Test] - public void TestNewIarPath() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); - - Dictionary foldersCreated = new Dictionary(); - HashSet nodesLoaded = new HashSet(); - - string folder1Name = "1"; - string folder2aName = "2a"; - string folder2bName = "2b"; - - string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); - string folder2aArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2aName, UUID.Random()); - string folder2bArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2bName, UUID.Random()); - - string iarPath1 = string.Join("", new string[] { folder1ArchiveName, folder2aArchiveName }); - string iarPath2 = string.Join("", new string[] { folder1ArchiveName, folder2bArchiveName }); - - { - // Test replication of path1 - new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - foldersCreated, nodesLoaded); - - List folder1Candidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); - Assert.That(folder1Candidates.Count, Is.EqualTo(1)); - - InventoryFolderBase folder1 = folder1Candidates[0]; - List folder2aCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); - Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); - } - - { - // Test replication of path2 - new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - foldersCreated, nodesLoaded); - - List folder1Candidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); - Assert.That(folder1Candidates.Count, Is.EqualTo(1)); - - InventoryFolderBase folder1 = folder1Candidates[0]; - - List folder2aCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); - Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); - - List folder2bCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2bName); - Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); - } - } - - /// - /// Test replication of a partly existing archive path to the user's inventory. This should create - /// a duplicate path without the merge option. - /// - [Test] - public void TestPartExistingIarPath() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); - - string folder1ExistingName = "a"; - string folder2Name = "b"; - - InventoryFolderBase folder1 - = UserInventoryHelpers.CreateInventoryFolder( - scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - - string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); - string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); - - string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); - - new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - new Dictionary(), new HashSet()); - - List folder1PostCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); - - // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. - InventoryFolderBase folder1Post = null; - foreach (InventoryFolderBase folder in folder1PostCandidates) - { - if (folder.ID != folder1.ID) - { - folder1Post = folder; - break; - } - } -// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); - - List folder2PostCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b"); - Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); - } - - /// - /// Test replication of a partly existing archive path to the user's inventory. This should create - /// a merged path. - /// - [Test] - public void TestMergeIarPath() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); - - string folder1ExistingName = "a"; - string folder2Name = "b"; - - InventoryFolderBase folder1 - = UserInventoryHelpers.CreateInventoryFolder( - scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - - string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); - string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); - - string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); - - new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true) - .ReplicateArchivePathToUserInventory( - itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - new Dictionary(), new HashSet()); - - List folder1PostCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); - Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); - - List folder2PostCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1PostCandidates[0], "b"); - Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index bcb7f42..bba48cc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -47,10 +47,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer /// private List m_Scenelist = new List(); -// private Dictionary m_AgentRegions = -// new Dictionary(); - private IMessageTransferModule m_TransferModule = null; + private IMessageTransferModule m_TransferModule; private bool m_Enabled = true; #region Region Module interface @@ -81,9 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer // scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; -// scene.EventManager.OnClientClosed += ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; } public void RegionLoaded(Scene scene) @@ -96,11 +92,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only"); m_Enabled = false; - m_Scenelist.Clear(); - scene.EventManager.OnNewClient -= OnNewClient; -// scene.EventManager.OnClientClosed -= ClientLoggedOut; +// m_Scenelist.Clear(); +// scene.EventManager.OnNewClient -= OnNewClient; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; } } } @@ -108,9 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer public void RemoveRegion(Scene scene) { scene.EventManager.OnNewClient -= OnNewClient; -// scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; m_Scenelist.Remove(scene); } @@ -139,11 +131,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer // Inventory giving is conducted via instant message client.OnInstantMessage += OnInstantMessage; } - -// protected void OnSetRootAgentScene(UUID id, Scene scene) -// { -// m_AgentRegions[id] = scene; -// } private Scene FindClientScene(UUID agentId) { @@ -162,8 +149,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer private void OnInstantMessage(IClientAPI client, GridInstantMessage im) { // m_log.DebugFormat( -// "[INVENTORY TRANSFER]: {0} IM type received from {1}", -// (InstantMessageDialog)im.dialog, client.Name); +// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}", +// (InstantMessageDialog)im.dialog, client.Name, +// im.fromAgentID, im.fromAgentName, im.toAgentID); Scene scene = FindClientScene(client.AgentId); @@ -188,12 +176,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { UUID folderID = new UUID(im.binaryBucket, 1); - m_log.DebugFormat("[INVENTORY TRANSFER]: Inserting original folder {0} "+ - "into agent {1}'s inventory", - folderID, new UUID(im.toAgentID)); + m_log.DebugFormat( + "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory", + folderID, new UUID(im.toAgentID)); - InventoryFolderBase folderCopy - = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero); + InventoryFolderBase folderCopy + = scene.GiveInventoryFolder(client, receipientID, client.AgentId, folderID, UUID.Zero); if (folderCopy == null) { @@ -213,7 +201,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer user.ControllingClient.SendBulkUpdateInventory(folderCopy); // HACK!! - im.imSessionID = folderID.Guid; + // Insert the ID of the copied folder into the IM so that we know which item to move to trash if it + // is rejected. + // XXX: This is probably a misuse of the session ID slot. + im.imSessionID = copyID.Guid; } else { @@ -226,13 +217,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer "into agent {1}'s inventory", itemID, new UUID(im.toAgentID)); - InventoryItemBase itemCopy = scene.GiveInventoryItem( - new UUID(im.toAgentID), - client.AgentId, itemID); + string message; + InventoryItemBase itemCopy = scene.GiveInventoryItem(new UUID(im.toAgentID), client.AgentId, itemID, out message); if (itemCopy == null) { - client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); + client.SendAgentAlertMessage(message, false); return; } @@ -243,7 +233,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer user.ControllingClient.SendBulkUpdateInventory(itemCopy); // HACK!! - im.imSessionID = itemID.Guid; + // Insert the ID of the copied item into the IM so that we know which item to move to trash if it + // is rejected. + // XXX: This is probably a misuse of the session ID slot. + im.imSessionID = copyID.Guid; } // Send the IM to the recipient. The item is already @@ -379,7 +372,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer IInventoryService invService = scene.InventoryService; InventoryFolderBase trashFolder = - invService.GetFolderForType(client.AgentId, AssetType.TrashFolder); + invService.GetFolderForType(client.AgentId, FolderType.Trash); UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip @@ -403,7 +396,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { folder = new InventoryFolderBase(inventoryID, client.AgentId); folder = invService.GetFolder(folder); - + if (folder != null & trashFolder != null) { previousParentFolderID = folder.ParentID; @@ -454,90 +447,61 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer } } -// public bool NeedSceneCacheClear(UUID agentID, Scene scene) -// { -// if (!m_AgentRegions.ContainsKey(agentID)) -// { -// // Since we can get here two ways, we need to scan -// // the scenes here. This is somewhat more expensive -// // but helps avoid a nasty bug -// // -// -// foreach (Scene s in m_Scenelist) -// { -// ScenePresence presence; -// -// if (s.TryGetScenePresence(agentID, out presence)) -// { -// // If the agent is in this scene, then we -// // are being called twice in a single -// // teleport. This is wasteful of cycles -// // but harmless due to this 2nd level check -// // -// // If the agent is found in another scene -// // then the list wasn't current -// // -// // If the agent is totally unknown, then what -// // are we even doing here?? -// // -// if (s == scene) -// { -// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); -// return true; -// } -// else -// { -// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); -// return false; -// } -// } -// } -// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); -// return true; -// } -// -// // The agent is left in current Scene, so we must be -// // going to another instance -// // -// if (m_AgentRegions[agentID] == scene) -// { -// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); -// m_AgentRegions.Remove(agentID); -// return true; -// } -// -// // Another region has claimed the agent -// // -// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); -// return false; -// } -// -// public void ClientLoggedOut(UUID agentID, Scene scene) -// { -// if (m_AgentRegions.ContainsKey(agentID)) -// m_AgentRegions.Remove(agentID); -// } - /// /// /// - /// - private void OnGridInstantMessage(GridInstantMessage msg) + /// + private void OnGridInstantMessage(GridInstantMessage im) { + // Check if it's a type of message that we should handle + if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered) + || (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered) + || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) + || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined) + || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined))) + return; + + m_log.DebugFormat( + "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}", + (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID); + // Check if this is ours to handle // - Scene scene = FindClientScene(new UUID(msg.toAgentID)); + Scene scene = FindClientScene(new UUID(im.toAgentID)); if (scene == null) return; // Find agent to deliver to // - ScenePresence user = scene.GetScenePresence(new UUID(msg.toAgentID)); + ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); - // Just forward to local handling - OnInstantMessage(user.ControllingClient, msg); + if (user != null) + { + user.ControllingClient.SendInstantMessage(im); + + if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) + { + AssetType assetType = (AssetType)im.binaryBucket[0]; + UUID inventoryID = new UUID(im.binaryBucket, 1); + + IInventoryService invService = scene.InventoryService; + InventoryNodeBase node = null; + if (AssetType.Folder == assetType) + { + InventoryFolderBase folder = new InventoryFolderBase(inventoryID, new UUID(im.toAgentID)); + node = invService.GetFolder(folder); + } + else + { + InventoryItemBase item = new InventoryItemBase(inventoryID, new UUID(im.toAgentID)); + node = invService.GetItem(item); + } + if (node != null) + user.ControllingClient.SendBulkUpdateInventory(node); + } + } } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs new file mode 100644 index 0000000..7ddc396 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs @@ -0,0 +1,448 @@ +/* + * 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.Reflection; +using log4net.Config; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests +{ + [TestFixture] + public class InventoryTransferModuleTests : OpenSimTestCase + { + protected TestScene m_scene; + + [SetUp] + public override void SetUp() + { + base.SetUp(); + + IConfigSource config = new IniConfigSource(); + config.AddConfig("Messaging"); + config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule"); + + m_scene = new SceneHelpers().SetupScene(); + SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule()); + } + + [Test] + public void TestAcceptGivenItem() + { +// TestHelpers.EnableLogging(); + + UUID initialSessionId = TestHelpers.ParseTail(0x10); + UUID itemId = TestHelpers.ParseTail(0x100); + UUID assetId = TestHelpers.ParseTail(0x200); + + UserAccount ua1 + = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); + UserAccount ua2 + = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); + + ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); + TestClient giverClient = (TestClient)giverSp.ControllingClient; + + ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); + TestClient receiverClient = (TestClient)receiverSp.ControllingClient; + + // Create the object to test give + InventoryItemBase originalItem + = UserInventoryHelpers.CreateInventoryItem( + m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object); + + byte[] giveImBinaryBucket = new byte[17]; + byte[] itemIdBytes = itemId.GetBytes(); + Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); + + GridInstantMessage giveIm + = new GridInstantMessage( + m_scene, + giverSp.UUID, + giverSp.Name, + receiverSp.UUID, + (byte)InstantMessageDialog.InventoryOffered, + false, + "inventory offered msg", + initialSessionId, + false, + Vector3.Zero, + giveImBinaryBucket, + true); + + giverClient.HandleImprovedInstantMessage(giveIm); + + // These details might not all be correct. + GridInstantMessage acceptIm + = new GridInstantMessage( + m_scene, + receiverSp.UUID, + receiverSp.Name, + giverSp.UUID, + (byte)InstantMessageDialog.InventoryAccepted, + false, + "inventory accepted msg", + initialSessionId, + false, + Vector3.Zero, + null, + true); + + receiverClient.HandleImprovedInstantMessage(acceptIm); + + // Test for item remaining in the giver's inventory (here we assume a copy item) + // TODO: Test no-copy items. + InventoryItemBase originalItemAfterGive + = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); + + Assert.That(originalItemAfterGive, Is.Not.Null); + Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID)); + + // Test for item successfully making it into the receiver's inventory + InventoryItemBase receivedItem + = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj"); + + Assert.That(receivedItem, Is.Not.Null); + Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID)); + + // Test that on a delete, item still exists and is accessible for the giver. + m_scene.InventoryService.DeleteItems(receiverSp.UUID, new List() { receivedItem.ID }); + + InventoryItemBase originalItemAfterDelete + = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); + + Assert.That(originalItemAfterDelete, Is.Not.Null); + + // TODO: Test scenario where giver deletes their item first. + } + + /// + /// Test user rejection of a given item. + /// + /// + /// A rejected item still ends up in the user's trash folder. + /// + [Test] + public void TestRejectGivenItem() + { +// TestHelpers.EnableLogging(); + + UUID initialSessionId = TestHelpers.ParseTail(0x10); + UUID itemId = TestHelpers.ParseTail(0x100); + UUID assetId = TestHelpers.ParseTail(0x200); + + UserAccount ua1 + = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); + UserAccount ua2 + = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); + + ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); + TestClient giverClient = (TestClient)giverSp.ControllingClient; + + ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); + TestClient receiverClient = (TestClient)receiverSp.ControllingClient; + + // Create the object to test give + InventoryItemBase originalItem + = UserInventoryHelpers.CreateInventoryItem( + m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object); + + GridInstantMessage receivedIm = null; + receiverClient.OnReceivedInstantMessage += im => receivedIm = im; + + byte[] giveImBinaryBucket = new byte[17]; + byte[] itemIdBytes = itemId.GetBytes(); + Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); + + GridInstantMessage giveIm + = new GridInstantMessage( + m_scene, + giverSp.UUID, + giverSp.Name, + receiverSp.UUID, + (byte)InstantMessageDialog.InventoryOffered, + false, + "inventory offered msg", + initialSessionId, + false, + Vector3.Zero, + giveImBinaryBucket, + true); + + giverClient.HandleImprovedInstantMessage(giveIm); + + // These details might not all be correct. + // Session ID is now the created item ID (!) + GridInstantMessage rejectIm + = new GridInstantMessage( + m_scene, + receiverSp.UUID, + receiverSp.Name, + giverSp.UUID, + (byte)InstantMessageDialog.InventoryDeclined, + false, + "inventory declined msg", + new UUID(receivedIm.imSessionID), + false, + Vector3.Zero, + null, + true); + + receiverClient.HandleImprovedInstantMessage(rejectIm); + + // Test for item remaining in the giver's inventory (here we assume a copy item) + // TODO: Test no-copy items. + InventoryItemBase originalItemAfterGive + = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); + + Assert.That(originalItemAfterGive, Is.Not.Null); + Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID)); + + // Test for item successfully making it into the receiver's inventory + InventoryItemBase receivedItem + = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj"); + + InventoryFolderBase trashFolder + = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, FolderType.Trash); + + Assert.That(receivedItem, Is.Not.Null); + Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID)); + Assert.That(receivedItem.Folder, Is.EqualTo(trashFolder.ID)); + + // Test that on a delete, item still exists and is accessible for the giver. + m_scene.InventoryService.PurgeFolder(trashFolder); + + InventoryItemBase originalItemAfterDelete + = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); + + Assert.That(originalItemAfterDelete, Is.Not.Null); + } + + [Test] + public void TestAcceptGivenFolder() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UUID initialSessionId = TestHelpers.ParseTail(0x10); + UUID folderId = TestHelpers.ParseTail(0x100); + + UserAccount ua1 + = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); + UserAccount ua2 + = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); + + ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); + TestClient giverClient = (TestClient)giverSp.ControllingClient; + + ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); + TestClient receiverClient = (TestClient)receiverSp.ControllingClient; + + InventoryFolderBase originalFolder + = UserInventoryHelpers.CreateInventoryFolder( + m_scene.InventoryService, giverSp.UUID, folderId, "f1", true); + + byte[] giveImBinaryBucket = new byte[17]; + giveImBinaryBucket[0] = (byte)AssetType.Folder; + byte[] itemIdBytes = folderId.GetBytes(); + Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); + + GridInstantMessage giveIm + = new GridInstantMessage( + m_scene, + giverSp.UUID, + giverSp.Name, + receiverSp.UUID, + (byte)InstantMessageDialog.InventoryOffered, + false, + "inventory offered msg", + initialSessionId, + false, + Vector3.Zero, + giveImBinaryBucket, + true); + + giverClient.HandleImprovedInstantMessage(giveIm); + + // These details might not all be correct. + GridInstantMessage acceptIm + = new GridInstantMessage( + m_scene, + receiverSp.UUID, + receiverSp.Name, + giverSp.UUID, + (byte)InstantMessageDialog.InventoryAccepted, + false, + "inventory accepted msg", + initialSessionId, + false, + Vector3.Zero, + null, + true); + + receiverClient.HandleImprovedInstantMessage(acceptIm); + + // Test for item remaining in the giver's inventory (here we assume a copy item) + // TODO: Test no-copy items. + InventoryFolderBase originalFolderAfterGive + = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); + + Assert.That(originalFolderAfterGive, Is.Not.Null); + Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID)); + + // Test for item successfully making it into the receiver's inventory + InventoryFolderBase receivedFolder + = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1"); + + Assert.That(receivedFolder, Is.Not.Null); + Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID)); + + // Test that on a delete, item still exists and is accessible for the giver. + m_scene.InventoryService.DeleteFolders(receiverSp.UUID, new List() { receivedFolder.ID }); + + InventoryFolderBase originalFolderAfterDelete + = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); + + Assert.That(originalFolderAfterDelete, Is.Not.Null); + + // TODO: Test scenario where giver deletes their item first. + } + + /// + /// Test user rejection of a given item. + /// + /// + /// A rejected item still ends up in the user's trash folder. + /// + [Test] + public void TestRejectGivenFolder() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UUID initialSessionId = TestHelpers.ParseTail(0x10); + UUID folderId = TestHelpers.ParseTail(0x100); + + UserAccount ua1 + = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); + UserAccount ua2 + = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); + + ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); + TestClient giverClient = (TestClient)giverSp.ControllingClient; + + ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); + TestClient receiverClient = (TestClient)receiverSp.ControllingClient; + + // Create the folder to test give + InventoryFolderBase originalFolder + = UserInventoryHelpers.CreateInventoryFolder( + m_scene.InventoryService, giverSp.UUID, folderId, "f1", true); + + GridInstantMessage receivedIm = null; + receiverClient.OnReceivedInstantMessage += im => receivedIm = im; + + byte[] giveImBinaryBucket = new byte[17]; + giveImBinaryBucket[0] = (byte)AssetType.Folder; + byte[] itemIdBytes = folderId.GetBytes(); + Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); + + GridInstantMessage giveIm + = new GridInstantMessage( + m_scene, + giverSp.UUID, + giverSp.Name, + receiverSp.UUID, + (byte)InstantMessageDialog.InventoryOffered, + false, + "inventory offered msg", + initialSessionId, + false, + Vector3.Zero, + giveImBinaryBucket, + true); + + giverClient.HandleImprovedInstantMessage(giveIm); + + // These details might not all be correct. + // Session ID is now the created item ID (!) + GridInstantMessage rejectIm + = new GridInstantMessage( + m_scene, + receiverSp.UUID, + receiverSp.Name, + giverSp.UUID, + (byte)InstantMessageDialog.InventoryDeclined, + false, + "inventory declined msg", + new UUID(receivedIm.imSessionID), + false, + Vector3.Zero, + null, + true); + + receiverClient.HandleImprovedInstantMessage(rejectIm); + + // Test for item remaining in the giver's inventory (here we assume a copy item) + // TODO: Test no-copy items. + InventoryFolderBase originalFolderAfterGive + = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); + + Assert.That(originalFolderAfterGive, Is.Not.Null); + Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID)); + + // Test for folder successfully making it into the receiver's inventory + InventoryFolderBase receivedFolder + = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1"); + + InventoryFolderBase trashFolder + = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, FolderType.Trash); + + Assert.That(receivedFolder, Is.Not.Null); + Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID)); + Assert.That(receivedFolder.ParentID, Is.EqualTo(trashFolder.ID)); + + // Test that on a delete, item still exists and is accessible for the giver. + m_scene.InventoryService.PurgeFolder(trashFolder); + + InventoryFolderBase originalFolderAfterDelete + = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); + + Assert.That(originalFolderAfterDelete, Is.Not.Null); + } + } +} \ No newline at end of file -- cgit v1.1