Build 0.21.6.0 (1.0 pre-patch)
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using Barotrauma.Utils;
|
||||
using FluentAssertions;
|
||||
using FsCheck;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using Xunit;
|
||||
namespace TestProject;
|
||||
|
||||
public class CoordinateSpace2DTests
|
||||
{
|
||||
class CustomGenerators
|
||||
{
|
||||
public static Arbitrary<Vector2> Vector2Generator()
|
||||
{
|
||||
const int intRange = 1 << 22;
|
||||
const float intToFloat = 1 << 19;
|
||||
|
||||
return Arb.From(
|
||||
from int x in Gen.Choose(-intRange, intRange)
|
||||
from int y in Gen.Choose(-intRange, intRange)
|
||||
select new Vector2(x / intToFloat, y / intToFloat));
|
||||
}
|
||||
}
|
||||
|
||||
public CoordinateSpace2DTests()
|
||||
{
|
||||
Arb.Register<CustomGenerators>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestLocalToCanonical()
|
||||
{
|
||||
void testCase(Tuple<Vector2, Vector2, Vector2, Vector2> args)
|
||||
{
|
||||
var (vector, origin, i, j) = args;
|
||||
|
||||
if (Vector2.DistanceSquared(i, j) <= 0.01f) { return; }
|
||||
|
||||
var space = new CoordinateSpace2D
|
||||
{
|
||||
Origin = origin,
|
||||
I = i,
|
||||
J = j
|
||||
};
|
||||
|
||||
Assert.True(Vector2.DistanceSquared(
|
||||
Vector2.Transform(vector, space.LocalToCanonical),
|
||||
origin + vector.X * i + vector.Y * j) < 0.01f);
|
||||
}
|
||||
|
||||
Prop.ForAll(
|
||||
Arb.Generate<Tuple<Vector2, Vector2, Vector2, Vector2>>().ToArbitrary(),
|
||||
testCase).QuickCheckThrowOnFailure();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Barotrauma;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Xunit;
|
||||
|
||||
namespace TestProject;
|
||||
|
||||
public class INetSerializableStructImplementationChecks
|
||||
public sealed class INetSerializableStructImplementationChecks
|
||||
{
|
||||
private delegate bool TryFindBehaviorDelegate(Type type, out NetSerializableProperties.IReadWriteBehavior behavior);
|
||||
|
||||
private Type FillGenericParameters(Type type)
|
||||
{
|
||||
// Plug in some known good parameters to evaluate
|
||||
// a concrete instance of this generic type
|
||||
|
||||
var paramsConstraints = type.GetGenericArguments()
|
||||
.Select(p => p.GetGenericParameterConstraints())
|
||||
.ToImmutableArray();
|
||||
|
||||
var chosenArgs = new Type[paramsConstraints.Length];
|
||||
|
||||
for (int i = 0; i < paramsConstraints.Length; i++)
|
||||
{
|
||||
var constraints = paramsConstraints[i];
|
||||
var baseTypeConstraints = constraints.Where(c => !c.IsGenericParameter);
|
||||
|
||||
bool hasGenericConstraint(GenericParameterAttributes flag)
|
||||
=> constraints.Any(c
|
||||
=> c.IsGenericParameter && c.GenericParameterAttributes.HasFlag(flag));
|
||||
|
||||
bool refTypeConstraint = hasGenericConstraint(GenericParameterAttributes.ReferenceTypeConstraint);
|
||||
bool valueTypeConstraint = baseTypeConstraints.Contains(typeof(ValueType));
|
||||
|
||||
if (refTypeConstraint && valueTypeConstraint)
|
||||
{
|
||||
throw new Exception($"Type \"{type.Name}\" has invalid generic constraints");
|
||||
}
|
||||
|
||||
var viableArguments = new List<Type>();
|
||||
if (!refTypeConstraint)
|
||||
{
|
||||
// Value types are viable
|
||||
viableArguments.AddRange(new[]
|
||||
{
|
||||
typeof(Vector2),
|
||||
typeof(float),
|
||||
typeof(int)
|
||||
});
|
||||
}
|
||||
if (!valueTypeConstraint)
|
||||
{
|
||||
// Reference types are viable
|
||||
viableArguments.AddRange(new[]
|
||||
{
|
||||
typeof(string),
|
||||
typeof(float[]),
|
||||
typeof(int[])
|
||||
});
|
||||
}
|
||||
|
||||
chosenArgs[i] = viableArguments.GetRandomUnsynced();
|
||||
}
|
||||
return type.MakeGenericType(chosenArgs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckStructMemberTypes()
|
||||
@@ -29,50 +86,10 @@ public class INetSerializableStructImplementationChecks
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var concreteType = type;
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
// Plug in some known good parameters to evaluate
|
||||
// a concrete instance of this generic type
|
||||
|
||||
var paramsConstraints = type.GetGenericArguments()
|
||||
.Select(p => p.GetGenericParameterConstraints())
|
||||
.ToImmutableArray();
|
||||
var concreteType = type.IsGenericType
|
||||
? FillGenericParameters(type)
|
||||
: type;
|
||||
|
||||
var chosenArgs = new Type[paramsConstraints.Length];
|
||||
|
||||
for (int i = 0; i < paramsConstraints.Length; i++)
|
||||
{
|
||||
var constraints = paramsConstraints[i];
|
||||
bool refTypeConstraint = constraints.Any(c
|
||||
=> c.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint));
|
||||
bool valueTypeConstraint = constraints.Any(c
|
||||
=> c.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint));
|
||||
if (refTypeConstraint && valueTypeConstraint)
|
||||
{
|
||||
throw new Exception($"Type \"{type.Name}\" has invalid generic constraints");
|
||||
}
|
||||
|
||||
int rngMin = refTypeConstraint ? 3 : 0;
|
||||
int rngMax = valueTypeConstraint ? 3 : 6;
|
||||
|
||||
chosenArgs[i] = Rand.Range(rngMin, rngMax) switch
|
||||
{
|
||||
0 => typeof(Vector2),
|
||||
1 => typeof(Point),
|
||||
2 => typeof(int),
|
||||
|
||||
3 => typeof(string),
|
||||
4 => typeof(float[]),
|
||||
5 => typeof(int[]),
|
||||
|
||||
var invalid => throw new Exception($"Broken RNG ranges in test, got {invalid}")
|
||||
};
|
||||
}
|
||||
|
||||
concreteType = type.MakeGenericType(chosenArgs);
|
||||
}
|
||||
|
||||
var members = NetSerializableProperties.GetPropertiesAndFields(concreteType);
|
||||
foreach (var member in members)
|
||||
{
|
||||
|
||||
@@ -217,6 +217,9 @@ namespace TestProject
|
||||
public T NotSerializedFunction() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[NetworkSerialize]
|
||||
private readonly record struct TestRecord<T>(T Value) : INetSerializableStruct;
|
||||
|
||||
private struct TupleNullableStruct<T, U> : INetSerializableStruct
|
||||
{
|
||||
[NetworkSerialize]
|
||||
@@ -248,24 +251,35 @@ namespace TestProject
|
||||
readStruct.IntValue.Should().Be(intValue);
|
||||
}
|
||||
|
||||
private static void SerializeDeserialize<T>(T arg) where T : notnull
|
||||
private static void SerializeDeserializeImpl<T>(T toWrite) where T : INetSerializableStruct
|
||||
{
|
||||
ReadWriteMessage msg = new ReadWriteMessage();
|
||||
TestStruct<T> writeStruct = new TestStruct<T>
|
||||
{
|
||||
Value = arg
|
||||
};
|
||||
|
||||
msg.WriteNetSerializableStruct(writeStruct);
|
||||
msg.WriteNetSerializableStruct(toWrite);
|
||||
msg.BitPosition = 0;
|
||||
|
||||
TestStruct<T> readStruct = INetSerializableStruct.Read<TestStruct<T>>(msg);
|
||||
T read = INetSerializableStruct.Read<T>(msg);
|
||||
|
||||
readStruct.Should().BeEquivalentTo(writeStruct, options => options
|
||||
.ComparingByMembers<TestStruct<T>>()
|
||||
read.Should().BeEquivalentTo(toWrite, options => options
|
||||
.ComparingByMembers<T>()
|
||||
.ComparingByMembers(typeof(Option<>)));
|
||||
}
|
||||
|
||||
private static void SerializeDeserializeStruct<T>(T arg) where T : notnull
|
||||
=> SerializeDeserializeImpl(new TestStruct<T>
|
||||
{
|
||||
Value = arg
|
||||
});
|
||||
|
||||
private static void SerializeDeserializeRecord<T>(T arg) where T : notnull
|
||||
=> SerializeDeserializeImpl(new TestRecord<T>(arg));
|
||||
|
||||
private static void SerializeDeserialize<T>(T arg) where T : notnull
|
||||
{
|
||||
SerializeDeserializeStruct(arg);
|
||||
SerializeDeserializeRecord(arg);
|
||||
}
|
||||
|
||||
private static void SerializeDeserializeNullableTuple<T, U>(T arg1, U arg2)
|
||||
{
|
||||
ReadWriteMessage msg = new ReadWriteMessage();
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Barotrauma;
|
||||
using FluentAssertions;
|
||||
using FsCheck;
|
||||
using Xunit;
|
||||
|
||||
namespace TestProject;
|
||||
|
||||
public sealed class SerializableDateTimeTests
|
||||
{
|
||||
private class CustomGenerators
|
||||
{
|
||||
private const short MinutesPerDay = 24 * 60;
|
||||
private const int SecondsPerDay = MinutesPerDay * 60;
|
||||
|
||||
public static Arbitrary<SerializableDateTime> SerializableDateTimeGenerator()
|
||||
{
|
||||
return Arb.From(
|
||||
from int dateTimeDay in Gen.Choose(0, (int)(DateTime.MaxValue.Ticks / TimeSpan.TicksPerDay))
|
||||
from int dateTimeSeconds in Gen.Choose(0, SecondsPerDay)
|
||||
from int timeZoneMinutes in Gen.Choose(-MinutesPerDay / 2, MinutesPerDay / 2)
|
||||
select new SerializableDateTime(
|
||||
DateTime.MinValue + TimeSpan.FromDays(dateTimeDay) + TimeSpan.FromSeconds(dateTimeSeconds),
|
||||
new SerializableTimeZone(TimeSpan.FromMinutes(timeZoneMinutes))));
|
||||
}
|
||||
}
|
||||
|
||||
public SerializableDateTimeTests()
|
||||
{
|
||||
Arb.Register<TestProject.CustomGenerators>();
|
||||
Arb.Register<CustomGenerators>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EqualityTest()
|
||||
{
|
||||
Prop.ForAll<SerializableDateTime>(EqualityCheck).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseTest()
|
||||
{
|
||||
var parseTest = "9369Y 09M 06D 03HR 43MIN 09SEC UTC+8:49";
|
||||
SerializableDateTime.Parse(parseTest);
|
||||
Prop.ForAll<SerializableDateTime>(ParseCheck).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
private static void EqualityCheck(SerializableDateTime original)
|
||||
{
|
||||
var local = original.ToLocal();
|
||||
var utc = original.ToUtc();
|
||||
original.Should().BeEquivalentTo(local);
|
||||
original.Should().BeEquivalentTo(utc);
|
||||
local.Should().BeEquivalentTo(utc);
|
||||
}
|
||||
|
||||
private static void ParseCheck(SerializableDateTime original)
|
||||
{
|
||||
var str = original.ToString();
|
||||
SerializableDateTime.Parse(str).TryUnwrap(out var parsedTime).Should().BeTrue();
|
||||
parsedTime.Should().BeEquivalentTo(original);
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,8 @@ namespace TestProject
|
||||
{
|
||||
public static Arbitrary<Vector2> Vector2Generator()
|
||||
{
|
||||
return Arb.From(from int x in Arb.Generate<int>()
|
||||
from int y in Arb.Generate<int>()
|
||||
return Arb.From(from float x in Arb.Generate<float>().Where(f => !float.IsNaN(f) && !float.IsInfinity(f))
|
||||
from float y in Arb.Generate<float>().Where(f => !float.IsNaN(f) && !float.IsInfinity(f))
|
||||
select new Vector2(x, y));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user