More work

This commit is contained in:
MSWS
2024-09-04 19:12:06 -07:00
parent fc6c53e4eb
commit 432304e868
34 changed files with 262 additions and 365 deletions

View File

@@ -20,6 +20,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CS2", "CS2", "{AC07CD29-5C9
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands", "Commands\Commands.csproj", "{C7DF1D47-8D2B-4651-98AB-AEEBE5860ECA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stats", "GangsImpl\Stats\Stats.csproj", "{BA8D993B-754E-4BB4-B103-482A4F779404}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -58,6 +60,10 @@ Global
{C7DF1D47-8D2B-4651-98AB-AEEBE5860ECA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C7DF1D47-8D2B-4651-98AB-AEEBE5860ECA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C7DF1D47-8D2B-4651-98AB-AEEBE5860ECA}.Release|Any CPU.Build.0 = Release|Any CPU
{BA8D993B-754E-4BB4-B103-482A4F779404}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA8D993B-754E-4BB4-B103-482A4F779404}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA8D993B-754E-4BB4-B103-482A4F779404}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA8D993B-754E-4BB4-B103-482A4F779404}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{1899055E-62B8-4907-85A2-DFE22531729E} = {3AB7703F-880F-4A41-96EE-B891FA888C65}
@@ -66,5 +72,6 @@ Global
{140E1706-30E8-4440-AAA0-56E8DD32F054} = {3AB7703F-880F-4A41-96EE-B891FA888C65}
{3EA38296-9022-4874-8309-872388D884DE} = {AC07CD29-5C9D-4AD1-99C7-01DABAB8D0EC}
{C7DF1D47-8D2B-4651-98AB-AEEBE5860ECA} = {AC07CD29-5C9D-4AD1-99C7-01DABAB8D0EC}
{BA8D993B-754E-4BB4-B103-482A4F779404} = {3AB7703F-880F-4A41-96EE-B891FA888C65}
EndGlobalSection
EndGlobal

View File

@@ -37,70 +37,6 @@ public interface IGang : IEqualityComparer<IGang>, IEquatable<IGang>,
=> Members.First(m => m.Value.Perms.HasFlag(IGangRank.Permissions.OWNER))
.Key;
/// <summary>
/// The amount of currency the gang has in its bank.
/// </summary>
int? Bank {
get {
var stat = GetStat("gang_bank") as IStat<int>;
return stat?.Value;
}
set {
ArgumentNullException.ThrowIfNull(value);
if (GetStat("gang_bank") is IStat<int> stat) stat.Value = value.Value;
}
}
/// <summary>
/// The set of perks the gang has.
/// </summary>
ISet<IStat> Perks { get; }
/// <summary>
/// The set of statistics the gang has.
/// </summary>
ISet<IStat> Stats { get; }
/// <summary>
/// The gang's capacity. Underlying implementation
/// should be a perk with the id "gang_capacity".
/// </summary>
/// <exception cref="ArgumentNullException"></exception>
int? GangCapacity {
get {
var perk = GetPerk("gang_capacity") as IGangStat<int>;
return perk?.Value;
}
set {
ArgumentNullException.ThrowIfNull(value);
if (GetPerk("gang_capacity") is IGangStat<int> perk)
perk.Value = value.Value;
}
}
/// <summary>
/// The gang's "message of the day".
/// Underlying implementation should be a perk with the id "gang_motd".
/// </summary>
/// <exception cref="ArgumentNullException"></exception>
string? MOTD {
get {
var perk = GetPerk("gang_motd") as IGangStat<string>;
return perk?.Value;
}
set {
if (value == null)
throw new ArgumentNullException(nameof(value),
"To un-set MOTD, remove the perk from the gang.");
if (GetPerk("gang_motd") is IGangStat<string> perk) perk.Value = value;
}
}
IEnumerator IEnumerable.GetEnumerator() {
return Members.Keys.GetEnumerator();
}
@@ -122,12 +58,4 @@ public interface IGang : IEqualityComparer<IGang>, IEquatable<IGang>,
if (other is null) return false;
return GangId == other.GangId;
}
IStat? GetPerk(string perkId) {
return Perks.FirstOrDefault(p => p.StatId.Equals(perkId));
}
IStat? GetStat(string statId) {
return Stats.FirstOrDefault(s => s.StatId.Equals(statId));
}
}

View File

