Build 0.18.0.0
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using Barotrauma;
|
||||
using Barotrauma.Networking;
|
||||
using FluentAssertions;
|
||||
using FsCheck;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Xunit;
|
||||
|
||||
namespace TestProject
|
||||
{
|
||||
// ReSharper disable UnusedMember.Local NotAccessedField.Local UnusedMember.Global
|
||||
public class INetSerializableStructTests
|
||||
{
|
||||
private class CustomGenerators
|
||||
{
|
||||
// no null strings!!!
|
||||
public static Arbitrary<string> StringGeneratorOverride() => Arb.Default.String().Generator.Where(s => s != null).ToArbitrary();
|
||||
}
|
||||
|
||||
public INetSerializableStructTests()
|
||||
{
|
||||
Arb.Register<TestProject.CustomGenerators>();
|
||||
Arb.Register<CustomGenerators>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestOptional()
|
||||
{
|
||||
Prop.ForAll<Option<Int32>>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
Prop.ForAll<Option<Byte[]>>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
Prop.ForAll<Option<String>>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestNested()
|
||||
{
|
||||
Prop.ForAll<String, Int32, Boolean>((arg1, arg2, arg3) => SerializeDeserializeNullableTuple(arg1, new TupleNullableStruct<int, bool> { One = arg2, Two = arg3 })).QuickCheckThrowOnFailure();
|
||||
Prop.ForAll<Byte, UInt64>((arg1, arg2) => SerializeDeserialize(new TupleNullableStruct<byte, ulong> { One = arg1, Two = arg2 })).QuickCheckThrowOnFailure();
|
||||
Prop.ForAll<Int16, String>((arg1, arg2) => SerializeDeserialize(new TupleNullableStruct<short, string> { One = arg1, Two = arg2 })).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestVector2()
|
||||
{
|
||||
Prop.ForAll<Vector2>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestColor()
|
||||
{
|
||||
Prop.ForAll<Color>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestEnum()
|
||||
{
|
||||
Prop.ForAll<EnumTest>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestArray()
|
||||
{
|
||||
Prop.ForAll<Int32[]>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
Prop.ForAll<Boolean[]>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
Prop.ForAll<String[]>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestNullable()
|
||||
{
|
||||
Prop.ForAll<Int32?, String?>(SerializeDeserializeNullableTuple).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestBoolean()
|
||||
{
|
||||
Prop.ForAll<Boolean>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestByte()
|
||||
{
|
||||
Prop.ForAll<Byte>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestUInt16()
|
||||
{
|
||||
Prop.ForAll<UInt16>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestInt16()
|
||||
{
|
||||
Prop.ForAll<Int16>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestUInt32()
|
||||
{
|
||||
Prop.ForAll<UInt32>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestInt32()
|
||||
{
|
||||
Prop.ForAll<Int32>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestUInt64()
|
||||
{
|
||||
Prop.ForAll<UInt64>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestInt64()
|
||||
{
|
||||
Prop.ForAll<Int64>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSingle()
|
||||
{
|
||||
Prop.ForAll<Single>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestDouble()
|
||||
{
|
||||
Prop.ForAll<Double>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestString()
|
||||
{
|
||||
Prop.ForAll<String>(SerializeDeserialize).QuickCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
private enum EnumTest
|
||||
{
|
||||
One = 1,
|
||||
Two = 2,
|
||||
Three = 3,
|
||||
Thousand = 1000
|
||||
}
|
||||
|
||||
private struct TestStruct<T> : INetSerializableStruct
|
||||
{
|
||||
[NetworkSerialize]
|
||||
public T Value;
|
||||
|
||||
public T NotSerializedValue;
|
||||
|
||||
public T NotSerializedFunction() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private struct TupleNullableStruct<T, U> : INetSerializableStruct
|
||||
{
|
||||
[NetworkSerialize]
|
||||
public T? One;
|
||||
|
||||
[NetworkSerialize]
|
||||
public U? Two;
|
||||
|
||||
public (T, U) NotSerializedValue;
|
||||
public (T, U) NotSerializedFunction() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void SerializeDeserialize<T>(T arg) where T : notnull
|
||||
{
|
||||
ReadWriteMessage msg = new ReadWriteMessage();
|
||||
TestStruct<T> writeStruct = new TestStruct<T>
|
||||
{
|
||||
Value = arg
|
||||
};
|
||||
|
||||
((INetSerializableStruct)writeStruct).Write(msg);
|
||||
msg.BitPosition = 0;
|
||||
|
||||
TestStruct<T> readStruct = INetSerializableStruct.Read<TestStruct<T>>(msg);
|
||||
|
||||
readStruct.Should().BeEquivalentTo(writeStruct, options => options.ComparingByMembers<TestStruct<T>>());
|
||||
}
|
||||
|
||||
private static void SerializeDeserializeNullableTuple<T, U>(T arg1, U arg2)
|
||||
{
|
||||
ReadWriteMessage msg = new ReadWriteMessage();
|
||||
TupleNullableStruct<T, U> writeStruct = new TupleNullableStruct<T, U>
|
||||
{
|
||||
One = arg1,
|
||||
Two = arg2
|
||||
};
|
||||
|
||||
((INetSerializableStruct)writeStruct).Write(msg);
|
||||
msg.BitPosition = 0;
|
||||
|
||||
TupleNullableStruct<T, U> readStruct = INetSerializableStruct.Read<TupleNullableStruct<T, U>>(msg);
|
||||
|
||||
readStruct.Should().BeEquivalentTo(writeStruct, options => options.ComparingByMembers<TupleNullableStruct<T, U>>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<RootNamespace>LinuxTest</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.5.1" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BarotraumaClient\LinuxClient.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="TestExample.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<RootNamespace>MacTest</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.5.1" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BarotraumaClient\MacClient.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="TestExample.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma;
|
||||
using FluentAssertions;
|
||||
using FsCheck;
|
||||
using FsCheck.Xunit;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace TestProject
|
||||
{
|
||||
public class TestExample
|
||||
{
|
||||
// By default FsCheck has generators for basic types like floats ints and strings
|
||||
// Anything custom like Rectangle or Vector2 requires writing a custom generator for it
|
||||
private class CustomExampleGenerators
|
||||
{
|
||||
// We override the float generator to exclude NaNs and infinites
|
||||
public static Arbitrary<float> FloatGeneratorOverride() => Arb.Default.Float32().Generator.Where(MathUtils.IsValid).ToArbitrary();
|
||||
|
||||
// We override the String generator to exclude null and empty strings
|
||||
public static Arbitrary<string> StringGeneratorOverride() => Arb.Default.String().Generator.Where(s => !string.IsNullOrWhiteSpace(s)).ToArbitrary();
|
||||
|
||||
// Generator for the Rectangle type
|
||||
public static Arbitrary<Rectangle> RectangleGenerator()
|
||||
{
|
||||
return Arb.From(from int x in Arb.Generate<int>()
|
||||
from int y in Arb.Generate<int>()
|
||||
from int w in Arb.Generate<int>().Where(i => i > 0)
|
||||
from int h in Arb.Generate<int>().Where(i => i > 0)
|
||||
select new Rectangle(x, y, w, h));
|
||||
}
|
||||
}
|
||||
|
||||
// Used to output text into the test output
|
||||
private readonly ITestOutputHelper testOutputHelper;
|
||||
|
||||
public TestExample(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
this.testOutputHelper = testOutputHelper;
|
||||
Arb.Register<CustomExampleGenerators>(); // Register our custom generators
|
||||
}
|
||||
|
||||
[Fact] // Create a public function and add the [Fact] attribute on it to make a test function
|
||||
public void TestXORAlgorithm()
|
||||
{
|
||||
Prop.ForAll<string, string>((text, key) => // generates a pair of random strings
|
||||
{
|
||||
string encrypted = XOREncryptDecrypt(text, key);
|
||||
string decrypted = XOREncryptDecrypt(encrypted, key);
|
||||
|
||||
decrypted.Should().BeEquivalentTo(text); // FluentAssertions provides clear and verbose assertions with the Should() method
|
||||
}).VerboseCheckThrowOnFailure(testOutputHelper);
|
||||
// VerboseCheck performs 100 tests and outputs the generated values into the test output
|
||||
// ThrowOnFailure will additionally throw an exception if any of the functions fail which will make the test fail
|
||||
|
||||
// We will see that this fails the test with the following exception:
|
||||
|
||||
/*
|
||||
* System.Exception
|
||||
* Falsifiable, after 1 test (0 shrinks) (StdGen (2118948508,297004609)):
|
||||
* Original:
|
||||
* ("Jl", "m")
|
||||
* with exception:
|
||||
* Xunit.Sdk.XunitException: Expected decrypted to be equivalent to "Jl" with a length of 2, but "948492" has a length of 6, differs near "948" (index 0).
|
||||
*/
|
||||
|
||||
// We can see that the reason it is failing is because the original text was "Jl" but when encrypted and decrypted the string becomes "948492"
|
||||
// This is of course because we are not casting the XOR'd value to a char and instead appending the integer to the string builder
|
||||
}
|
||||
|
||||
// Erroneous XOR encryption algorithm
|
||||
private static string XOREncryptDecrypt(string text, string key)
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
result.Append(text[i] ^ (uint)key[i % key.Length]);
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private class ExampleEntity : ISerializableEntity
|
||||
{
|
||||
[Serialize(0.0f, IsPropertySaveable.Yes)]
|
||||
public float ExampleValue { get; set; }
|
||||
|
||||
public string Name => nameof(ExampleEntity);
|
||||
public Dictionary<Identifier, SerializableProperty> SerializableProperties { get; }
|
||||
|
||||
public ExampleEntity()
|
||||
{
|
||||
SerializableProperties = SerializableProperty.GetProperties(this);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestPropertyConditionalEqualsOperator()
|
||||
{
|
||||
// Test if the PropertyConditional equals operator is working correctly
|
||||
Prop.ForAll<float>(value =>
|
||||
{
|
||||
XAttribute xmlAttribute = new XAttribute("examplevalue", $"equals {value}");
|
||||
|
||||
PropertyConditional conditional = new PropertyConditional(xmlAttribute);
|
||||
|
||||
ExampleEntity entity = new ExampleEntity
|
||||
{
|
||||
ExampleValue = value
|
||||
};
|
||||
|
||||
conditional.Matches(entity).Should().BeTrue();
|
||||
}).VerboseCheckThrowOnFailure(testOutputHelper); // Remember to pass testOutputHelper so we actually get output
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Barotrauma;
|
||||
using FsCheck;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace TestProject
|
||||
{
|
||||
public static class TestProject
|
||||
{
|
||||
public class CustomGenerators
|
||||
{
|
||||
public static Arbitrary<Vector2> Vector2Generator()
|
||||
{
|
||||
return Arb.From(from int x in Arb.Generate<int>()
|
||||
from int y in Arb.Generate<int>()
|
||||
select new Vector2(x, y));
|
||||
}
|
||||
|
||||
public static Arbitrary<Color> ColorGenerator()
|
||||
{
|
||||
return Arb.From(from int r in Gen.Choose(0, 255)
|
||||
from int g in Gen.Choose(0, 255)
|
||||
from int b in Gen.Choose(0, 255)
|
||||
select new Color(r, g, b));
|
||||
}
|
||||
|
||||
public static Arbitrary<Option<T>> OptionalGenerator<T>()
|
||||
{
|
||||
return Arb.From(from T x in Arb.Generate<T>()
|
||||
from bool isNone in Arb.Generate<bool>()
|
||||
select x is null || isNone ? Option<T>.None() : Option<T>.Some(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<RootNamespace>WindowsTest</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.5.1" />
|
||||
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BarotraumaClient\WindowsClient.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="TestExample.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user