ArchiverTests.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.IO;
  30. using System.Reflection;
  31. using System.Threading;
  32. using log4net.Config;
  33. using Nini.Config;
  34. using NUnit.Framework;
  35. using OpenMetaverse;
  36. using OpenMetaverse.Assets;
  37. using OpenSim.Framework;
  38. using OpenSim.Framework.Serialization;
  39. using OpenSim.Framework.Serialization.External;
  40. using OpenSim.Region.CoreModules.World.Land;
  41. using OpenSim.Region.CoreModules.World.Serialiser;
  42. using OpenSim.Region.CoreModules.World.Terrain;
  43. using OpenSim.Region.Framework.Scenes;
  44. using OpenSim.Region.Framework.Scenes.Serialization;
  45. using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
  46. using OpenSim.Tests.Common;
  47. using OpenSim.Tests.Common.Mock;
  48. using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants;
  49. using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader;
  50. using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter;
  51. using RegionSettings = OpenSim.Framework.RegionSettings;
  52. using OpenSim.Region.Framework.Interfaces;
  53. namespace OpenSim.Region.CoreModules.World.Archiver.Tests
  54. {
  55. [TestFixture]
  56. public class ArchiverTests : OpenSimTestCase
  57. {
  58. private Guid m_lastRequestId;
  59. private string m_lastErrorMessage;
  60. protected SceneHelpers m_sceneHelpers;
  61. protected TestScene m_scene;
  62. protected ArchiverModule m_archiverModule;
  63. protected SerialiserModule m_serialiserModule;
  64. protected TaskInventoryItem m_soundItem;
  65. [SetUp]
  66. public override void SetUp()
  67. {
  68. base.SetUp();
  69. m_archiverModule = new ArchiverModule();
  70. m_serialiserModule = new SerialiserModule();
  71. TerrainModule terrainModule = new TerrainModule();
  72. m_sceneHelpers = new SceneHelpers();
  73. m_scene = m_sceneHelpers.SetupScene();
  74. SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule);
  75. }
  76. private void LoadCompleted(Guid requestId, List<UUID> loadedScenes, string errorMessage)
  77. {
  78. lock (this)
  79. {
  80. m_lastRequestId = requestId;
  81. m_lastErrorMessage = errorMessage;
  82. Console.WriteLine("About to pulse ArchiverTests on LoadCompleted");
  83. Monitor.PulseAll(this);
  84. }
  85. }
  86. private void SaveCompleted(Guid requestId, string errorMessage)
  87. {
  88. lock (this)
  89. {
  90. m_lastRequestId = requestId;
  91. m_lastErrorMessage = errorMessage;
  92. Console.WriteLine("About to pulse ArchiverTests on SaveCompleted");
  93. Monitor.PulseAll(this);
  94. }
  95. }
  96. protected SceneObjectPart CreateSceneObjectPart1()
  97. {
  98. string partName = "My Little Pony";
  99. UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000015");
  100. PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
  101. Vector3 groupPosition = new Vector3(10, 20, 30);
  102. Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
  103. // Vector3 offsetPosition = new Vector3(5, 10, 15);
  104. return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, Vector3.Zero) { Name = partName };
  105. }
  106. protected SceneObjectPart CreateSceneObjectPart2()
  107. {
  108. string partName = "Action Man";
  109. UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000016");
  110. PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder();
  111. Vector3 groupPosition = new Vector3(90, 80, 70);
  112. Quaternion rotationOffset = new Quaternion(60, 70, 80, 90);
  113. Vector3 offsetPosition = new Vector3(20, 25, 30);
  114. return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName };
  115. }
  116. private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
  117. {
  118. SceneObjectPart part1 = CreateSceneObjectPart1();
  119. sog1 = new SceneObjectGroup(part1);
  120. scene.AddNewSceneObject(sog1, false);
  121. AssetNotecard nc = new AssetNotecard();
  122. nc.BodyText = "Hello World!";
  123. nc.Encode();
  124. ncAssetUuid = UUID.Random();
  125. UUID ncItemUuid = UUID.Random();
  126. AssetBase ncAsset
  127. = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
  128. m_scene.AssetService.Store(ncAsset);
  129. TaskInventoryItem ncItem
  130. = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
  131. SceneObjectPart part2 = CreateSceneObjectPart2();
  132. sog2 = new SceneObjectGroup(part2);
  133. part2.Inventory.AddInventoryItem(ncItem, true);
  134. scene.AddNewSceneObject(sog2, false);
  135. }
  136. private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid)
  137. {
  138. using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
  139. {
  140. using (BinaryReader br = new BinaryReader(resource))
  141. {
  142. // FIXME: Use the inspector instead
  143. soundData = br.ReadBytes(99999999);
  144. soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
  145. string soundAssetFileName
  146. = ArchiveConstants.ASSETS_PATH + soundUuid
  147. + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
  148. tar.WriteFile(soundAssetFileName, soundData);
  149. /*
  150. AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
  151. scene.AssetService.Store(soundAsset);
  152. asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
  153. */
  154. }
  155. }
  156. }
  157. /// <summary>
  158. /// Test saving an OpenSim Region Archive.
  159. /// </summary>
  160. [Test]
  161. public void TestSaveOar()
  162. {
  163. TestHelpers.InMethod();
  164. // log4net.Config.XmlConfigurator.Configure();
  165. SceneObjectGroup sog1;
  166. SceneObjectGroup sog2;
  167. UUID ncAssetUuid;
  168. CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid);
  169. MemoryStream archiveWriteStream = new MemoryStream();
  170. m_scene.EventManager.OnOarFileSaved += SaveCompleted;
  171. Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
  172. lock (this)
  173. {
  174. m_archiverModule.ArchiveRegion(archiveWriteStream, requestId);
  175. //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer;
  176. //while (assetServer.HasWaitingRequests())
  177. // assetServer.ProcessNextRequest();
  178. Monitor.Wait(this, 60000);
  179. }
  180. Assert.That(m_lastRequestId, Is.EqualTo(requestId));
  181. byte[] archive = archiveWriteStream.ToArray();
  182. MemoryStream archiveReadStream = new MemoryStream(archive);
  183. TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
  184. bool gotNcAssetFile = false;
  185. string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt");
  186. List<string> foundPaths = new List<string>();
  187. List<string> expectedPaths = new List<string>();
  188. expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog1));
  189. expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2));
  190. string filePath;
  191. TarArchiveReader.TarEntryType tarEntryType;
  192. byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
  193. Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
  194. ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
  195. arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
  196. Assert.That(arr.ControlFileLoaded, Is.True);
  197. while (tar.ReadEntry(out filePath, out tarEntryType) != null)
  198. {
  199. if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
  200. {
  201. string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
  202. Assert.That(fileName, Is.EqualTo(expectedNcAssetFileName));
  203. gotNcAssetFile = true;
  204. }
  205. else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
  206. {
  207. foundPaths.Add(filePath);
  208. }
  209. }
  210. Assert.That(gotNcAssetFile, Is.True, "No notecard asset file in archive");
  211. Assert.That(foundPaths, Is.EquivalentTo(expectedPaths));
  212. // TODO: Test presence of more files and contents of files.
  213. }
  214. /// <summary>
  215. /// Test saving an OpenSim Region Archive with the no assets option
  216. /// </summary>
  217. [Test]
  218. public void TestSaveOarNoAssets()
  219. {
  220. TestHelpers.InMethod();
  221. // log4net.Config.XmlConfigurator.Configure();
  222. SceneObjectPart part1 = CreateSceneObjectPart1();
  223. SceneObjectGroup sog1 = new SceneObjectGroup(part1);
  224. m_scene.AddNewSceneObject(sog1, false);
  225. SceneObjectPart part2 = CreateSceneObjectPart2();
  226. AssetNotecard nc = new AssetNotecard();
  227. nc.BodyText = "Hello World!";
  228. nc.Encode();
  229. UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
  230. UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
  231. AssetBase ncAsset
  232. = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
  233. m_scene.AssetService.Store(ncAsset);
  234. SceneObjectGroup sog2 = new SceneObjectGroup(part2);
  235. TaskInventoryItem ncItem
  236. = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
  237. part2.Inventory.AddInventoryItem(ncItem, true);
  238. m_scene.AddNewSceneObject(sog2, false);
  239. MemoryStream archiveWriteStream = new MemoryStream();
  240. Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
  241. Dictionary<string, Object> options = new Dictionary<string, Object>();
  242. options.Add("noassets", true);
  243. m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
  244. // Don't wait for completion - with --noassets save oar happens synchronously
  245. // Monitor.Wait(this, 60000);
  246. Assert.That(m_lastRequestId, Is.EqualTo(requestId));
  247. byte[] archive = archiveWriteStream.ToArray();
  248. MemoryStream archiveReadStream = new MemoryStream(archive);
  249. TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
  250. List<string> foundPaths = new List<string>();
  251. List<string> expectedPaths = new List<string>();
  252. expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog1));
  253. expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2));
  254. string filePath;
  255. TarArchiveReader.TarEntryType tarEntryType;
  256. byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
  257. Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
  258. ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
  259. arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
  260. Assert.That(arr.ControlFileLoaded, Is.True);
  261. while (tar.ReadEntry(out filePath, out tarEntryType) != null)
  262. {
  263. if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
  264. {
  265. Assert.Fail("Asset was found in saved oar of TestSaveOarNoAssets()");
  266. }
  267. else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
  268. {
  269. foundPaths.Add(filePath);
  270. }
  271. }
  272. Assert.That(foundPaths, Is.EquivalentTo(expectedPaths));
  273. // TODO: Test presence of more files and contents of files.
  274. }
  275. /// <summary>
  276. /// Test loading an OpenSim Region Archive.
  277. /// </summary>
  278. [Test]
  279. public void TestLoadOar()
  280. {
  281. TestHelpers.InMethod();
  282. // log4net.Config.XmlConfigurator.Configure();
  283. MemoryStream archiveWriteStream = new MemoryStream();
  284. TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
  285. // Put in a random blank directory to check that this doesn't upset the load process
  286. tar.WriteDir("ignoreme");
  287. // Also check that direct entries which will also have a file entry containing that directory doesn't
  288. // upset load
  289. tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
  290. tar.WriteFile(
  291. ArchiveConstants.CONTROL_FILE_PATH,
  292. new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
  293. SceneObjectPart part1 = CreateSceneObjectPart1();
  294. part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
  295. part1.SitTargetPosition = new Vector3(1, 2, 3);
  296. SceneObjectGroup object1 = new SceneObjectGroup(part1);
  297. // Let's put some inventory items into our object
  298. string soundItemName = "sound-item1";
  299. UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
  300. Type type = GetType();
  301. Assembly assembly = type.Assembly;
  302. string soundDataResourceName = null;
  303. string[] names = assembly.GetManifestResourceNames();
  304. foreach (string name in names)
  305. {
  306. if (name.EndsWith(".Resources.test-sound.wav"))
  307. soundDataResourceName = name;
  308. }
  309. Assert.That(soundDataResourceName, Is.Not.Null);
  310. byte[] soundData;
  311. UUID soundUuid;
  312. CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
  313. TaskInventoryItem item1
  314. = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
  315. part1.Inventory.AddInventoryItem(item1, true);
  316. m_scene.AddNewSceneObject(object1, false);
  317. string object1FileName = string.Format(
  318. "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
  319. part1.Name,
  320. Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
  321. part1.UUID);
  322. tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, SceneObjectSerializer.ToXml2Format(object1));
  323. tar.Close();
  324. MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
  325. lock (this)
  326. {
  327. m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
  328. m_archiverModule.DearchiveRegion(archiveReadStream);
  329. }
  330. Assert.That(m_lastErrorMessage, Is.Null);
  331. TestLoadedRegion(part1, soundItemName, soundData);
  332. }
  333. /// <summary>
  334. /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
  335. /// 2 can come after 3).
  336. /// </summary>
  337. [Test]
  338. public void TestLoadOarUnorderedParts()
  339. {
  340. TestHelpers.InMethod();
  341. UUID ownerId = TestHelpers.ParseTail(0xaaaa);
  342. MemoryStream archiveWriteStream = new MemoryStream();
  343. TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
  344. tar.WriteFile(
  345. ArchiveConstants.CONTROL_FILE_PATH,
  346. new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
  347. SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
  348. SceneObjectPart sop2
  349. = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
  350. SceneObjectPart sop3
  351. = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
  352. // Add the parts so they will be written out in reverse order to the oar
  353. sog1.AddPart(sop3);
  354. sop3.LinkNum = 3;
  355. sog1.AddPart(sop2);
  356. sop2.LinkNum = 2;
  357. tar.WriteFile(
  358. ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
  359. SceneObjectSerializer.ToXml2Format(sog1));
  360. tar.Close();
  361. MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
  362. lock (this)
  363. {
  364. m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
  365. m_archiverModule.DearchiveRegion(archiveReadStream);
  366. }
  367. Assert.That(m_lastErrorMessage, Is.Null);
  368. SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
  369. Assert.That(part2.LinkNum, Is.EqualTo(2));
  370. SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
  371. Assert.That(part3.LinkNum, Is.EqualTo(3));
  372. }
  373. /// <summary>
  374. /// Test loading an OpenSim Region Archive saved with the --publish option.
  375. /// </summary>
  376. [Test]
  377. public void TestLoadPublishedOar()
  378. {
  379. TestHelpers.InMethod();
  380. // log4net.Config.XmlConfigurator.Configure();
  381. SceneObjectPart part1 = CreateSceneObjectPart1();
  382. SceneObjectGroup sog1 = new SceneObjectGroup(part1);
  383. m_scene.AddNewSceneObject(sog1, false);
  384. SceneObjectPart part2 = CreateSceneObjectPart2();
  385. AssetNotecard nc = new AssetNotecard();
  386. nc.BodyText = "Hello World!";
  387. nc.Encode();
  388. UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
  389. UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
  390. AssetBase ncAsset
  391. = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
  392. m_scene.AssetService.Store(ncAsset);
  393. SceneObjectGroup sog2 = new SceneObjectGroup(part2);
  394. TaskInventoryItem ncItem
  395. = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
  396. part2.Inventory.AddInventoryItem(ncItem, true);
  397. m_scene.AddNewSceneObject(sog2, false);
  398. MemoryStream archiveWriteStream = new MemoryStream();
  399. m_scene.EventManager.OnOarFileSaved += SaveCompleted;
  400. Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
  401. lock (this)
  402. {
  403. m_archiverModule.ArchiveRegion(
  404. archiveWriteStream, requestId, new Dictionary<string, Object>() { { "wipe-owners", Boolean.TrueString } });
  405. Monitor.Wait(this, 60000);
  406. }
  407. Assert.That(m_lastRequestId, Is.EqualTo(requestId));
  408. byte[] archive = archiveWriteStream.ToArray();
  409. MemoryStream archiveReadStream = new MemoryStream(archive);
  410. {
  411. UUID estateOwner = TestHelpers.ParseTail(0x4747);
  412. UUID objectOwner = TestHelpers.ParseTail(0x15);
  413. // Reload to new scene
  414. ArchiverModule archiverModule = new ArchiverModule();
  415. SerialiserModule serialiserModule = new SerialiserModule();
  416. TerrainModule terrainModule = new TerrainModule();
  417. SceneHelpers m_sceneHelpers2 = new SceneHelpers();
  418. TestScene scene2 = m_sceneHelpers2.SetupScene();
  419. SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
  420. // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
  421. // behaving correctly
  422. UserAccountHelpers.CreateUserWithInventory(scene2, objectOwner);
  423. scene2.RegionInfo.EstateSettings.EstateOwner = estateOwner;
  424. lock (this)
  425. {
  426. scene2.EventManager.OnOarFileLoaded += LoadCompleted;
  427. archiverModule.DearchiveRegion(archiveReadStream);
  428. }
  429. Assert.That(m_lastErrorMessage, Is.Null);
  430. SceneObjectGroup loadedSog = scene2.GetSceneObjectGroup(part1.Name);
  431. Assert.That(loadedSog.OwnerID, Is.EqualTo(estateOwner));
  432. Assert.That(loadedSog.LastOwnerID, Is.EqualTo(estateOwner));
  433. }
  434. }
  435. /// <summary>
  436. /// Test OAR loading where the land parcel is group deeded.
  437. /// </summary>
  438. /// <remarks>
  439. /// In this situation, the owner ID is set to the group ID.
  440. /// </remarks>
  441. [Test]
  442. public void TestLoadOarDeededLand()
  443. {
  444. TestHelpers.InMethod();
  445. // TestHelpers.EnableLogging();
  446. UUID landID = TestHelpers.ParseTail(0x10);
  447. MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector();
  448. IConfigSource configSource = new IniConfigSource();
  449. IConfig config = configSource.AddConfig("Groups");
  450. config.Set("Enabled", true);
  451. config.Set("Module", "GroupsModule");
  452. config.Set("DebugEnabled", true);
  453. SceneHelpers.SetupSceneModules(
  454. m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() });
  455. // Create group in scene for loading
  456. // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests.
  457. UUID groupID
  458. = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero);
  459. // Construct OAR
  460. MemoryStream oarStream = new MemoryStream();
  461. TarArchiveWriter tar = new TarArchiveWriter(oarStream);
  462. tar.WriteDir(ArchiveConstants.LANDDATA_PATH);
  463. tar.WriteFile(
  464. ArchiveConstants.CONTROL_FILE_PATH,
  465. new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
  466. LandObject lo = new LandObject(groupID, true, null);
  467. lo.SetLandBitmap(lo.BasicFullRegionLandBitmap());
  468. LandData ld = lo.LandData;
  469. ld.GlobalID = landID;
  470. string ldPath = ArchiveConstants.CreateOarLandDataPath(ld);
  471. tar.WriteFile(ldPath, LandDataSerializer.Serialize(ld, null));
  472. tar.Close();
  473. oarStream = new MemoryStream(oarStream.ToArray());
  474. // Load OAR
  475. lock (this)
  476. {
  477. m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
  478. m_archiverModule.DearchiveRegion(oarStream);
  479. }
  480. ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16);
  481. LandData rLd = rLo.LandData;
  482. Assert.That(rLd.GlobalID, Is.EqualTo(landID));
  483. Assert.That(rLd.OwnerID, Is.EqualTo(groupID));
  484. Assert.That(rLd.GroupID, Is.EqualTo(groupID));
  485. Assert.That(rLd.IsGroupOwned, Is.EqualTo(true));
  486. }
  487. /// <summary>
  488. /// Test loading the region settings of an OpenSim Region Archive.
  489. /// </summary>
  490. [Test]
  491. public void TestLoadOarRegionSettings()
  492. {
  493. TestHelpers.InMethod();
  494. //log4net.Config.XmlConfigurator.Configure();
  495. MemoryStream archiveWriteStream = new MemoryStream();
  496. TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
  497. tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
  498. tar.WriteFile(
  499. ArchiveConstants.CONTROL_FILE_PATH,
  500. new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
  501. RegionSettings rs = new RegionSettings();
  502. rs.AgentLimit = 17;
  503. rs.AllowDamage = true;
  504. rs.AllowLandJoinDivide = true;
  505. rs.AllowLandResell = true;
  506. rs.BlockFly = true;
  507. rs.BlockShowInSearch = true;
  508. rs.BlockTerraform = true;
  509. rs.DisableCollisions = true;
  510. rs.DisablePhysics = true;
  511. rs.DisableScripts = true;
  512. rs.Elevation1NW = 15.9;
  513. rs.Elevation1NE = 45.3;
  514. rs.Elevation1SE = 49;
  515. rs.Elevation1SW = 1.9;
  516. rs.Elevation2NW = 4.5;
  517. rs.Elevation2NE = 19.2;
  518. rs.Elevation2SE = 9.2;
  519. rs.Elevation2SW = 2.1;
  520. rs.FixedSun = true;
  521. rs.SunPosition = 12.0;
  522. rs.ObjectBonus = 1.4;
  523. rs.RestrictPushing = true;
  524. rs.TerrainLowerLimit = 0.4;
  525. rs.TerrainRaiseLimit = 17.9;
  526. rs.TerrainTexture1 = UUID.Parse("00000000-0000-0000-0000-000000000020");
  527. rs.TerrainTexture2 = UUID.Parse("00000000-0000-0000-0000-000000000040");
  528. rs.TerrainTexture3 = UUID.Parse("00000000-0000-0000-0000-000000000060");
  529. rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080");
  530. rs.UseEstateSun = true;
  531. rs.WaterHeight = 23;
  532. rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111");
  533. rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33"));
  534. tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs));
  535. tar.Close();
  536. MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
  537. lock (this)
  538. {
  539. m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
  540. m_archiverModule.DearchiveRegion(archiveReadStream);
  541. }
  542. Assert.That(m_lastErrorMessage, Is.Null);
  543. RegionSettings loadedRs = m_scene.RegionInfo.RegionSettings;
  544. Assert.That(loadedRs.AgentLimit, Is.EqualTo(17));
  545. Assert.That(loadedRs.AllowDamage, Is.True);
  546. Assert.That(loadedRs.AllowLandJoinDivide, Is.True);
  547. Assert.That(loadedRs.AllowLandResell, Is.True);
  548. Assert.That(loadedRs.BlockFly, Is.True);
  549. Assert.That(loadedRs.BlockShowInSearch, Is.True);
  550. Assert.That(loadedRs.BlockTerraform, Is.True);
  551. Assert.That(loadedRs.DisableCollisions, Is.True);
  552. Assert.That(loadedRs.DisablePhysics, Is.True);
  553. Assert.That(loadedRs.DisableScripts, Is.True);
  554. Assert.That(loadedRs.Elevation1NW, Is.EqualTo(15.9));
  555. Assert.That(loadedRs.Elevation1NE, Is.EqualTo(45.3));
  556. Assert.That(loadedRs.Elevation1SE, Is.EqualTo(49));
  557. Assert.That(loadedRs.Elevation1SW, Is.EqualTo(1.9));
  558. Assert.That(loadedRs.Elevation2NW, Is.EqualTo(4.5));
  559. Assert.That(loadedRs.Elevation2NE, Is.EqualTo(19.2));
  560. Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2));
  561. Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1));
  562. Assert.That(loadedRs.FixedSun, Is.True);
  563. Assert.AreEqual(12.0, loadedRs.SunPosition);
  564. Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4));
  565. Assert.That(loadedRs.RestrictPushing, Is.True);
  566. Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(0.4));
  567. Assert.That(loadedRs.TerrainRaiseLimit, Is.EqualTo(17.9));
  568. Assert.That(loadedRs.TerrainTexture1, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000020")));
  569. Assert.That(loadedRs.TerrainTexture2, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000040")));
  570. Assert.That(loadedRs.TerrainTexture3, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000060")));
  571. Assert.That(loadedRs.TerrainTexture4, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000080")));
  572. Assert.That(loadedRs.UseEstateSun, Is.True);
  573. Assert.That(loadedRs.WaterHeight, Is.EqualTo(23));
  574. Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID
  575. Assert.AreEqual(0, loadedRs.SpawnPoints().Count);
  576. }
  577. /// <summary>
  578. /// Test merging an OpenSim Region Archive into an existing scene
  579. /// </summary>
  580. //[Test]
  581. public void TestMergeOar()
  582. {
  583. TestHelpers.InMethod();
  584. //XmlConfigurator.Configure();
  585. MemoryStream archiveWriteStream = new MemoryStream();
  586. // string part2Name = "objectMerge";
  587. // PrimitiveBaseShape part2Shape = PrimitiveBaseShape.CreateCylinder();
  588. // Vector3 part2GroupPosition = new Vector3(90, 80, 70);
  589. // Quaternion part2RotationOffset = new Quaternion(60, 70, 80, 90);
  590. // Vector3 part2OffsetPosition = new Vector3(20, 25, 30);
  591. SceneObjectPart part2 = CreateSceneObjectPart2();
  592. // Create an oar file that we can use for the merge
  593. {
  594. ArchiverModule archiverModule = new ArchiverModule();
  595. SerialiserModule serialiserModule = new SerialiserModule();
  596. TerrainModule terrainModule = new TerrainModule();
  597. Scene scene = m_sceneHelpers.SetupScene();
  598. SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
  599. m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
  600. // Write out this scene
  601. scene.EventManager.OnOarFileSaved += SaveCompleted;
  602. lock (this)
  603. {
  604. m_archiverModule.ArchiveRegion(archiveWriteStream);
  605. Monitor.Wait(this, 60000);
  606. }
  607. }
  608. {
  609. SceneObjectPart part1 = CreateSceneObjectPart1();
  610. m_scene.AddNewSceneObject(new SceneObjectGroup(part1), false);
  611. // Merge in the archive we created earlier
  612. byte[] archive = archiveWriteStream.ToArray();
  613. MemoryStream archiveReadStream = new MemoryStream(archive);
  614. m_archiverModule.DearchiveRegion(archiveReadStream, true, false, Guid.Empty);
  615. SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name);
  616. Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge");
  617. Assert.That(object1Existing.Name, Is.EqualTo(part1.Name), "object1 names not identical after merge");
  618. Assert.That(object1Existing.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal after merge");
  619. SceneObjectPart object2PartMerged = m_scene.GetSceneObjectPart(part2.Name);
  620. Assert.That(object2PartMerged, Is.Not.Null, "object2 was not present after merge");
  621. Assert.That(object2PartMerged.Name, Is.EqualTo(part2.Name), "object2 names not identical after merge");
  622. Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge");
  623. }
  624. }
  625. /// <summary>
  626. /// Test saving a multi-region OAR.
  627. /// </summary>
  628. [Test]
  629. public void TestSaveMultiRegionOar()
  630. {
  631. TestHelpers.InMethod();
  632. // Create test regions
  633. int WIDTH = 2;
  634. int HEIGHT = 2;
  635. List<Scene> scenes = new List<Scene>();
  636. // Maps (Directory in OAR file -> scene)
  637. Dictionary<string, Scene> regionPaths = new Dictionary<string, Scene>();
  638. // Maps (Scene -> expected object paths)
  639. Dictionary<UUID, List<string>> expectedPaths = new Dictionary<UUID, List<string>>();
  640. // List of expected assets
  641. List<UUID> expectedAssets = new List<UUID>();
  642. for (uint y = 0; y < HEIGHT; y++)
  643. {
  644. for (uint x = 0; x < WIDTH; x++)
  645. {
  646. Scene scene;
  647. if (x == 0 && y == 0)
  648. {
  649. scene = m_scene; // this scene was already created in SetUp()
  650. }
  651. else
  652. {
  653. scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
  654. SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
  655. }
  656. scenes.Add(scene);
  657. string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_"));
  658. regionPaths[dir] = scene;
  659. SceneObjectGroup sog1;
  660. SceneObjectGroup sog2;
  661. UUID ncAssetUuid;
  662. CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid);
  663. expectedPaths[scene.RegionInfo.RegionID] = new List<string>();
  664. expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1));
  665. expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2));
  666. expectedAssets.Add(ncAssetUuid);
  667. }
  668. }
  669. // Save OAR
  670. MemoryStream archiveWriteStream = new MemoryStream();
  671. m_scene.EventManager.OnOarFileSaved += SaveCompleted;
  672. Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
  673. Dictionary<string, Object> options = new Dictionary<string, Object>();
  674. options.Add("all", true);
  675. lock (this)
  676. {
  677. m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
  678. Monitor.Wait(this, 60000);
  679. }
  680. // Check that the OAR contains the expected data
  681. Assert.That(m_lastRequestId, Is.EqualTo(requestId));
  682. byte[] archive = archiveWriteStream.ToArray();
  683. MemoryStream archiveReadStream = new MemoryStream(archive);
  684. TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
  685. Dictionary<UUID, List<string>> foundPaths = new Dictionary<UUID, List<string>>();
  686. List<UUID> foundAssets = new List<UUID>();
  687. foreach (Scene scene in scenes)
  688. {
  689. foundPaths[scene.RegionInfo.RegionID] = new List<string>();
  690. }
  691. string filePath;
  692. TarArchiveReader.TarEntryType tarEntryType;
  693. byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
  694. Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
  695. ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
  696. arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
  697. Assert.That(arr.ControlFileLoaded, Is.True);
  698. while (tar.ReadEntry(out filePath, out tarEntryType) != null)
  699. {
  700. if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
  701. {
  702. // Assets are shared, so this file doesn't belong to any specific region.
  703. string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
  704. if (fileName.EndsWith("_notecard.txt"))
  705. foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length)));
  706. }
  707. else
  708. {
  709. // This file belongs to one of the regions. Find out which one.
  710. Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH));
  711. string[] parts = filePath.Split(new Char[] { '/' }, 3);
  712. Assert.AreEqual(3, parts.Length);
  713. string regionDirectory = parts[1];
  714. string relativePath = parts[2];
  715. Scene scene = regionPaths[regionDirectory];
  716. if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
  717. {
  718. foundPaths[scene.RegionInfo.RegionID].Add(relativePath);
  719. }
  720. }
  721. }
  722. Assert.AreEqual(scenes.Count, foundPaths.Count);
  723. foreach (Scene scene in scenes)
  724. {
  725. Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID]));
  726. }
  727. Assert.That(foundAssets, Is.EquivalentTo(expectedAssets));
  728. }
  729. /// <summary>
  730. /// Test loading a multi-region OAR.
  731. /// </summary>
  732. [Test]
  733. public void TestLoadMultiRegionOar()
  734. {
  735. TestHelpers.InMethod();
  736. // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file.
  737. int WIDTH = 2;
  738. int HEIGHT = 2;
  739. for (uint y = 0; y < HEIGHT; y++)
  740. {
  741. for (uint x = 0; x < WIDTH; x++)
  742. {
  743. Scene scene;
  744. if (x == 0 && y == 0)
  745. {
  746. scene = m_scene; // this scene was already created in SetUp()
  747. }
  748. else
  749. {
  750. scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
  751. SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
  752. }
  753. }
  754. }
  755. ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
  756. m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
  757. {
  758. scenesGroup.AddScene(scene);
  759. });
  760. scenesGroup.CalcSceneLocations();
  761. // Generate the OAR file
  762. MemoryStream archiveWriteStream = new MemoryStream();
  763. TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
  764. ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty);
  765. writeRequest.MultiRegionFormat = true;
  766. tar.WriteFile(
  767. ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup));
  768. SceneObjectPart part1 = CreateSceneObjectPart1();
  769. part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
  770. part1.SitTargetPosition = new Vector3(1, 2, 3);
  771. SceneObjectGroup object1 = new SceneObjectGroup(part1);
  772. // Let's put some inventory items into our object
  773. string soundItemName = "sound-item1";
  774. UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
  775. Type type = GetType();
  776. Assembly assembly = type.Assembly;
  777. string soundDataResourceName = null;
  778. string[] names = assembly.GetManifestResourceNames();
  779. foreach (string name in names)
  780. {
  781. if (name.EndsWith(".Resources.test-sound.wav"))
  782. soundDataResourceName = name;
  783. }
  784. Assert.That(soundDataResourceName, Is.Not.Null);
  785. byte[] soundData;
  786. UUID soundUuid;
  787. CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
  788. TaskInventoryItem item1
  789. = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
  790. part1.Inventory.AddInventoryItem(item1, true);
  791. m_scene.AddNewSceneObject(object1, false);
  792. string object1FileName = string.Format(
  793. "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
  794. part1.Name,
  795. Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
  796. part1.UUID);
  797. string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName;
  798. tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1));
  799. tar.Close();
  800. // Delete the current objects, to test that they're loaded from the OAR and didn't
  801. // just remain in the scene.
  802. m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
  803. {
  804. scene.DeleteAllSceneObjects();
  805. });
  806. // Create a "hole", to test that that the corresponding region isn't loaded from the OAR
  807. m_sceneHelpers.SceneManager.CloseScene(SceneManager.Instance.Scenes[1]);
  808. // Check thay the OAR file contains the expected data
  809. MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
  810. lock (this)
  811. {
  812. m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
  813. m_archiverModule.DearchiveRegion(archiveReadStream);
  814. }
  815. Assert.That(m_lastErrorMessage, Is.Null);
  816. Assert.AreEqual(3, m_sceneHelpers.SceneManager.Scenes.Count);
  817. TestLoadedRegion(part1, soundItemName, soundData);
  818. }
  819. private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
  820. {
  821. SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
  822. Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
  823. Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical");
  824. Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal");
  825. Assert.That(
  826. object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
  827. Assert.That(
  828. object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
  829. Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
  830. Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
  831. TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
  832. Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");
  833. AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString());
  834. Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null");
  835. Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
  836. Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
  837. }
  838. }
  839. }