@@ -27,39 +27,4 @@ public interface IGangPlayer {
/// The rank the player has in the gang (if in one).
/// </summary>
IGangRank? Rank { get; }
/// <summary>
/// The last time the player was seen by the plugin.
/// </summary>
DateTime? LastSeen {
get {
var stat = GetStat("gang_native_lastseen") as IStat<DateTime>;
return stat?.Value;
}
set {
if (GetStat("gang_native_lastseen") is IStat<DateTime?> stat)
stat.Value = value;
}
}
ISet<IStat> Stats { get; }
ISet<IStat> Perks { get; }
int? Balance {
get {
var stat = GetStat("gang_native_balance") as IStat<int>;
return stat?.Value;
}
set {
ArgumentNullException.ThrowIfNull(value);
if (GetStat("gang_native_balance") is IStat<int> stat)
stat.Value = value.Value;
}
}
IStat? GetStat(string statId) {
return Stats.FirstOrDefault(stat => stat.StatId == statId);
}
}

View File

@@ -1,3 +0,0 @@
namespace GangsAPI.Data.Stat;
public interface IGangStat<T> : IStat<T> { }

View File

@@ -1,3 +0,0 @@
namespace GangsAPI.Data.Stat;
public interface IPlayerStat<T> : IStat<T> { }

View File

