opensim-development – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 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 tar.WriteFile(ldPath, LandDataSerializer.Serialize(ld, null));
589 tar.Close();
590  
591 oarStream = new MemoryStream(oarStream.ToArray());
592  
593 // Load OAR
594 lock (this)
595 {
596 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
597 m_archiverModule.DearchiveRegion(oarStream);
598 }
599  
600 ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16);
601 LandData rLd = rLo.LandData;
602  
603 Assert.That(rLd.GlobalID, Is.EqualTo(landID));
604 Assert.That(rLd.OwnerID, Is.EqualTo(groupID));
605 Assert.That(rLd.GroupID, Is.EqualTo(groupID));
606 Assert.That(rLd.IsGroupOwned, Is.EqualTo(true));
607 }
608  
609 /// <summary>
610 /// Test loading the region settings of an OpenSim Region Archive.
611 /// </summary>
612 [Test]
613 public void TestLoadOarRegionSettings()
614 {
615 TestHelpers.InMethod();
616 //log4net.Config.XmlConfigurator.Configure();
617  
618 MemoryStream archiveWriteStream = new MemoryStream();
619 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
620  
621 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
622 tar.WriteFile(
623 ArchiveConstants.CONTROL_FILE_PATH,
624 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
625  
626 RegionSettings rs = new RegionSettings();
627 rs.AgentLimit = 17;
628 rs.AllowDamage = true;
629 rs.AllowLandJoinDivide = true;
630 rs.AllowLandResell = true;
631 rs.BlockFly = true;
632 rs.BlockShowInSearch = true;
633 rs.BlockTerraform = true;
634 rs.DisableCollisions = true;
635 rs.DisablePhysics = true;
636 rs.DisableScripts = true;
637 rs.Elevation1NW = 15.9;
638 rs.Elevation1NE = 45.3;
639 rs.Elevation1SE = 49;
640 rs.Elevation1SW = 1.9;
641 rs.Elevation2NW = 4.5;
642 rs.Elevation2NE = 19.2;
643 rs.Elevation2SE = 9.2;
644 rs.Elevation2SW = 2.1;
645 rs.FixedSun = true;
646 rs.SunPosition = 12.0;
647 rs.ObjectBonus = 1.4;
648 rs.RestrictPushing = true;
649 rs.TerrainLowerLimit = 0.4;
650 rs.TerrainRaiseLimit = 17.9;
651 rs.TerrainTexture1 = UUID.Parse("00000000-0000-0000-0000-000000000020");
652 rs.TerrainTexture2 = UUID.Parse("00000000-0000-0000-0000-000000000040");
653 rs.TerrainTexture3 = UUID.Parse("00000000-0000-0000-0000-000000000060");
654 rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080");
655 rs.UseEstateSun = true;
656 rs.WaterHeight = 23;
657 rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111");
658 rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33"));
659  
660 tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs));
661  
662 tar.Close();
663  
664 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
665  
666 lock (this)
667 {
668 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
669 m_archiverModule.DearchiveRegion(archiveReadStream);
670 }
671  
672 Assert.That(m_lastErrorMessage, Is.Null);
673 RegionSettings loadedRs = m_scene.RegionInfo.RegionSettings;
674  
675 Assert.That(loadedRs.AgentLimit, Is.EqualTo(17));
676 Assert.That(loadedRs.AllowDamage, Is.True);
677 Assert.That(loadedRs.AllowLandJoinDivide, Is.True);
678 Assert.That(loadedRs.AllowLandResell, Is.True);
679 Assert.That(loadedRs.BlockFly, Is.True);
680 Assert.That(loadedRs.BlockShowInSearch, Is.True);
681 Assert.That(loadedRs.BlockTerraform, Is.True);
682 Assert.That(loadedRs.DisableCollisions, Is.True);
683 Assert.That(loadedRs.DisablePhysics, Is.True);
684 Assert.That(loadedRs.DisableScripts, Is.True);
685 Assert.That(loadedRs.Elevation1NW, Is.EqualTo(15.9));
686 Assert.That(loadedRs.Elevation1NE, Is.EqualTo(45.3));
687 Assert.That(loadedRs.Elevation1SE, Is.EqualTo(49));
688 Assert.That(loadedRs.Elevation1SW, Is.EqualTo(1.9));
689 Assert.That(loadedRs.Elevation2NW, Is.EqualTo(4.5));
690 Assert.That(loadedRs.Elevation2NE, Is.EqualTo(19.2));
691 Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2));
692 Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1));
693 Assert.That(loadedRs.FixedSun, Is.True);
694 Assert.AreEqual(12.0, loadedRs.SunPosition);
695 Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4));
696 Assert.That(loadedRs.RestrictPushing, Is.True);
697 Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(0.4));
698 Assert.That(loadedRs.TerrainRaiseLimit, Is.EqualTo(17.9));
699 Assert.That(loadedRs.TerrainTexture1, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000020")));
700 Assert.That(loadedRs.TerrainTexture2, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000040")));
701 Assert.That(loadedRs.TerrainTexture3, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000060")));
702 Assert.That(loadedRs.TerrainTexture4, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000080")));
703 Assert.That(loadedRs.UseEstateSun, Is.True);
704 Assert.That(loadedRs.WaterHeight, Is.EqualTo(23));
705 Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID
706 Assert.AreEqual(0, loadedRs.SpawnPoints().Count);
707 }
708  
709 /// <summary>
710 /// Test merging an OpenSim Region Archive into an existing scene
711 /// </summary>
712 //[Test]
713 public void TestMergeOar()
714 {
715 TestHelpers.InMethod();
716 //XmlConfigurator.Configure();
717  
718 MemoryStream archiveWriteStream = new MemoryStream();
719  
720 // string part2Name = "objectMerge";
721 // PrimitiveBaseShape part2Shape = PrimitiveBaseShape.CreateCylinder();
722 // Vector3 part2GroupPosition = new Vector3(90, 80, 70);
723 // Quaternion part2RotationOffset = new Quaternion(60, 70, 80, 90);
724 // Vector3 part2OffsetPosition = new Vector3(20, 25, 30);
725  
726 SceneObjectPart part2 = CreateSceneObjectPart2();
727  
728 // Create an oar file that we can use for the merge
729 {
730 ArchiverModule archiverModule = new ArchiverModule();
731 SerialiserModule serialiserModule = new SerialiserModule();
732 TerrainModule terrainModule = new TerrainModule();
733  
734 Scene scene = m_sceneHelpers.SetupScene();
735 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
736  
737 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
738  
739 // Write out this scene
740 scene.EventManager.OnOarFileSaved += SaveCompleted;
741  
742 lock (this)
743 {
744 m_archiverModule.ArchiveRegion(archiveWriteStream);
745 Monitor.Wait(this, 60000);
746 }
747 }
748  
749 {
750 SceneObjectPart part1 = CreateSceneObjectPart1();
751 m_scene.AddNewSceneObject(new SceneObjectGroup(part1), false);
752  
753 // Merge in the archive we created earlier
754 byte[] archive = archiveWriteStream.ToArray();
755 MemoryStream archiveReadStream = new MemoryStream(archive);
756  
757 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
758 archiveOptions.Add("merge", null);
759 m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions);
760  
761 SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name);
762 Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge");
763 Assert.That(object1Existing.Name, Is.EqualTo(part1.Name), "object1 names not identical after merge");
764 Assert.That(object1Existing.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal after merge");
765  
766 SceneObjectPart object2PartMerged = m_scene.GetSceneObjectPart(part2.Name);
767 Assert.That(object2PartMerged, Is.Not.Null, "object2 was not present after merge");
768 Assert.That(object2PartMerged.Name, Is.EqualTo(part2.Name), "object2 names not identical after merge");
769 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge");
770 }
771 }
772  
773 /// <summary>
774 /// Test saving a multi-region OAR.
775 /// </summary>
776 [Test]
777 public void TestSaveMultiRegionOar()
778 {
779 TestHelpers.InMethod();
780  
781 // Create test regions
782  
783 int WIDTH = 2;
784 int HEIGHT = 2;
785  
786 List<Scene> scenes = new List<Scene>();
787  
788 // Maps (Directory in OAR file -> scene)
789 Dictionary<string, Scene> regionPaths = new Dictionary<string, Scene>();
790  
791 // Maps (Scene -> expected object paths)
792 Dictionary<UUID, List<string>> expectedPaths = new Dictionary<UUID, List<string>>();
793  
794 // List of expected assets
795 List<UUID> expectedAssets = new List<UUID>();
796  
797 for (uint y = 0; y < HEIGHT; y++)
798 {
799 for (uint x = 0; x < WIDTH; x++)
800 {
801 Scene scene;
802 if (x == 0 && y == 0)
803 {
804 scene = m_scene; // this scene was already created in SetUp()
805 }
806 else
807 {
808 scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
809 SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
810 }
811 scenes.Add(scene);
812  
813 string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_"));
814 regionPaths[dir] = scene;
815  
816 SceneObjectGroup sog1;
817 SceneObjectGroup sog2;
818 UUID ncAssetUuid;
819  
820 CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid);
821  
822 expectedPaths[scene.RegionInfo.RegionID] = new List<string>();
823 expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1));
824 expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2));
825  
826 expectedAssets.Add(ncAssetUuid);
827 }
828 }
829  
830 // Save OAR
831 MemoryStream archiveWriteStream = new MemoryStream();
832 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
833  
834 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
835  
836 Dictionary<string, Object> options = new Dictionary<string, Object>();
837 options.Add("all", true);
838  
839 lock (this)
840 {
841 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
842 Monitor.Wait(this, 60000);
843 }
844  
845  
846 // Check that the OAR contains the expected data
847 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
848  
849 byte[] archive = archiveWriteStream.ToArray();
850 MemoryStream archiveReadStream = new MemoryStream(archive);
851 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
852  
853 Dictionary<UUID, List<string>> foundPaths = new Dictionary<UUID, List<string>>();
854 List<UUID> foundAssets = new List<UUID>();
855  
856 foreach (Scene scene in scenes)
857 {
858 foundPaths[scene.RegionInfo.RegionID] = new List<string>();
859 }
860  
861 string filePath;
862 TarArchiveReader.TarEntryType tarEntryType;
863  
864 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
865 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
866  
867 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
868 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
869 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
870  
871 Assert.That(arr.ControlFileLoaded, Is.True);
872  
873 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
874 {
875 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
876 {
877 // Assets are shared, so this file doesn't belong to any specific region.
878 string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
879 if (fileName.EndsWith("_notecard.txt"))
880 foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length)));
881 }
882 else
883 {
884 // This file belongs to one of the regions. Find out which one.
885 Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH));
886 string[] parts = filePath.Split(new Char[] { '/' }, 3);
887 Assert.AreEqual(3, parts.Length);
888 string regionDirectory = parts[1];
889 string relativePath = parts[2];
890 Scene scene = regionPaths[regionDirectory];
891  
892 if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
893 {
894 foundPaths[scene.RegionInfo.RegionID].Add(relativePath);
895 }
896 }
897 }
898  
899 Assert.AreEqual(scenes.Count, foundPaths.Count);
900 foreach (Scene scene in scenes)
901 {
902 Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID]));
903 }
904  
905 Assert.That(foundAssets, Is.EquivalentTo(expectedAssets));
906 }
907  
908 /// <summary>
909 /// Test loading a multi-region OAR.
910 /// </summary>
911 [Test]
912 public void TestLoadMultiRegionOar()
913 {
914 TestHelpers.InMethod();
915  
916 // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file.
917  
918 int WIDTH = 2;
919 int HEIGHT = 2;
920  
921 for (uint y = 0; y < HEIGHT; y++)
922 {
923 for (uint x = 0; x < WIDTH; x++)
924 {
925 Scene scene;
926 if (x == 0 && y == 0)
927 {
928 scene = m_scene; // this scene was already created in SetUp()
929 }
930 else
931 {
932 scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
933 SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
934 }
935 }
936 }
937  
938 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
939 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
940 {
941 scenesGroup.AddScene(scene);
942 });
943 scenesGroup.CalcSceneLocations();
944  
945 // Generate the OAR file
946  
947 MemoryStream archiveWriteStream = new MemoryStream();
948 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
949  
950 ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty);
951 writeRequest.MultiRegionFormat = true;
952 tar.WriteFile(
953 ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup));
954  
955 SceneObjectPart part1 = CreateSceneObjectPart1();
956 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
957 part1.SitTargetPosition = new Vector3(1, 2, 3);
958  
959 SceneObjectGroup object1 = new SceneObjectGroup(part1);
960  
961 // Let's put some inventory items into our object
962 string soundItemName = "sound-item1";
963 UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
964 Type type = GetType();
965 Assembly assembly = type.Assembly;
966 string soundDataResourceName = null;
967 string[] names = assembly.GetManifestResourceNames();
968 foreach (string name in names)
969 {
970 if (name.EndsWith(".Resources.test-sound.wav"))
971 soundDataResourceName = name;
972 }
973 Assert.That(soundDataResourceName, Is.Not.Null);
974  
975 byte[] soundData;
976 UUID soundUuid;
977 CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
978  
979 TaskInventoryItem item1
980 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
981 part1.Inventory.AddInventoryItem(item1, true);
982 m_scene.AddNewSceneObject(object1, false);
983  
984 string object1FileName = string.Format(
985 "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
986 part1.Name,
987 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
988 part1.UUID);
989 string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName;
990 tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1));
991  
992 tar.Close();
993  
994  
995 // Delete the current objects, to test that they're loaded from the OAR and didn't
996 // just remain in the scene.
997 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
998 {
999 scene.DeleteAllSceneObjects();
1000 });
1001  
1002 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR
1003 m_sceneHelpers.SceneManager.CloseScene(SceneManager.Instance.Scenes[1]);
1004  
1005  
1006 // Check thay the OAR file contains the expected data
1007  
1008 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
1009  
1010 lock (this)
1011 {
1012 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
1013 m_archiverModule.DearchiveRegion(archiveReadStream);
1014 }
1015  
1016 Assert.That(m_lastErrorMessage, Is.Null);
1017  
1018 Assert.AreEqual(3, m_sceneHelpers.SceneManager.Scenes.Count);
1019  
1020 TestLoadedRegion(part1, soundItemName, soundData);
1021 }
1022  
1023 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
1024 {
1025 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
1026  
1027 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
1028 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical");
1029 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal");
1030 Assert.That(
1031 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
1032 Assert.That(
1033 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
1034 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
1035 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
1036  
1037 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
1038 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");
1039 AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString());
1040 Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null");
1041 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
1042  
1043 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
1044 }
1045 }
1046 }