clockwerk-opensim – Blame information for rev 1

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