@@ -3,7 +3,7 @@
/// <summary>
/// Represents a numerical statistic.
/// </summary>
public interface IStat : IEqualityComparer<IStat>, IEquatable<IStat> {
public interface IStat : IEquatable<IStat> {
/// <summary>
/// The unique identifier of the statistic.
/// </summary>
@@ -19,15 +19,6 @@ public interface IStat : IEqualityComparer<IStat>, IEquatable<IStat> {
/// </summary>
string? Description { get; }
bool IEqualityComparer<IStat>.Equals(IStat? x, IStat? y) {
if (x is null || y is null) return false;
return x.StatId == y.StatId;
}
int IEqualityComparer<IStat>.GetHashCode(IStat obj) {
return obj.StatId.GetHashCode();
}
bool IEquatable<IStat>.Equals(IStat? other) {
if (other is null) return false;
return StatId == other.StatId;

View File

@@ -5,10 +5,15 @@ using GangsAPI.Data.Stat;
namespace GangsAPI.Services;
public interface IGangStatManager : ICacher {
Task<IGangStat<V>?> GetForGang<V>(int key, string id);
Task<IStat<V>?> GetForGang<V>(int key, string id);
Task<IStat?> GetForGang(int key, string id);
Task<bool> PushToGang<V>(int gangId, string id, V value);
Task<IGangStat<V>?> GetForGang<V>(IGang gang, string id) {
Task<IStat?> GetForGang(IGang gang, string id) {
return GetForGang(gang.GangId, id);
}
Task<IStat<V>?> GetForGang<V>(IGang gang, string id) {
return GetForGang<V>(gang.GangId, id);
}
@@ -16,10 +21,6 @@ public interface IGangStatManager : ICacher {
return PushToGang(gang.GangId, id, value);
}
Task<IGangStat<V>?> GetForGang<V>(IGang gang, IStat stat, V value) {
return GetForGang<V>(gang, stat.StatId);
}
Task<bool> PushToGang<V>(IGang gang, IStat stat, V value) {
return PushToGang(gang, stat.StatId, value);
}
@@ -32,15 +33,15 @@ public interface IGangStatManager : ICacher {
return PushToGang(gang, stat.StatId, stat.Value);
}
Task<IGangStat<V>?> GetForGang<V>(int key, IStat stat, V value) {
return GetForGang<V>(key, stat.StatId);
}
Task<bool> PushToGang<V>(int gangId, IStat stat, V value) {
return PushToGang(gangId, stat.StatId, value);
}
Task<IGangStat<V>?> GetForGang<V>(IGang gang, IStat stat) {
Task<IStat?> GetForGang(IGang gang, IStat stat) {
return GetForGang(gang, stat.StatId);
}
Task<IStat<V>?> GetForGang<V>(IGang gang, IStat<V> stat) {
return GetForGang<V>(gang, stat.StatId);
}
}

View File

@@ -4,9 +4,9 @@ using GangsAPI.Data.Stat;
namespace GangsAPI.Services;
public interface IPlayerStatManager : IPluginBehavior, ICacher {
Task<IPlayerStat<V>?> GetForPlayer<V>(ulong key, string statId);
Task<IStat<V>?> GetForPlayer<V>(ulong key, string statId);
Task<bool> PushToPlayer<V>(ulong key, IPlayerStat<V> value) {
Task<bool> PushToPlayer<V>(ulong key, IStat<V> value) {
return PushToPlayer(key, value.StatId, value.Value);
}

View File

@@ -19,7 +19,7 @@ public interface IStatManager : IPluginBehavior, ICacher {
/// <param name="id"></param>
/// <returns></returns>
Task<IStat?> GetStat(string id);
/// <summary>
/// Creates a statistic with the manager, but does not register it.
/// If the statistic already exists with the same ID,

View File

@@ -1,5 +1,4 @@
using GangsAPI.Data.Gang;
using GangsAPI.Data.Stat;
using GangsAPI.Permissions;
using Mock;
@@ -10,19 +9,15 @@ namespace GenericDB;
/// </summary>
public class DBGang : MockGang {
public DBGang(int id, string name, ulong owner,
IDictionary<ulong, IGangRank> members, ISet<IGangRank> ranks,
ISet<IStat> perks, ISet<IStat> stats) : base(id, name, owner) {
IDictionary<ulong, IGangRank> members, ISet<IGangRank> ranks) : base(id,
name, owner) {
Members = members;
Ranks = ranks;
Perks = perks;
Stats = stats;
}
public DBGang(IGang gang) : base(gang.GangId, gang.Name, gang.Owner) {
Members = gang.Members;
Ranks = gang.Ranks;
Perks = gang.Perks;
Stats = gang.Stats;
}
public DBGang(int id, string name, ulong owner) : base(id, name, owner) { }

View File

@@ -1,10 +0,0 @@
using GangsAPI.Data.Stat;
namespace Mock;
public class MockBankStat : IGangStat<int> {
public string StatId => "gang_bank";
public string Name => "Mock Bank";
public string? Description => "The balance of the gang's bank.";
public int Value { get; set; } = 0;
}

View File

@@ -10,12 +10,20 @@ public class MockInstanceStatManager(IStatManager mgr)
private readonly Dictionary<ulong, Dictionary<string, IStat>>
playerStats = [];
public Task<IGangStat<V>?> GetForGang<V>(int key, string id) {
public Task<IStat<V>?> GetForGang<V>(int key, string id) {
if (!gangStats.TryGetValue(key, out var gangStatMap))
return Task.FromResult<IGangStat<V>?>(null);
return Task.FromResult<IStat<V>?>(null);
if (!gangStatMap.TryGetValue(id, out var result))
return Task.FromResult<IGangStat<V>?>(null);
return Task.FromResult(result as IGangStat<V>);
return Task.FromResult<IStat<V>?>(null);
return Task.FromResult(result as IStat<V>);
}
public Task<IStat?> GetForGang(int key, string id) {
if (!gangStats.TryGetValue(key, out var gangStatMap))
return Task.FromResult<IStat?>(null);
if (!gangStatMap.TryGetValue(id, out var result))
return Task.FromResult<IStat?>(null);
return Task.FromResult(result)!;
}
public async Task<bool> PushToGang<V>(int gangId, string id, V value) {
@@ -23,16 +31,16 @@ public class MockInstanceStatManager(IStatManager mgr)
gangStats[gangId] = gangStatMap = new Dictionary<string, IStat>();
var stat = await mgr.GetStat(id);
if (stat == null) return false;
gangStatMap[id] = new MockGangStat<V>(stat, value);
gangStatMap[id] = new MockStat<V>(stat, value);
return true;
}
public Task<IPlayerStat<V>?> GetForPlayer<V>(ulong key, string id) {
public Task<IStat<V>?> GetForPlayer<V>(ulong key, string id) {
if (!playerStats.TryGetValue(key, out var playerStatMap))
return Task.FromResult<IPlayerStat<V>?>(null);
return Task.FromResult<IStat<V>?>(null);
if (!playerStatMap.TryGetValue(id, out var result))
return Task.FromResult<IPlayerStat<V>?>(null);
return Task.FromResult(result as IPlayerStat<V>);
return Task.FromResult<IStat<V>?>(null);
return Task.FromResult(result as IStat<V>);
}
public async Task<bool> PushToPlayer<V>(ulong key, string id, V value) {
@@ -40,7 +48,7 @@ public class MockInstanceStatManager(IStatManager mgr)
playerStats[key] = playerStatMap = new Dictionary<string, IStat>();
var stat = await mgr.GetStat(id);
if (stat == null) return false;
playerStatMap[id] = new MockPlayerStat<V>(stat, value);
playerStatMap[id] = new MockStat<V>(stat, value);
return true;
}

View File

@@ -2,34 +2,37 @@ using GangsAPI.Data.Stat;
namespace Mock;
public class MockStat(string statId, string name, string? desc = null) : IStat {
public class MockStat(string statId, string name, string? desc = null)
: IStat, IEquatable<MockStat> {
public string StatId { get; } = statId;
public string Name { get; } = name;
public string? Description { get; } = desc;
public bool Equals(MockStat? other) {
return other is not null && ((IStat)this).Equals(other);
}
public override bool Equals(object? obj) { return Equals(obj as MockStat); }
public override int GetHashCode() { return HashCode.Combine(StatId); }
}
public class MockStat<KType, VType>(string statId, string name, string? desc,
KType key, VType value) : MockStat(statId, name, desc) {
public MockStat(IStat b, KType key, VType value) : this(b.StatId, b.Name,
b.Description, key, value) { }
public KType Key { get; init; } = key;
public VType Value { get; set; } = value;
}
public class MockPlayerStat<VType>(string statId, string name, string? desc,
VType value) : MockStat(statId, name, desc), IPlayerStat<VType> {
public MockPlayerStat(IStat b, VType value) : this(b.StatId, b.Name,
b.Description, value) { }
public ulong Key { get; init; }
public VType Value { get; set; } = value;
}
public class MockGangStat<T>(string statId, string name, string? desc, T value)
: MockStat(statId, name, desc), IGangStat<T> {
public MockGangStat(IStat b, T value) : this(b.StatId, b.Name, b.Description,
public class MockStat<VType>(string statId, string name, string? desc,
VType value) : MockStat(statId, name, desc), IEquatable<MockStat<VType>> {
public MockStat(IStat b, VType value) : this(b.StatId, b.Name, b.Description,
value) { }
public T Value { get; set; } = value;
public VType Value { get; set; } = value;
public bool Equals(MockStat<VType>? other) {
return other is not null && base.Equals(other);
}
public override bool Equals(object? obj) {
return Equals(obj as MockStat<VType>);
}
public override int GetHashCode() {
return HashCode.Combine(base.GetHashCode());
}
}

View File

@@ -0,0 +1,10 @@
using GangsAPI.Data.Stat;
namespace Stats;
public class GangBankStat : IStat<int> {
public string StatId => "gang_native_bank";
public string Name => "Gang Bank";
public string? Description => "The amount of money in the gang's bank.";
public int Value { get; set; } = 0;
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\GangsAPI\GangsAPI.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,7 @@
using GangsAPI.Data.Command;
using GangsAPI.Services.Commands;
namespace GangsTest.Commands.CommandLogic;
namespace GangsTest.Commands;
public class LogicTests : ManagerTests.ManagerTests {
[Theory]

View File

@@ -2,7 +2,7 @@
using GangsAPI.Data.Command;
using GangsAPI.Services.Commands;
namespace GangsTest.Commands.CommandPerms;
namespace GangsTest.Commands;
public class PermissionTests : ManagerTests.ManagerTests {
[Theory]

View File

@@ -1,118 +0,0 @@
using GangsAPI.Data.Stat;
using GangsAPI.Services;
using GangsTest.GangTests;
using Mock;
namespace GangsTest.GangBankTests;
public class GangBankTest {
private readonly IStat bankStat = new MockBankStat();
private readonly IGangManager gangManager;
private readonly IGangStatManager gangStatManager;
private readonly IStatManager statManager;
public GangBankTest(IGangManager gangManager, IStatManager statManager,
IGangStatManager gangStatManager) {
this.gangManager = gangManager;
this.statManager = statManager;
this.gangStatManager = gangStatManager;
Assert.True(
this.statManager.RegisterStat(bankStat).GetAwaiter().GetResult());
Assert.NotNull(this.statManager.GetStat(bankStat.StatId)
.GetAwaiter()
.GetResult());
}
[Fact]
public async Task GangBank_ZeroBalance() {
var gang = await GangTestUtil.CreateGang(gangManager);
Assert.NotNull(gang);
Assert.Null(gang.Bank);
gang.Stats.Add(bankStat);
Assert.Equal(0, gang.Bank);
Assert.True(await gangManager.UpdateGang(gang));
gang = await gangManager.GetGang(gang.GangId);
Assert.NotNull(gang);
Assert.Null(gang.Bank);
}
[Fact]
public async Task GangBank_Deposit() {
var gang = await GangTestUtil.CreateGang(gangManager);
Assert.NotNull(gang);
gang.Stats.Add(bankStat);
Assert.Equal(0, gang.Bank);
var stat = gang.GetStat(bankStat.StatId);
Assert.Same(stat, bankStat);
var bank = stat as IGangStat<int>;
Assert.NotNull(bank);
Assert.Equal(0, bank.Value);
bank.Value += 1;
Assert.NotEmpty(await statManager.GetStats());
Assert.True(await gangStatManager.PushToGang(gang, bank),
"Failed to push bank value to gang");
gang = await gangManager.GetGang(gang.GangId);
Assert.NotNull(gang);
bank = await gangStatManager.GetForGang<int>(gang, bank);
Assert.NotNull(bank);
Assert.Equal(1, bank.Value);
}
[Theory]
[InlineData(50, 25)]
[InlineData(5, 25)]
[InlineData(-5, 25)]
[InlineData(-5, -25)]
[InlineData(int.MaxValue, int.MinValue)]
[InlineData(int.MinValue, int.MaxValue)]
[InlineData(int.MaxValue, int.MaxValue)]
[InlineData(int.MinValue, int.MinValue)]
public async Task GangBank_Withdraw(int initial, int withdraw) {
var gang = await GangTestUtil.CreateGang(gangManager);
Assert.NotNull(gang);
Assert.True(await gangStatManager.PushToGang(gang, bankStat, initial));
var stat = await gangStatManager.GetForGang<int>(gang, bankStat);
Assert.NotNull(stat);
Assert.Equal(initial, stat.Value);
stat.Value -= withdraw;
Assert.True(await gangStatManager.PushToGang(gang, stat));
stat = await gangStatManager.GetForGang<int>(gang, bankStat);
Assert.NotNull(stat);
Assert.Equal(initial - withdraw, stat.Value);
}
[Theory]
[InlineData(50, 25)]
[InlineData(5, 25)]
[InlineData(-5, 25)]
[InlineData(-5, -25)]
[InlineData(int.MaxValue, int.MinValue)]
[InlineData(int.MinValue, int.MaxValue)]
[InlineData(int.MaxValue, int.MaxValue)]
[InlineData(int.MinValue, int.MinValue)]
public async Task
GangBank_Withdraw_Indirect_Alias(int initial, int withdraw) {
var gang = await GangTestUtil.CreateGang(gangManager);
Assert.NotNull(gang);
Assert.True(await gangStatManager.PushToGang(gang, bankStat, initial));
var stat = await gangStatManager.GetForGang<int>(gang, bankStat);
Assert.NotNull(stat);
Assert.Equal(initial, stat.Value);
gang.Stats.Add(stat);
gang.Bank -= withdraw;
Assert.True(await gangStatManager.PushToGang(gang, stat));
stat = await gangStatManager.GetForGang<int>(gang, bankStat);
Assert.NotNull(stat);
Assert.Equal(initial - withdraw, stat.Value);
Assert.Equal(initial - withdraw, gang.Bank);
}
}

View File

@@ -41,44 +41,6 @@ public class GangCreationTests(IPlayerManager playerMgr) {
Assert.NotSame(dummy, clone);
Assert.NotSame(dummy.Members, clone.Members);
Assert.NotSame(dummy.Ranks, clone.Ranks);
Assert.NotSame(dummy.Perks, clone.Perks);
Assert.NotSame(dummy.Stats, clone.Stats);
}
[Theory]
[ClassData(typeof(GangManagerData))]
public async Task Gang_Clone_WithPerks(IGangManager mgr) {
var dummy = await mgr.CreateGang("foobar", 0);
Assert.NotNull(dummy);
dummy.Perks.Add(new MockStat("test_perk", "Test Perk"));
var clone = dummy.Clone() as IGang;
Assert.NotNull(clone);
Assert.Equivalent(dummy, clone, true);
Assert.NotSame(dummy, clone);
Assert.NotSame(dummy.Members, clone.Members);
Assert.NotSame(dummy.Ranks, clone.Ranks);
Assert.NotSame(dummy.Perks, clone.Perks);
Assert.NotSame(dummy.Stats, clone.Stats);
}
[Theory]
[ClassData(typeof(GangManagerData))]
public async Task Gang_Clone_WithStats(IGangManager mgr) {
var dummy = await mgr.CreateGang("foobar", 0);
Assert.NotNull(dummy);
dummy.Stats.Add(new MockStat("test_stats", "Test Stat"));
var clone = dummy.Clone() as IGang;
Assert.NotNull(clone);
Assert.Equivalent(dummy, clone, true);
Assert.NotSame(dummy, clone);
Assert.NotSame(dummy.Members, clone.Members);
Assert.NotSame(dummy.Ranks, clone.Ranks);
Assert.NotSame(dummy.Perks, clone.Perks);
Assert.NotSame(dummy.Stats, clone.Stats);
}
[Theory]

View File

@@ -20,22 +20,6 @@ public class GangFieldTests {
Assert.Single(dummy.Members);
}
[Theory]
[ClassData(typeof(GangManagerData))]
public async Task Gang_Fields_Perks(IGangManager mgr) {
var dummy = await GangTestUtil.CreateGang(mgr);
Assert.NotNull(dummy);
Assert.NotNull(dummy.Perks);
}
[Theory]
[ClassData(typeof(GangManagerData))]
public async Task Gang_Fields_Stats(IGangManager mgr) {
var dummy = await GangTestUtil.CreateGang(mgr);
Assert.NotNull(dummy);
Assert.NotNull(dummy.Stats);
}
[Theory]
[ClassData(typeof(GangManagerData))]
public async Task Gang_Fields_Iteration(IGangManager mgr) {

View File

@@ -32,7 +32,13 @@
<ProjectReference Include="..\GangsImpl\Mock\Mock.csproj"/>
<ProjectReference Include="..\GangsImpl\SQLite\SQLite.csproj"/>
<ProjectReference Include="..\GangsImpl\SQL\SQL.csproj"/>
<ProjectReference Include="..\GangsImpl\Stats\Stats.csproj" />
<ProjectReference Include="..\Gangs\Gangs.csproj"/>
</ItemGroup>
<ItemGroup>
<Folder Include="StatTests\InstanceManageTests\GangManager\" />
<Folder Include="StatTests\InstanceManageTests\PlayerManager\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,56 @@
using GangsAPI.Data.Gang;
using GangsAPI.Data.Stat;
using GangsAPI.Services;
namespace GangsTest.StatTests.InstanceManageTests;
public class InstanceGangTests(IGangManager gangMgr) {
private class TestStatInstance : IStat<int> {
public string StatId => "test_stat";
public string Name => "Test Stat";
public string? Description => "A test stat.";
public int Value { get; set; } = 32;
}
private IGang testGang =
gangMgr.CreateGang("Test Gang", (ulong)new Random().NextInt64())
.GetAwaiter()
.GetResult() ?? throw new InvalidOperationException();
private readonly IStat<int> testStat = new TestStatInstance();
[Theory]
[ClassData(typeof(InstanceManageData))]
public async Task Instance_Register(IStatManager stat,
IGangStatManager manager) {
Assert.True(await stat.RegisterStat(testStat));
Assert.True(await manager.PushToGang(testGang, testStat));
}
[Theory]
[ClassData(typeof(InstanceManageData))]
public async Task Instance_Register_Unregistered(IStatManager _,
IGangStatManager manager) {
Assert.False(await manager.PushToGang(testGang, testStat));
}
[Theory]
[ClassData(typeof(InstanceManageData))]
public async Task Instance_Fetch_Registered(IStatManager stat,
IGangStatManager manager) {
Assert.True(await stat.RegisterStat(testStat));
Assert.True(await manager.PushToGang(testGang, testStat));
var result = await manager.GetForGang(testGang, testStat);
Assert.NotNull(result);
Assert.Equal(testStat, result);
}
[Theory]
[ClassData(typeof(InstanceManageData))]
public async Task Instance_Fetch_Unregistered(IStatManager stat,
IGangStatManager manager) {
Assert.True(await stat.RegisterStat(testStat));
var result = await manager.GetForGang(testGang, testStat);
Assert.Null(result);
}
}

View File

@@ -0,0 +1,19 @@
using System.Collections;
using Mock;
namespace GangsTest.StatTests.InstanceManageTests;
public class InstanceManageData : IEnumerable<object[]> {
private object[][] behaviors;
public InstanceManageData() {
var inst = new MockStatManager();
behaviors = new object[][] { [inst, new MockInstanceStatManager(inst)] };
}
public IEnumerator<object[]> GetEnumerator() {
return behaviors.Select(behavior => behavior).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}

View File

@@ -0,0 +1,11 @@
using GangsAPI.Data.Stat;
namespace GangsTest.StatTests.InstanceTests;
public class InstanceFieldTests {
[Theory]
[ClassData(typeof(StatInstanceData))]
public void Instance_Id(IStat stat) {
Assert.Matches("^[a-z0-9_]+$", stat.StatId);
}
}

View File

@@ -0,0 +1,15 @@
using System.Collections;
using GangsAPI.Data.Stat;
using Stats;
namespace GangsTest.StatTests.InstanceTests;
public class StatInstanceData : IEnumerable<object[]> {
private readonly IStat[] stats = [new GangBankStat()];
public IEnumerator<object[]> GetEnumerator() {
return stats.Select(stat => (object[]) [stat]).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}

View File

@@ -1,6 +1,6 @@
using GangsAPI.Services;
namespace GangsTest.StatTests;
namespace GangsTest.StatTests.ManageTests;
public class MockStatManagerTests {
[Theory]

View File

@@ -4,7 +4,7 @@ using Mock;
using SQLImpl;
using SQLite;
namespace GangsTest.StatTests;
namespace GangsTest.StatTests.ManageTests;
public class StatManagerData : IEnumerable<object[]> {
private readonly IBehavior[] behaviors = [

View File

@@ -1,6 +1,6 @@
using GangsAPI.Services;
namespace GangsTest.StatTests;
namespace GangsTest.StatTests.ManageTests;
public class StatRegistrationTests {
[Theory]

View File

@@ -1,6 +1,6 @@
using GangsAPI.Services;
namespace GangsTest.StatTests;
namespace GangsTest.StatTests.ManageTests;
public class StatRetainTests {
[Theory]

View File

@@ -1,4 +1,5 @@
using GangsAPI.Services;
using GangsTest.StatTests.ManageTests;
namespace GangsTest.StatTests;

View File

@@ -1,4 +1,5 @@
using GangsAPI.Services;
using GangsTest.StatTests.ManageTests;
namespace GangsTest.StatTests;

View File

@@ -0,0 +1,47 @@
using GangsAPI.Services;
using GangsTest.StatTests.ManageTests;
using Mock;
namespace GangsTest.StatTests;
public class StatInstanceEqualityTests {
[Fact]
public void Stat_Equality_SameEverything() {
var foo1 = new MockStat<int>("foo", "bar", null, 0);
var foo2 = new MockStat<int>("foo", "bar", null, 0);
Assert.Equal(foo1, foo2);
Assert.StrictEqual(foo1, foo2);
}
[Fact]
public void Stat_Equality_DiffName() {
var foo1 = new MockStat<int>("foo", "foobar", null, 0);
var foo2 = new MockStat<int>("foo", "bar", null, 0);
Assert.Equal(foo1, foo2);
Assert.StrictEqual(foo1, foo2);
}
[Fact]
public void Stat_Equality_DiffDesc() {
var foo1 = new MockStat<int>("foo", "bar", null, 0);
var foo2 = new MockStat<int>("foo", "bar", "foobar", 0);
Assert.Equal(foo1, foo2);
Assert.StrictEqual(foo1, foo2);
}
[Fact]
public void Stat_Equality_DiffBoth() {
var foo1 = new MockStat<int>("foo", "barfoo", null, 0);
var foo2 = new MockStat<int>("foo", "bar", "foobar", 0);
Assert.Equal(foo1, foo2);
Assert.StrictEqual(foo1, foo2);
}
[Fact]
public void Stat_Equality_DiffIDs() {
var foo1 = new MockStat<int>("foo", "bar", null, 0);
var foo2 = new MockStat<int>("foobar", "bar", null, 0);
Assert.NotStrictEqual(foo1, foo2);
Assert.NotEqual(foo1, foo2);
}
}

View File

@@ -1,4 +1,5 @@
using GangsAPI.Services;
using GangsTest.StatTests.ManageTests;
namespace GangsTest.StatTests;

7
compose.yml Normal file
View File

@@ -0,0 +1,7 @@
services:
mariadb:
image: mariadb:latest
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: yes
MARIADB_DATABASE: gangs
network_mode: host