752 lines
38 KiB
C#
752 lines
38 KiB
C#
/*
|
||
* Copyright (c) 2006-2016, openmetaverse.co
|
||
* Copyright (c) 2021-2024, Sjofn LLC.
|
||
* All rights reserved.
|
||
*
|
||
* - Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted provided that the following conditions are met:
|
||
*
|
||
* - Redistributions of source code must retain the above copyright notice, this
|
||
* list of conditions and the following disclaimer.
|
||
* - Neither the name of the openmetaverse.co nor the names
|
||
* of its contributors may be used to endorse or promote products derived from
|
||
* this software without specific prior written permission.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
* POSSIBILITY OF SUCH DAMAGE.
|
||
*/
|
||
|
||
/*
|
||
*
|
||
* This tests are based upon the description at
|
||
*
|
||
* http://wiki.secondlife.com/wiki/LLSD
|
||
*
|
||
* and (partially) generated by the (supposed) reference implementation at
|
||
*
|
||
* http://svn.secondlife.com/svn/linden/release/indra/lib/python/indra/base/llsd.py
|
||
*
|
||
*/
|
||
|
||
using System;
|
||
using System.IO;
|
||
using System.Text;
|
||
using System.Xml;
|
||
using NUnit.Framework;
|
||
using NUnit.Framework.Legacy;
|
||
using OpenMetaverse;
|
||
using OpenMetaverse.StructuredData;
|
||
|
||
namespace LibreMetaverse.Tests
|
||
{
|
||
|
||
[TestFixture()]
|
||
public class BinarySDTests
|
||
{
|
||
private static readonly byte[] binaryHead = Encoding.ASCII.GetBytes("<?llsd/binary?>\n");
|
||
|
||
[Test()]
|
||
public void HelperFunctions()
|
||
{
|
||
string s = "this is a teststring so that we can find something from the beginning";
|
||
byte[] sBinary = Encoding.ASCII.GetBytes(s);
|
||
MemoryStream stream = new MemoryStream(sBinary);
|
||
|
||
stream.Position = 0L;
|
||
bool result = OSDParser.FindString(stream, "this");
|
||
Assert.That(result, Is.EqualTo(true));
|
||
Assert.That(stream.Position, Is.EqualTo(4L));
|
||
|
||
stream.Position = 10L;
|
||
result = OSDParser.FindString(stream, "teststring");
|
||
Assert.That(result, Is.EqualTo(true));
|
||
Assert.That(stream.Position, Is.EqualTo(20L));
|
||
|
||
stream.Position = 25L;
|
||
result = OSDParser.FindString(stream, "notfound");
|
||
Assert.That(result, Is.EqualTo(false));
|
||
Assert.That(stream.Position, Is.EqualTo(25L));
|
||
|
||
stream.Position = 60L;
|
||
result = OSDParser.FindString(stream, "beginningAndMore");
|
||
Assert.That(result, Is.EqualTo(false));
|
||
Assert.That(stream.Position, Is.EqualTo(60L));
|
||
|
||
byte[] sFrontWhiteSpace = Encoding.ASCII.GetBytes(" \t\t\n\rtest");
|
||
MemoryStream streamTwo = new MemoryStream(sFrontWhiteSpace);
|
||
OSDParser.SkipWhiteSpace(streamTwo);
|
||
Assert.That(streamTwo.Position, Is.EqualTo(7L));
|
||
|
||
byte[] sMiddleWhiteSpace = Encoding.ASCII.GetBytes("test \t\t\n\rtest");
|
||
MemoryStream streamThree = new MemoryStream(sMiddleWhiteSpace);
|
||
streamThree.Position = 4L;
|
||
OSDParser.SkipWhiteSpace(streamThree);
|
||
Assert.That(streamThree.Position, Is.EqualTo(9L));
|
||
|
||
byte[] sNoWhiteSpace = Encoding.ASCII.GetBytes("testtesttest");
|
||
MemoryStream streamFour = new MemoryStream(sNoWhiteSpace);
|
||
OSDParser.SkipWhiteSpace(streamFour);
|
||
Assert.That(streamFour.Position, Is.EqualTo(0L));
|
||
|
||
}
|
||
|
||
// Testvalues for Undef:
|
||
private static byte[] binaryUndefValue = { 0x21 };
|
||
private static byte[] binaryUndef = (byte[])ConcatenateArrays(binaryHead, binaryUndefValue);
|
||
|
||
[Test()]
|
||
public void DeserializeUndef()
|
||
{
|
||
OSD llsdUndef = OSDParser.DeserializeLLSDBinary(binaryUndef);
|
||
Assert.That(llsdUndef.Type, Is.EqualTo(OSDType.Unknown));
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeUndef()
|
||
{
|
||
OSD llsdUndef = new OSD();
|
||
byte[] binaryUndefSerialized = OSDParser.SerializeLLSDBinary(llsdUndef);
|
||
Assert.That(binaryUndefSerialized, Is.EqualTo(binaryUndef));
|
||
}
|
||
|
||
private static byte[] binaryTrueValue = { 0x31 };
|
||
private static byte[] binaryTrue = (byte[])ConcatenateArrays(binaryHead, binaryTrueValue);
|
||
|
||
|
||
private static byte[] binaryFalseValue = { 0x30 };
|
||
private static byte[] binaryFalse = (byte[])ConcatenateArrays(binaryHead, binaryFalseValue);
|
||
|
||
[Test()]
|
||
public void DeserializeBool()
|
||
{
|
||
OSD llsdTrue = OSDParser.DeserializeLLSDBinary(binaryTrue);
|
||
Assert.That(llsdTrue.Type, Is.EqualTo(OSDType.Boolean));
|
||
Assert.That(llsdTrue.AsBoolean(), Is.EqualTo(true));
|
||
|
||
OSD llsdFalse = OSDParser.DeserializeLLSDBinary(binaryFalse);
|
||
Assert.That(llsdFalse.Type, Is.EqualTo(OSDType.Boolean));
|
||
Assert.That(llsdFalse.AsBoolean(), Is.EqualTo(false));
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeBool()
|
||
{
|
||
OSD llsdTrue = OSD.FromBoolean(true);
|
||
byte[] binaryTrueSerialized = OSDParser.SerializeLLSDBinary(llsdTrue);
|
||
Assert.That(binaryTrueSerialized, Is.EqualTo(binaryTrue));
|
||
|
||
OSD llsdFalse = OSD.FromBoolean(false);
|
||
byte[] binaryFalseSerialized = OSDParser.SerializeLLSDBinary(llsdFalse);
|
||
Assert.That(binaryFalseSerialized, Is.EqualTo(binaryFalse));
|
||
}
|
||
|
||
private static byte[] binaryZeroIntValue = { 0x69, 0x0, 0x0, 0x0, 0x0 };
|
||
private static byte[] binaryZeroInt = (byte[])ConcatenateArrays(binaryHead, binaryZeroIntValue);
|
||
|
||
private static byte[] binaryAnIntValue = { 0x69, 0x0, 0x12, 0xd7, 0x9b };
|
||
private static byte[] binaryAnInt = (byte[])ConcatenateArrays(binaryHead, binaryAnIntValue);
|
||
|
||
[Test()]
|
||
public void DeserializeInteger()
|
||
{
|
||
OSD llsdZeroInteger = OSDParser.DeserializeLLSDBinary(binaryZeroInt);
|
||
Assert.That(llsdZeroInteger.Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdZeroInteger.AsInteger(), Is.EqualTo(0));
|
||
|
||
|
||
OSD llsdAnInteger = OSDParser.DeserializeLLSDBinary(binaryAnInt);
|
||
Assert.That(llsdAnInteger.Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdAnInteger.AsInteger(), Is.EqualTo(1234843));
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeInteger()
|
||
{
|
||
OSD llsdZeroInt = OSD.FromInteger(0);
|
||
byte[] binaryZeroIntSerialized = OSDParser.SerializeLLSDBinary(llsdZeroInt);
|
||
Assert.That(binaryZeroIntSerialized, Is.EqualTo(binaryZeroInt));
|
||
|
||
binaryZeroIntSerialized = OSDParser.SerializeLLSDBinary(llsdZeroInt, false);
|
||
Assert.That(binaryZeroIntSerialized, Is.EqualTo(binaryZeroIntValue));
|
||
|
||
OSD llsdAnInt = OSD.FromInteger(1234843);
|
||
byte[] binaryAnIntSerialized = OSDParser.SerializeLLSDBinary(llsdAnInt);
|
||
Assert.That(binaryAnIntSerialized, Is.EqualTo(binaryAnInt));
|
||
|
||
binaryAnIntSerialized = OSDParser.SerializeLLSDBinary(llsdAnInt, false);
|
||
Assert.That(binaryAnIntSerialized, Is.EqualTo(binaryAnIntValue));
|
||
}
|
||
|
||
private static byte[] binaryRealValue = { 0x72, 0x41, 0x2c, 0xec, 0xf6, 0x77, 0xce, 0xd9, 0x17 };
|
||
private static byte[] binaryReal = (byte[])ConcatenateArrays(binaryHead, binaryRealValue);
|
||
|
||
[Test()]
|
||
public void DeserializeReal()
|
||
{
|
||
OSD llsdReal = OSDParser.DeserializeLLSDBinary(binaryReal);
|
||
Assert.That(llsdReal.Type, Is.EqualTo(OSDType.Real));
|
||
Assert.That(llsdReal.AsReal(), Is.EqualTo(947835.234d));
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeReal()
|
||
{
|
||
OSD llsdReal = OSD.FromReal(947835.234d);
|
||
byte[] binaryRealSerialized = OSDParser.SerializeLLSDBinary(llsdReal);
|
||
Assert.That(binaryRealSerialized, Is.EqualTo(binaryReal));
|
||
|
||
binaryRealSerialized = OSDParser.SerializeLLSDBinary(llsdReal);
|
||
Assert.That(binaryRealSerialized, Is.EqualTo(binaryReal));
|
||
}
|
||
|
||
private static byte[] binaryAUUIDValue = { 0x75, 0x97, 0xf4, 0xae, 0xca, 0x88, 0xa1, 0x42, 0xa1,
|
||
0xb3, 0x85, 0xb9, 0x7b, 0x18, 0xab, 0xb2, 0x55 };
|
||
private static byte[] binaryAUUID = (byte[])ConcatenateArrays(binaryHead, binaryAUUIDValue);
|
||
|
||
private static byte[] binaryZeroUUIDValue = { 0x75, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
|
||
private static byte[] binaryZeroUUID = (byte[])ConcatenateArrays(binaryHead, binaryZeroUUIDValue);
|
||
|
||
|
||
[Test()]
|
||
public void DeserializeUUID()
|
||
{
|
||
OSD llsdAUUID = OSDParser.DeserializeLLSDBinary(binaryAUUID);
|
||
Assert.That(llsdAUUID.Type, Is.EqualTo(OSDType.UUID));
|
||
Assert.That(llsdAUUID.AsString(), Is.EqualTo("97f4aeca-88a1-42a1-b385-b97b18abb255"));
|
||
|
||
OSD llsdZeroUUID = OSDParser.DeserializeLLSDBinary(binaryZeroUUID);
|
||
Assert.That(llsdZeroUUID.Type, Is.EqualTo(OSDType.UUID));
|
||
Assert.That(llsdZeroUUID.AsString(), Is.EqualTo("00000000-0000-0000-0000-000000000000"));
|
||
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeUUID()
|
||
{
|
||
OSD llsdAUUID = OSD.FromUUID(new UUID("97f4aeca-88a1-42a1-b385-b97b18abb255"));
|
||
byte[] binaryAUUIDSerialized = OSDParser.SerializeLLSDBinary(llsdAUUID);
|
||
Assert.That(binaryAUUIDSerialized, Is.EqualTo(binaryAUUID));
|
||
|
||
binaryAUUIDSerialized = OSDParser.SerializeLLSDBinary(llsdAUUID);
|
||
Assert.That(binaryAUUIDSerialized, Is.EqualTo(binaryAUUID));
|
||
|
||
OSD llsdZeroUUID = OSD.FromUUID(new UUID("00000000-0000-0000-0000-000000000000"));
|
||
byte[] binaryZeroUUIDSerialized = OSDParser.SerializeLLSDBinary(llsdZeroUUID);
|
||
Assert.That(binaryZeroUUIDSerialized, Is.EqualTo(binaryZeroUUID));
|
||
|
||
binaryZeroUUIDSerialized = OSDParser.SerializeLLSDBinary(llsdZeroUUID);
|
||
Assert.That(binaryZeroUUIDSerialized, Is.EqualTo(binaryZeroUUID));
|
||
}
|
||
|
||
private static byte[] binaryBinStringValue = { 0x62, 0x0, 0x0, 0x0, 0x34, // this line is the encoding header
|
||
0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73,
|
||
0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x63, 0x6f,
|
||
0x6e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68,
|
||
0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0xa, 0xd };
|
||
private static byte[] binaryBinString = (byte[])ConcatenateArrays(binaryHead, binaryBinStringValue);
|
||
|
||
[Test()]
|
||
public void DeserializeLLSDBinary()
|
||
{
|
||
OSD llsdBytes = OSDParser.DeserializeLLSDBinary(binaryBinString);
|
||
Assert.That(llsdBytes.Type, Is.EqualTo(OSDType.Binary));
|
||
byte[] contentBinString = { 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73,
|
||
0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x63, 0x6f,
|
||
0x6e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68,
|
||
0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0xa, 0xd };
|
||
Assert.That(llsdBytes.AsBinary(), Is.EqualTo(contentBinString));
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeLLSDBinary()
|
||
{
|
||
byte[] contentBinString = { 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73,
|
||
0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x63, 0x6f,
|
||
0x6e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68,
|
||
0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0xa, 0xd };
|
||
OSD llsdBinary = OSD.FromBinary(contentBinString);
|
||
byte[] binaryBinarySerialized = OSDParser.SerializeLLSDBinary(llsdBinary);
|
||
Assert.That(binaryBinarySerialized, Is.EqualTo(binaryBinString));
|
||
}
|
||
|
||
private static byte[] binaryEmptyStringValue = { 0x73, 0x0, 0x0, 0x0, 0x0 };
|
||
private static byte[] binaryEmptyString = (byte[])ConcatenateArrays(binaryHead, binaryEmptyStringValue);
|
||
private static byte[] binaryLongStringValue = { 0x73, 0x0, 0x0, 0x0, 0x25,
|
||
0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
|
||
0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
|
||
0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
|
||
0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
|
||
0x79, 0x7a, 0x30, 0x31, 0x32, 0x33,
|
||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
||
private static byte[] binaryLongString = (byte[])ConcatenateArrays(binaryHead, binaryLongStringValue);
|
||
|
||
[Test()]
|
||
public void DeserializeString()
|
||
{
|
||
OSD llsdEmptyString = OSDParser.DeserializeLLSDBinary(binaryEmptyString);
|
||
Assert.That(llsdEmptyString.Type, Is.EqualTo(OSDType.String));
|
||
string contentEmptyString = "";
|
||
Assert.That(llsdEmptyString.AsString(), Is.EqualTo(contentEmptyString));
|
||
|
||
OSD llsdLongString = OSDParser.DeserializeLLSDBinary(binaryLongString);
|
||
Assert.That(llsdLongString.Type, Is.EqualTo(OSDType.String));
|
||
string contentLongString = "abcdefghijklmnopqrstuvwxyz01234567890";
|
||
Assert.That(llsdLongString.AsString(), Is.EqualTo(contentLongString));
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeString()
|
||
{
|
||
OSD llsdString = OSD.FromString("abcdefghijklmnopqrstuvwxyz01234567890");
|
||
byte[] binaryLongStringSerialized = OSDParser.SerializeLLSDBinary(llsdString);
|
||
Assert.That(binaryLongStringSerialized, Is.EqualTo(binaryLongString));
|
||
|
||
// A test with some utf8 characters
|
||
string contentAStringXML = "<x>ƖȔȠȨɆɒ</x>";
|
||
byte[] bytes = Encoding.UTF8.GetBytes(contentAStringXML);
|
||
XmlTextReader xtr = new XmlTextReader(new MemoryStream(bytes, false));
|
||
xtr.Read();
|
||
xtr.Read();
|
||
|
||
string contentAString = xtr.ReadString();
|
||
OSD llsdAString = OSD.FromString(contentAString);
|
||
byte[] binaryAString = OSDParser.SerializeLLSDBinary(llsdAString);
|
||
OSD llsdAStringDS = OSDParser.DeserializeLLSDBinary(binaryAString);
|
||
Assert.That(llsdAStringDS.Type, Is.EqualTo(OSDType.String));
|
||
Assert.That(llsdAStringDS.AsString(), Is.EqualTo(contentAString));
|
||
|
||
// we also test for a 4byte character.
|
||
string xml = "<x>𐄷</x>";
|
||
byte[] bytesTwo = Encoding.UTF8.GetBytes(xml);
|
||
XmlTextReader xtrTwo = new XmlTextReader(new MemoryStream(bytesTwo, false));
|
||
xtrTwo.Read();
|
||
xtrTwo.Read();
|
||
string content = xtrTwo.ReadString();
|
||
|
||
OSD llsdStringOne = OSD.FromString(content);
|
||
byte[] binaryAStringOneSerialized = OSDParser.SerializeLLSDBinary(llsdStringOne);
|
||
OSD llsdStringOneDS = OSDParser.DeserializeLLSDBinary(binaryAStringOneSerialized);
|
||
Assert.That(llsdStringOneDS.Type, Is.EqualTo(OSDType.String));
|
||
Assert.That(llsdStringOneDS.AsString(), Is.EqualTo(content));
|
||
|
||
}
|
||
|
||
// Be careful. The current and above mentioned reference implementation has a bug that
|
||
// doesnt allow proper binary Uri encoding.
|
||
// We compare here to a fixed version of Uri encoding
|
||
private static byte[] binaryURIValue = { 0x6c, 0x0, 0x0, 0x0, 0x18, // this line is the encoding header
|
||
0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74,
|
||
0x65, 0x73, 0x74, 0x75, 0x72, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2f };
|
||
private static byte[] binaryURI = (byte[])ConcatenateArrays(binaryHead, binaryURIValue);
|
||
|
||
[Test()]
|
||
public void DeserializeURI()
|
||
{
|
||
OSD llsdURI = OSDParser.DeserializeLLSDBinary(binaryURI);
|
||
Assert.That(llsdURI.Type, Is.EqualTo(OSDType.URI));
|
||
Uri uri = new Uri("http://www.testurl.test/");
|
||
Assert.That(llsdURI.AsUri(), Is.EqualTo(uri));
|
||
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeURI()
|
||
{
|
||
OSD llsdUri = OSD.FromUri(new Uri("http://www.testurl.test/"));
|
||
byte[] binaryURISerialized = OSDParser.SerializeLLSDBinary(llsdUri);
|
||
Assert.That(binaryURISerialized, Is.EqualTo(binaryURI));
|
||
}
|
||
|
||
// Here is a problem.
|
||
// The reference implementation does serialize to a local timestamp and not to a universal timestamp,
|
||
// which means, this implementation and the reference implementation only work the same in the universal
|
||
// timezone. Therefore this binaryDateTimeValue is generated in the UTC timezone by the reference
|
||
// implementation.
|
||
private static byte[] binaryDateTimeValue = { 100, 0, 0, 192, 141, 167, 222, 209, 65 };
|
||
private static byte[] binaryDateTime = (byte[])ConcatenateArrays(binaryHead, binaryDateTimeValue);
|
||
|
||
[Test()]
|
||
public void DeserializeDateTime()
|
||
{
|
||
OSD llsdDateTime = OSDParser.DeserializeLLSDBinary(binaryDateTime);
|
||
Assert.That(llsdDateTime.Type, Is.EqualTo(OSDType.Date));
|
||
DateTime dt = new DateTime(2008, 1, 1, 20, 10, 31, 0, DateTimeKind.Utc);
|
||
DateTime dateLocal = llsdDateTime.AsDate();
|
||
Assert.That(dateLocal.ToUniversalTime(), Is.EqualTo(dt));
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeDateTime()
|
||
{
|
||
DateTime dt = new DateTime(2008, 1, 1, 20, 10, 31, 0, DateTimeKind.Utc);
|
||
OSD llsdDate = OSD.FromDate(dt);
|
||
byte[] binaryDateSerialized = OSDParser.SerializeLLSDBinary(llsdDate);
|
||
Assert.That(binaryDateSerialized, Is.EqualTo(binaryDateTime));
|
||
|
||
// check if a *local* time can be serialized and deserialized
|
||
DateTime dtOne = new DateTime(2009, 12, 30, 8, 25, 10, DateTimeKind.Local);
|
||
OSD llsdDateOne = OSD.FromDate(dtOne);
|
||
byte[] binaryDateOneSerialized = OSDParser.SerializeLLSDBinary(llsdDateOne);
|
||
OSD llsdDateOneDS = OSDParser.DeserializeLLSDBinary(binaryDateOneSerialized);
|
||
Assert.That(llsdDateOneDS.Type, Is.EqualTo(OSDType.Date));
|
||
Assert.That(llsdDateOneDS.AsDate(), Is.EqualTo(dtOne));
|
||
|
||
DateTime dtTwo = new DateTime(2010, 11, 11, 10, 8, 20, DateTimeKind.Utc);
|
||
OSD llsdDateTwo = OSD.FromDate(dtTwo);
|
||
byte[] binaryDateTwoSerialized = OSDParser.SerializeLLSDBinary(llsdDateTwo);
|
||
OSD llsdDateTwoDS = OSDParser.DeserializeLLSDBinary(binaryDateTwoSerialized);
|
||
Assert.That(llsdDateOneDS.Type, Is.EqualTo(OSDType.Date));
|
||
Assert.That(llsdDateTwoDS.AsDate(), Is.EqualTo(dtTwo.ToLocalTime()));
|
||
}
|
||
|
||
// Data for empty array { }
|
||
private static byte[] binaryEmptyArrayValue = { 0x5b, 0x0, 0x0, 0x0, 0x0, 0x5d };
|
||
// Encoding header + num of elements + tail
|
||
private static byte[] binaryEmptyArray = (byte[])ConcatenateArrays(binaryHead, binaryEmptyArrayValue);
|
||
// Data for simple array { 0 }
|
||
private static byte[] binarySimpleArrayValue = { 0x5b, 0x0, 0x0, 0x0, 0x1, // Encoding header + num of elements
|
||
0x69, 0x0, 0x0, 0x0, 0x0, 0x5d };
|
||
private static byte[] binarySimpleArray = (byte[])ConcatenateArrays(binaryHead, binarySimpleArrayValue);
|
||
|
||
// Data for simple array { 0, 0 }
|
||
private static byte[] binarySimpleArrayTwoValue = { 0x5b, 0x0, 0x0, 0x0, 0x2, // Encoding header + num of elements
|
||
0x69, 0x0, 0x0, 0x0, 0x0,
|
||
0x69, 0x0, 0x0, 0x0, 0x0, 0x5d };
|
||
private static byte[] binarySimpleArrayTwo = (byte[])ConcatenateArrays(binaryHead, binarySimpleArrayTwoValue);
|
||
|
||
[Test()]
|
||
public void DeserializeArray()
|
||
{
|
||
OSD llsdEmptyArray = OSDParser.DeserializeLLSDBinary(binaryEmptyArray);
|
||
Assert.That(llsdEmptyArray.Type, Is.EqualTo(OSDType.Array));
|
||
OSDArray llsdEmptyArrayArray = (OSDArray)llsdEmptyArray;
|
||
Assert.That(llsdEmptyArrayArray.Count, Is.EqualTo(0));
|
||
|
||
|
||
OSD llsdSimpleArray = OSDParser.DeserializeLLSDBinary(binarySimpleArray);
|
||
Assert.That(llsdSimpleArray.Type, Is.EqualTo(OSDType.Array));
|
||
OSDArray llsdArray = (OSDArray)llsdSimpleArray;
|
||
Assert.That(llsdArray[0].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdArray[0].AsInteger(), Is.EqualTo(0));
|
||
|
||
|
||
OSD llsdSimpleArrayTwo = OSDParser.DeserializeLLSDBinary(binarySimpleArrayTwo);
|
||
Assert.That(llsdSimpleArrayTwo.Type, Is.EqualTo(OSDType.Array));
|
||
OSDArray llsdArrayTwo = (OSDArray)llsdSimpleArrayTwo;
|
||
Assert.That(llsdArrayTwo.Count, Is.EqualTo(2));
|
||
|
||
Assert.That(llsdArrayTwo[0].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdArrayTwo[0].AsInteger(), Is.EqualTo(0));
|
||
Assert.That(llsdArrayTwo[1].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdArrayTwo[1].AsInteger(), Is.EqualTo(0));
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeArray()
|
||
{
|
||
OSDArray llsdEmptyArray = new OSDArray();
|
||
byte[] binaryEmptyArraySerialized = OSDParser.SerializeLLSDBinary(llsdEmptyArray);
|
||
Assert.That(binaryEmptyArraySerialized, Is.EqualTo(binaryEmptyArray));
|
||
|
||
binaryEmptyArraySerialized = OSDParser.SerializeLLSDBinary(llsdEmptyArray, false);
|
||
Assert.That(binaryEmptyArraySerialized, Is.EqualTo(binaryEmptyArrayValue));
|
||
|
||
OSDArray llsdSimpleArray = new OSDArray();
|
||
llsdSimpleArray.Add(OSD.FromInteger(0));
|
||
byte[] binarySimpleArraySerialized = OSDParser.SerializeLLSDBinary(llsdSimpleArray);
|
||
Assert.That(binarySimpleArraySerialized, Is.EqualTo(binarySimpleArray));
|
||
|
||
binarySimpleArraySerialized = OSDParser.SerializeLLSDBinary(llsdSimpleArray, false);
|
||
Assert.That(binarySimpleArraySerialized, Is.EqualTo(binarySimpleArrayValue));
|
||
|
||
OSDArray llsdSimpleArrayTwo = new OSDArray();
|
||
llsdSimpleArrayTwo.Add(OSD.FromInteger(0));
|
||
llsdSimpleArrayTwo.Add(OSD.FromInteger(0));
|
||
byte[] binarySimpleArrayTwoSerialized = OSDParser.SerializeLLSDBinary(llsdSimpleArrayTwo);
|
||
Assert.That(binarySimpleArrayTwoSerialized, Is.EqualTo(binarySimpleArrayTwo));
|
||
|
||
binarySimpleArrayTwoSerialized = OSDParser.SerializeLLSDBinary(llsdSimpleArrayTwo, false);
|
||
Assert.That(binarySimpleArrayTwoSerialized, Is.EqualTo(binarySimpleArrayTwoValue));
|
||
}
|
||
|
||
// Data for empty dictionary { }
|
||
private static byte[] binaryEmptyMapValue = { 0x7b, 0x0, 0x0, 0x0, 0x0, 0x7d };
|
||
private static byte[] binaryEmptyMap = (byte[])ConcatenateArrays(binaryHead, binaryEmptyMapValue);
|
||
|
||
// Data for simple dictionary { test = 0 }
|
||
private static byte[] binarySimpleMapValue = { 0x7b, 0x0, 0x0, 0x0, 0x1, // Encoding header + num of elements
|
||
0x6b, 0x0, 0x0, 0x0, 0x4, // 'k' + keylength
|
||
0x74, 0x65, 0x73, 0x74, // key 'test'
|
||
0x69, 0x0, 0x0, 0x0, 0x0, // i + '0'
|
||
0x7d };
|
||
private static byte[] binarySimpleMap = (byte[])ConcatenateArrays(binaryHead, binarySimpleMapValue);
|
||
|
||
// Data for simple dictionary { t0st = 241, tes1 = "aha", test = undef }
|
||
private static byte[] binarySimpleMapTwoValue = { 0x7b, 0x0, 0x0, 0x0, 0x3, // Encoding header + num of elements
|
||
0x6b, 0x0, 0x0, 0x0, 0x4, // 'k' + keylength
|
||
0x74, 0x65, 0x73, 0x74, // key 'test'
|
||
0x21, // undef
|
||
0x6b, 0x0, 0x0, 0x0, 0x4, // k + keylength
|
||
0x74, 0x65, 0x73, 0x31, // key 'tes1'
|
||
0x73, 0x0, 0x0, 0x0, 0x3, // string head + length
|
||
0x61, 0x68, 0x61, // 'aha'
|
||
0x6b, 0x0, 0x0, 0x0, 0x4, // k + keylength
|
||
0x74, 0x30, 0x73, 0x74, // key 't0st'
|
||
0x69, 0x0, 0x0, 0x0, 0xf1, // integer 241
|
||
0x7d };
|
||
private static byte[] binarySimpleMapTwo = (byte[])ConcatenateArrays(binaryHead, binarySimpleMapTwoValue);
|
||
|
||
[Test()]
|
||
public void DeserializeDictionary()
|
||
{
|
||
OSDMap llsdEmptyMap = (OSDMap)OSDParser.DeserializeLLSDBinary(binaryEmptyMap);
|
||
Assert.That(llsdEmptyMap.Type, Is.EqualTo(OSDType.Map));
|
||
Assert.That(llsdEmptyMap.Count, Is.EqualTo(0));
|
||
|
||
OSDMap llsdSimpleMap = (OSDMap)OSDParser.DeserializeLLSDBinary(binarySimpleMap);
|
||
Assert.That(llsdSimpleMap.Type, Is.EqualTo(OSDType.Map));
|
||
Assert.That(llsdSimpleMap.Count, Is.EqualTo(1));
|
||
Assert.That(llsdSimpleMap["test"].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdSimpleMap["test"].AsInteger(), Is.EqualTo(0));
|
||
|
||
OSDMap llsdSimpleMapTwo = (OSDMap)OSDParser.DeserializeLLSDBinary(binarySimpleMapTwo);
|
||
Assert.That(llsdSimpleMapTwo.Type, Is.EqualTo(OSDType.Map));
|
||
Assert.That(llsdSimpleMapTwo.Count, Is.EqualTo(3));
|
||
Assert.That(llsdSimpleMapTwo["test"].Type, Is.EqualTo(OSDType.Unknown));
|
||
Assert.That(llsdSimpleMapTwo["tes1"].Type, Is.EqualTo(OSDType.String));
|
||
Assert.That(llsdSimpleMapTwo["tes1"].AsString(), Is.EqualTo("aha"));
|
||
Assert.That(llsdSimpleMapTwo["t0st"].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdSimpleMapTwo["t0st"].AsInteger(), Is.EqualTo(241));
|
||
|
||
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeDictionary()
|
||
{
|
||
OSDMap llsdEmptyMap = new OSDMap();
|
||
byte[] binaryEmptyMapSerialized = OSDParser.SerializeLLSDBinary(llsdEmptyMap);
|
||
Assert.That(binaryEmptyMapSerialized, Is.EqualTo(binaryEmptyMap));
|
||
|
||
OSDMap llsdSimpleMap = new OSDMap();
|
||
llsdSimpleMap["test"] = OSD.FromInteger(0);
|
||
byte[] binarySimpleMapSerialized = OSDParser.SerializeLLSDBinary(llsdSimpleMap);
|
||
Assert.That(binarySimpleMapSerialized, Is.EqualTo(binarySimpleMap));
|
||
|
||
OSDMap llsdSimpleMapTwo = new OSDMap();
|
||
llsdSimpleMapTwo["t0st"] = OSD.FromInteger(241);
|
||
llsdSimpleMapTwo["tes1"] = OSD.FromString("aha");
|
||
llsdSimpleMapTwo["test"] = new OSD();
|
||
byte[] binarySimpleMapTwoSerialized = OSDParser.SerializeLLSDBinary(llsdSimpleMapTwo);
|
||
|
||
// We dont compare here to the original serialized value, because, as maps dont preserve order,
|
||
// the original serialized value is not *exactly* the same. Instead we compare to a deserialized
|
||
// version created by this deserializer.
|
||
OSDMap llsdSimpleMapDeserialized = (OSDMap)OSDParser.DeserializeLLSDBinary(binarySimpleMapTwoSerialized);
|
||
Assert.That(llsdSimpleMapDeserialized.Type, Is.EqualTo(OSDType.Map));
|
||
Assert.That(llsdSimpleMapDeserialized.Count, Is.EqualTo(3));
|
||
Assert.That(llsdSimpleMapDeserialized["t0st"].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdSimpleMapDeserialized["t0st"].AsInteger(), Is.EqualTo(241));
|
||
Assert.That(llsdSimpleMapDeserialized["tes1"].Type, Is.EqualTo(OSDType.String));
|
||
Assert.That(llsdSimpleMapDeserialized["tes1"].AsString(), Is.EqualTo("aha"));
|
||
Assert.That(llsdSimpleMapDeserialized["test"].Type, Is.EqualTo(OSDType.Unknown));
|
||
|
||
// we also test for a 4byte key character.
|
||
string xml = "<x>𐄷</x>";
|
||
byte[] bytes = Encoding.UTF8.GetBytes(xml);
|
||
XmlTextReader xtr = new XmlTextReader(new MemoryStream(bytes, false));
|
||
xtr.Read();
|
||
xtr.Read();
|
||
string content = xtr.ReadString();
|
||
|
||
OSDMap llsdSimpleMapThree = new OSDMap();
|
||
OSD llsdSimpleValue = OSD.FromString(content);
|
||
llsdSimpleMapThree[content] = llsdSimpleValue;
|
||
Assert.That(llsdSimpleMapThree[content].AsString(), Is.EqualTo(content));
|
||
|
||
byte[] binarySimpleMapThree = OSDParser.SerializeLLSDBinary(llsdSimpleMapThree);
|
||
OSDMap llsdSimpleMapThreeDS = (OSDMap)OSDParser.DeserializeLLSDBinary(binarySimpleMapThree);
|
||
Assert.That(llsdSimpleMapThreeDS.Type, Is.EqualTo(OSDType.Map));
|
||
Assert.That(llsdSimpleMapThreeDS.Count, Is.EqualTo(1));
|
||
Assert.That(llsdSimpleMapThreeDS[content].AsString(), Is.EqualTo(content));
|
||
|
||
}
|
||
|
||
private static byte[] binaryNestedValue = { 0x5b, 0x0, 0x0, 0x0, 0x3,
|
||
0x7b, 0x0, 0x0, 0x0, 0x2,
|
||
0x6b, 0x0, 0x0, 0x0, 0x4,
|
||
0x74, 0x65, 0x73, 0x74,
|
||
0x73, 0x0, 0x0, 0x0, 0x4,
|
||
0x77, 0x68, 0x61, 0x74,
|
||
0x6b, 0x0, 0x0, 0x0, 0x4,
|
||
0x74, 0x30, 0x73,
|
||
0x74, 0x5b, 0x0, 0x0, 0x0, 0x2,
|
||
0x69, 0x0, 0x0, 0x0, 0x1,
|
||
0x69, 0x0, 0x0, 0x0, 0x2,
|
||
0x5d, 0x7d, 0x69, 0x0, 0x0, 0x0,
|
||
0x7c, 0x69, 0x0, 0x0, 0x3, 0xdb,
|
||
0x5d };
|
||
private static byte[] binaryNested = (byte[])ConcatenateArrays(binaryHead, binaryNestedValue);
|
||
|
||
[Test()]
|
||
public void DeserializeNestedComposite()
|
||
{
|
||
OSD llsdNested = OSDParser.DeserializeLLSDBinary(binaryNested);
|
||
Assert.That(llsdNested.Type, Is.EqualTo(OSDType.Array));
|
||
OSDArray llsdArray = (OSDArray)llsdNested;
|
||
Assert.That(llsdArray.Count, Is.EqualTo(3));
|
||
|
||
OSDMap llsdMap = (OSDMap)llsdArray[0];
|
||
Assert.That(llsdMap.Type, Is.EqualTo(OSDType.Map));
|
||
Assert.That(llsdMap.Count, Is.EqualTo(2));
|
||
|
||
OSDArray llsdNestedArray = (OSDArray)llsdMap["t0st"];
|
||
Assert.That(llsdNestedArray.Type, Is.EqualTo(OSDType.Array));
|
||
OSDInteger llsdNestedIntOne = (OSDInteger)llsdNestedArray[0];
|
||
Assert.That(llsdNestedIntOne.Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdNestedIntOne.AsInteger(), Is.EqualTo(1));
|
||
OSDInteger llsdNestedIntTwo = (OSDInteger)llsdNestedArray[1];
|
||
Assert.That(llsdNestedIntTwo.Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdNestedIntTwo.AsInteger(), Is.EqualTo(2));
|
||
|
||
OSDString llsdString = (OSDString)llsdMap["test"];
|
||
Assert.That(llsdString.Type, Is.EqualTo(OSDType.String));
|
||
Assert.That(llsdString.AsString(), Is.EqualTo("what"));
|
||
|
||
OSDInteger llsdIntOne = (OSDInteger)llsdArray[1];
|
||
Assert.That(llsdIntOne.Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdIntOne.AsInteger(), Is.EqualTo(124));
|
||
OSDInteger llsdIntTwo = (OSDInteger)llsdArray[2];
|
||
Assert.That(llsdIntTwo.Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdIntTwo.AsInteger(), Is.EqualTo(987));
|
||
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeNestedComposite()
|
||
{
|
||
OSDArray llsdNested = new OSDArray();
|
||
OSDMap llsdMap = new OSDMap();
|
||
OSDArray llsdArray = new OSDArray();
|
||
llsdArray.Add(OSD.FromInteger(1));
|
||
llsdArray.Add(OSD.FromInteger(2));
|
||
llsdMap["t0st"] = llsdArray;
|
||
llsdMap["test"] = OSD.FromString("what");
|
||
llsdNested.Add(llsdMap);
|
||
llsdNested.Add(OSD.FromInteger(124));
|
||
llsdNested.Add(OSD.FromInteger(987));
|
||
|
||
byte[] binaryNestedSerialized = OSDParser.SerializeLLSDBinary(llsdNested);
|
||
// Because maps don't preserve order, we compare here to a deserialized value.
|
||
OSDArray llsdNestedDeserialized = (OSDArray)OSDParser.DeserializeLLSDBinary(binaryNestedSerialized);
|
||
Assert.That(llsdNestedDeserialized.Type, Is.EqualTo(OSDType.Array));
|
||
Assert.That(llsdNestedDeserialized.Count, Is.EqualTo(3));
|
||
|
||
OSDMap llsdMapDeserialized = (OSDMap)llsdNestedDeserialized[0];
|
||
Assert.That(llsdMapDeserialized.Type, Is.EqualTo(OSDType.Map));
|
||
Assert.That(llsdMapDeserialized.Count, Is.EqualTo(2));
|
||
Assert.That(llsdMapDeserialized["t0st"].Type, Is.EqualTo(OSDType.Array));
|
||
|
||
OSDArray llsdNestedArray = (OSDArray)llsdMapDeserialized["t0st"];
|
||
Assert.That(llsdNestedArray.Type, Is.EqualTo(OSDType.Array));
|
||
Assert.That(llsdNestedArray.Count, Is.EqualTo(2));
|
||
Assert.That(llsdNestedArray[0].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdNestedArray[0].AsInteger(), Is.EqualTo(1));
|
||
Assert.That(llsdNestedArray[1].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdNestedArray[1].AsInteger(), Is.EqualTo(2));
|
||
|
||
Assert.That(llsdMapDeserialized["test"].Type, Is.EqualTo(OSDType.String));
|
||
Assert.That(llsdMapDeserialized["test"].AsString(), Is.EqualTo("what"));
|
||
|
||
Assert.That(llsdNestedDeserialized[1].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdNestedDeserialized[1].AsInteger(), Is.EqualTo(124));
|
||
|
||
Assert.That(llsdNestedDeserialized[2].Type, Is.EqualTo(OSDType.Integer));
|
||
Assert.That(llsdNestedDeserialized[2].AsInteger(), Is.EqualTo(987));
|
||
|
||
}
|
||
|
||
[Test()]
|
||
public void SerializeLongMessage()
|
||
{
|
||
// each 80 chars
|
||
string sOne = "asdklfjasadlfkjaerotiudfgjkhsdklgjhsdklfghasdfklhjasdfkjhasdfkljahsdfjklaasdfkj8";
|
||
string sTwo = "asdfkjlaaweoiugsdfjkhsdfg,.mnasdgfkljhrtuiohfgl<67>kajsdfoiwghjkdlaaaaseldkfjgheus9";
|
||
|
||
OSD stringOne = OSD.FromString( sOne );
|
||
OSD stringTwo = OSD.FromString(sTwo);
|
||
|
||
OSDMap llsdMap = new OSDMap();
|
||
llsdMap["testOne"] = stringOne;
|
||
llsdMap["testTwo"] = stringTwo;
|
||
llsdMap["testThree"] = stringOne;
|
||
llsdMap["testFour"] = stringTwo;
|
||
llsdMap["testFive"] = stringOne;
|
||
llsdMap["testSix"] = stringTwo;
|
||
llsdMap["testSeven"] = stringOne;
|
||
llsdMap["testEight"] = stringTwo;
|
||
llsdMap["testNine"] = stringOne;
|
||
llsdMap["testTen"] = stringTwo;
|
||
|
||
|
||
byte[] binaryData = OSDParser.SerializeLLSDBinary( llsdMap );
|
||
|
||
OSDMap llsdMapDS = (OSDMap)OSDParser.DeserializeLLSDBinary( binaryData );
|
||
Assert.That(llsdMapDS.Type, Is.EqualTo(OSDType.Map));
|
||
Assert.That(llsdMapDS.Count, Is.EqualTo(10));
|
||
Assert.That(llsdMapDS["testOne"].AsString(), Is.EqualTo(sOne));
|
||
Assert.That(llsdMapDS["testTwo"].AsString(), Is.EqualTo(sTwo));
|
||
Assert.That(llsdMapDS["testThree"].AsString(), Is.EqualTo(sOne));
|
||
Assert.That(llsdMapDS["testFour"].AsString(), Is.EqualTo(sTwo));
|
||
Assert.That(llsdMapDS["testFive"].AsString(), Is.EqualTo(sOne));
|
||
Assert.That(llsdMapDS["testSix"].AsString(), Is.EqualTo(sTwo));
|
||
Assert.That(llsdMapDS["testSeven"].AsString(), Is.EqualTo(sOne));
|
||
Assert.That(llsdMapDS["testEight"].AsString(), Is.EqualTo(sTwo));
|
||
Assert.That(llsdMapDS["testNine"].AsString(), Is.EqualTo(sOne));
|
||
Assert.That(llsdMapDS["testTen"].AsString(), Is.EqualTo(sTwo));
|
||
}
|
||
|
||
|
||
static Array ConcatenateArrays(params Array[] arrays)
|
||
{
|
||
if (arrays == null)
|
||
{
|
||
throw new ArgumentNullException(nameof(arrays));
|
||
}
|
||
if (arrays.Length == 0)
|
||
{
|
||
throw new ArgumentException("No arrays specified");
|
||
}
|
||
|
||
Type type = arrays[0].GetType().GetElementType();
|
||
int totalLength = arrays[0].Length;
|
||
for (int i = 1; i < arrays.Length; i++)
|
||
{
|
||
if (arrays[i].GetType().GetElementType() != type)
|
||
{
|
||
throw new ArgumentException("Arrays must all be of the same type");
|
||
}
|
||
totalLength += arrays[i].Length;
|
||
}
|
||
|
||
Array ret = Array.CreateInstance(type, totalLength);
|
||
int index = 0;
|
||
foreach (Array array in arrays)
|
||
{
|
||
Array.Copy(array, 0, ret, index, array.Length);
|
||
index += array.Length;
|
||
}
|
||
return ret;
|
||
}
|
||
}
|
||
}
|