allow reports to be filed against anyone

fix rare issue with alias (maybe)
update some tests
This commit is contained in:
RaidMax 2019-06-24 11:01:34 -05:00
parent cb80def122
commit 253c7c8721
16 changed files with 336 additions and 229 deletions

View File

@ -32,7 +32,7 @@
<PropertyGroup> <PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection> <ServerGarbageCollection>true</ServerGarbageCollection>
<TieredCompilation>true</TieredCompilation> <TieredCompilation>true</TieredCompilation>
<AssemblyVersion>2.2.7.6</AssemblyVersion> <AssemblyVersion>2.2.7.7</AssemblyVersion>
<FileVersion>2.2.7.7</FileVersion> <FileVersion>2.2.7.7</FileVersion>
<LangVersion>7.1</LangVersion> <LangVersion>7.1</LangVersion>
</PropertyGroup> </PropertyGroup>

View File

@ -30,7 +30,9 @@ namespace IW4MAdmin.Application.IO
{ {
while (!_server.Manager.CancellationToken.IsCancellationRequested) while (!_server.Manager.CancellationToken.IsCancellationRequested)
{ {
#if !DEBUG
if (_server.IsInitialized) if (_server.IsInitialized)
#endif
{ {
try try
{ {

View File

@ -585,6 +585,13 @@ namespace IW4MAdmin
try try
{ {
#if DEBUG
if (Manager.GetApplicationSettings().Configuration().RConPollRate == int.MaxValue)
{
return true;
}
#endif
var polledClients = await PollPlayersAsync(); var polledClients = await PollPlayersAsync();
var waiterList = new List<GameEvent>(); var waiterList = new List<GameEvent>();
@ -766,7 +773,8 @@ namespace IW4MAdmin
if (version?.Value?.Length != 0) if (version?.Value?.Length != 0)
{ {
RconParser = Manager.AdditionalRConParsers.FirstOrDefault(_parser => _parser.Version == version.Value) ?? RconParser; var matchedRconParser = Manager.AdditionalRConParsers.FirstOrDefault(_parser => _parser.Version == version.Value);
RconParser.Configuration = matchedRconParser != null ? matchedRconParser.Configuration : RconParser.Configuration;
EventParser = Manager.AdditionalEventParsers.FirstOrDefault(_parser => _parser.Version == version.Value) ?? EventParser; EventParser = Manager.AdditionalEventParsers.FirstOrDefault(_parser => _parser.Version == version.Value) ?? EventParser;
Version = RconParser.Version; Version = RconParser.Version;
} }
@ -1011,11 +1019,9 @@ namespace IW4MAdmin
#endif #endif
} }
// this should link evading clients
if (isEvade) if (isEvade)
{ {
Logger.WriteInfo($"updating alias for banned client {targetClient}"); Logger.WriteInfo($"updating alias for banned client {targetClient}");
await Manager.GetClientService().UpdateAlias(targetClient);
} }
EFPenalty newPenalty = new EFPenalty() EFPenalty newPenalty = new EFPenalty()

View File

@ -1,6 +1,7 @@
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
@ -73,10 +74,12 @@ namespace IW4MAdmin.Application
// lets keep it simple and dispose of everything quickly as logging wont be that much (relatively) // lets keep it simple and dispose of everything quickly as logging wont be that much (relatively)
Console.WriteLine(LogLine); Console.WriteLine(LogLine);
File.AppendAllText(FileName, LogLine + Environment.NewLine); File.AppendAllText(FileName, LogLine + Environment.NewLine);
Debug.WriteLine(msg);
#else #else
if (type == LogType.Error || type == LogType.Verbose) if (type == LogType.Error || type == LogType.Verbose)
{
Console.WriteLine(LogLine); Console.WriteLine(LogLine);
//if (type != LogType.Debug) }
File.AppendAllText(FileName, $"{LogLine}{Environment.NewLine}"); File.AppendAllText(FileName, $"{LogLine}{Environment.NewLine}");
#endif #endif
} }

View File

@ -12,7 +12,11 @@ using static SharedLibraryCore.Server;
namespace IW4MAdmin.Application.RconParsers namespace IW4MAdmin.Application.RconParsers
{ {
#if DEBUG
public class BaseRConParser : IRConParser
#else
class BaseRConParser : IRConParser class BaseRConParser : IRConParser
#endif
{ {
public BaseRConParser() public BaseRConParser()
{ {
@ -52,7 +56,7 @@ namespace IW4MAdmin.Application.RconParsers
public IRConParserConfiguration Configuration { get; set; } public IRConParserConfiguration Configuration { get; set; }
public string Version { get; set; } = "CoD"; public virtual string Version { get; set; } = "CoD";
public Game GameName { get; set; } = Game.COD; public Game GameName { get; set; } = Game.COD;
public bool CanGenerateLogPath { get; set; } = true; public bool CanGenerateLogPath { get; set; } = true;
@ -89,7 +93,7 @@ namespace IW4MAdmin.Application.RconParsers
}; };
} }
public async Task<List<EFClient>> GetStatusAsync(Connection connection) public virtual async Task<List<EFClient>> GetStatusAsync(Connection connection)
{ {
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND_STATUS); string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND_STATUS);
return ClientsFromStatus(response); return ClientsFromStatus(response);

View File

@ -34,8 +34,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Plugins\Tests\Test
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IW4ScriptCommands", "Plugins\IW4ScriptCommands\IW4ScriptCommands.csproj", "{6C706CE5-A206-4E46-8712-F8C48D526091}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IW4ScriptCommands", "Plugins\IW4ScriptCommands\IW4ScriptCommands.csproj", "{6C706CE5-A206-4E46-8712-F8C48D526091}"
EndProject EndProject
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "DiscordWebhook", "DiscordWebhook\DiscordWebhook.pyproj", "{15A81D6E-7502-46CE-8530-0647A380B5F4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlugins", "{3F9ACC27-26DB-49FA-BCD2-50C54A49C9FA}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlugins", "{3F9ACC27-26DB-49FA-BCD2-50C54A49C9FA}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
Plugins\ScriptPlugins\ParserCoD4x.js = Plugins\ScriptPlugins\ParserCoD4x.js Plugins\ScriptPlugins\ParserCoD4x.js = Plugins\ScriptPlugins\ParserCoD4x.js
@ -309,18 +307,6 @@ Global
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x64.Build.0 = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x64.Build.0 = Release|Any CPU
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.ActiveCfg = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.ActiveCfg = Release|Any CPU
{6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.Build.0 = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x86.Build.0 = Release|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Debug|x86.ActiveCfg = Debug|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|Any CPU.ActiveCfg = Prerelease|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|Mixed Platforms.ActiveCfg = Release|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|x64.ActiveCfg = Release|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Prerelease|x86.ActiveCfg = Release|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|x64.ActiveCfg = Release|Any CPU
{15A81D6E-7502-46CE-8530-0647A380B5F4}.Release|x86.ActiveCfg = Release|Any CPU
{42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {42EFDA12-10D3-4C40-A210-9483520116BC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU

View File

@ -133,6 +133,8 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
var weightedSessionAverage = HitLocationCount.Where(_hit => _hit.Value.Count > 0) var weightedSessionAverage = HitLocationCount.Where(_hit => _hit.Value.Count > 0)
.Sum(_hit => _hit.Value.Offset * _hit.Value.Count) / totalSessionHits; .Sum(_hit => _hit.Value.Offset * _hit.Value.Count) / totalSessionHits;
AngleDifferenceAverage = weightedSessionAverage;
if (weightedSessionAverage > Thresholds.MaxOffset(totalSessionHits) && if (weightedSessionAverage > Thresholds.MaxOffset(totalSessionHits) &&
totalSessionHits > 40) totalSessionHits > 40)
{ {

View File

@ -2,11 +2,13 @@
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Commands; using SharedLibraryCore.Commands;
using SharedLibraryCore.Database.Models; using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Events;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Xunit; using Xunit;
namespace Tests namespace Tests
@ -14,12 +16,12 @@ namespace Tests
[Collection("ManagerCollection")] [Collection("ManagerCollection")]
public class ClientTests public class ClientTests
{ {
readonly ApplicationManager Manager; private readonly ApplicationManager _manager;
const int TestTimeout = 10000; const int TestTimeout = 10000;
public ClientTests(ManagerFixture fixture) public ClientTests(ManagerFixture fixture)
{ {
Manager = fixture.Manager; _manager = fixture.Manager;
} }
[Fact] [Fact]
@ -41,38 +43,122 @@ namespace Tests
} }
[Fact] [Fact]
public void WarnClientShouldSucceed() public void BanEvasionShouldLink()
{ {
while (!Manager.IsInitialized) var server = _manager.Servers[0];
var waiter = new ManualResetEventSlim();
_manager.GetApplicationSettings().Configuration().RConPollRate = 5000;
while (!server.IsInitialized)
{ {
Thread.Sleep(100); Thread.Sleep(100);
} }
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault(); var e = new GameEvent()
{
Type = GameEvent.EventType.PreConnect,
Owner = server,
Origin = new EFClient()
{
NetworkId = 1337,
ClientNumber = 0,
CurrentAlias = new EFAlias()
{
Name = "Ban Me",
IPAddress = 1337
}
}
};
Assert.False(client == null, "no client found to warn"); _manager.GetEventHandler().AddEvent(e);
e.OnProcessed.Wait();
var warnEvent = client.Warn("test warn", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer }); e = new GameEvent()
warnEvent.OnProcessed.Wait(); {
Type = GameEvent.EventType.PreConnect,
Owner = server,
Origin = new EFClient()
{
NetworkId = 1338,
ClientNumber = 1,
CurrentAlias = new EFAlias()
{
Name = "Ban Me",
IPAddress = null
}
}
};
//Assert.True((client.Warnings == 1 || _manager.GetEventHandler().AddEvent(e);
// warnEvent.Failed) && e.OnProcessed.Wait();
// Manager.GetPenaltyService().GetClientPenaltiesAsync(client.ClientId).Result.Count(p => p.Type == Penalty.PenaltyType.Warning) == 1,
// "warning did not get applied"); e = new GameEvent()
{
Type = GameEvent.EventType.Update,
Owner = server,
Origin = new EFClient()
{
NetworkId = 1338,
ClientNumber = 1,
CurrentAlias = new EFAlias()
{
Name = "Ban Me",
IPAddress = 1337
}
}
};
_manager.GetEventHandler().AddEvent(e);
e.OnProcessed.Wait();
}
[Fact]
public void WarnClientShouldSucceed()
{
var onJoined = new ManualResetEventSlim();
var server = _manager.Servers[0];
while (!server.IsInitialized)
{
Thread.Sleep(100);
}
_manager.OnServerEvent += (sender, eventArgs) =>
{
if (eventArgs.Event.Type == GameEvent.EventType.Connect)
{
onJoined.Set();
}
};
server.EmulateClientJoinLog();
onJoined.Wait();
var client = server.Clients[0];
var warnEvent = client.Warn("test warn", Utilities.IW4MAdminClient(server));
warnEvent.OnProcessed.Wait(5000);
Assert.False(warnEvent.Failed);
warnEvent = client.Warn("test warn", new EFClient() { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer }); warnEvent = client.Warn("test warn", new EFClient() { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
warnEvent.OnProcessed.Wait(); warnEvent.OnProcessed.Wait(5000);
Assert.True(warnEvent.FailReason == GameEvent.EventFailReason.Permission && Assert.True(warnEvent.FailReason == GameEvent.EventFailReason.Permission &&
client.Warnings == 1, "warning was applied without proper permissions"); client.Warnings == 1, "warning was applied without proper permissions");
// warn clear // warn clear
var warnClearEvent = client.WarnClear(new EFClient { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer }); var warnClearEvent = client.WarnClear(new EFClient { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
warnClearEvent.OnProcessed.Wait(5000);
Assert.True(warnClearEvent.FailReason == GameEvent.EventFailReason.Permission && Assert.True(warnClearEvent.FailReason == GameEvent.EventFailReason.Permission &&
client.Warnings == 1, "warning was removed without proper permissions"); client.Warnings == 1, "warning was removed without proper permissions");
warnClearEvent = client.WarnClear(new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer }); warnClearEvent = client.WarnClear(Utilities.IW4MAdminClient(server));
warnClearEvent.OnProcessed.Wait(5000);
Assert.True(!warnClearEvent.Failed && client.Warnings == 0, "warning was not cleared"); Assert.True(!warnClearEvent.Failed && client.Warnings == 0, "warning was not cleared");
} }
@ -80,12 +166,12 @@ namespace Tests
[Fact] [Fact]
public void ReportClientShouldSucceed() public void ReportClientShouldSucceed()
{ {
while (!Manager.IsInitialized) while (!_manager.IsInitialized)
{ {
Thread.Sleep(100); Thread.Sleep(100);
} }
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault(); var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to report"); Assert.False(client == null, "no client found to report");
// fail // fail
@ -127,12 +213,12 @@ namespace Tests
[Fact] [Fact]
public void FlagClientShouldSucceed() public void FlagClientShouldSucceed()
{ {
while (!Manager.IsInitialized) while (!_manager.IsInitialized)
{ {
Thread.Sleep(100); Thread.Sleep(100);
} }
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault(); var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to flag"); Assert.False(client == null, "no client found to flag");
var flagEvent = client.Flag("test flag", new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer }); var flagEvent = client.Flag("test flag", new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
@ -177,12 +263,12 @@ namespace Tests
[Fact] [Fact]
void KickClientShouldSucceed() void KickClientShouldSucceed()
{ {
while (!Manager.IsInitialized) while (!_manager.IsInitialized)
{ {
Thread.Sleep(100); Thread.Sleep(100);
} }
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault(); var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to kick"); Assert.False(client == null, "no client found to kick");
var kickEvent = client.Kick("test kick", new EFClient() { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer }); var kickEvent = client.Kick("test kick", new EFClient() { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
@ -193,18 +279,18 @@ namespace Tests
kickEvent = client.Kick("test kick", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer }); kickEvent = client.Kick("test kick", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
kickEvent.OnProcessed.Wait(); kickEvent.OnProcessed.Wait();
Assert.True(Manager.Servers.First().GetClientsAsList().FirstOrDefault(c => c.NetworkId == client.NetworkId) == null, "client was not kicked"); Assert.True(_manager.Servers.First().GetClientsAsList().FirstOrDefault(c => c.NetworkId == client.NetworkId) == null, "client was not kicked");
} }
[Fact] [Fact]
void TempBanClientShouldSucceed() void TempBanClientShouldSucceed()
{ {
while (!Manager.IsInitialized) while (!_manager.IsInitialized)
{ {
Thread.Sleep(100); Thread.Sleep(100);
} }
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault(); var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to tempban"); Assert.False(client == null, "no client found to tempban");
var tbCommand = new CTempBan(); var tbCommand = new CTempBan();
@ -217,19 +303,19 @@ namespace Tests
Owner = client.CurrentServer Owner = client.CurrentServer
}).Wait(); }).Wait();
Assert.True(Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.TempBan) == 1, Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.TempBan) == 1,
"tempban was not added"); "tempban was not added");
} }
[Fact] [Fact]
void BanUnbanClientShouldSucceed() void BanUnbanClientShouldSucceed()
{ {
while (!Manager.IsInitialized) while (!_manager.IsInitialized)
{ {
Thread.Sleep(100); Thread.Sleep(100);
} }
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault(); var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to ban"); Assert.False(client == null, "no client found to ban");
var banCommand = new CBan(); var banCommand = new CBan();
@ -242,7 +328,7 @@ namespace Tests
Owner = client.CurrentServer Owner = client.CurrentServer
}).Wait(); }).Wait();
Assert.True(Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 1, Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 1,
"ban was not added"); "ban was not added");
var unbanCommand = new CUnban(); var unbanCommand = new CUnban();
@ -255,7 +341,7 @@ namespace Tests
Owner = client.CurrentServer Owner = client.CurrentServer
}).Wait(); }).Wait();
Assert.True(Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 0, Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 0,
"ban was not removed"); "ban was not removed");
} }

View File

@ -16,9 +16,9 @@ namespace Tests
public ManagerFixture() public ManagerFixture()
{ {
File.WriteAllText("test_mp.log", "test_log_file"); string logFile = @"X:\IW4MAdmin\Plugins\Tests\bin\Debug\netcoreapp2.2\test_mp.log";
//IW4MAdmin.Application.Localization.Configure.Initialize("en-US"); File.WriteAllText(logFile, Environment.NewLine);
Manager = ApplicationManager.GetInstance(); Manager = ApplicationManager.GetInstance();
@ -31,18 +31,22 @@ namespace Tests
AutoMessages = new List<string>(), AutoMessages = new List<string>(),
IPAddress = "127.0.0.1", IPAddress = "127.0.0.1",
Password = "test", Password = "test",
Port = 28963, Port = 28960,
Rules = new List<string>(), Rules = new List<string>(),
ManualLogPath = "http://google.com" RConParserVersion = "test",
EventParserVersion = "IW4x (v0.6.0)",
ManualLogPath = logFile
} }
}, },
AutoMessages = new List<string>(), AutoMessages = new List<string>(),
GlobalRules = new List<string>(), GlobalRules = new List<string>(),
Maps = new List<MapConfiguration>(), Maps = new List<MapConfiguration>(),
RConPollRate = 10000 RConPollRate = int.MaxValue
}; };
Manager.ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("test"); Manager.ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("test");
Manager.ConfigHandler.Set(config); Manager.ConfigHandler.Set(config);
Manager.AdditionalRConParsers.Add(new TestRconParser());
Manager.Init().Wait(); Manager.Init().Wait();

View File

@ -1,7 +1,6 @@
using IW4MAdmin.Application; using IW4MAdmin.Application;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Database.Models; using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -33,162 +32,17 @@ namespace Tests
[Fact] [Fact]
public void AreCommandAliasesUnique() public void AreCommandAliasesUnique()
{ {
var mgr = Program.ServerManager; var mgr = Manager;
bool test = mgr.GetCommands().Count == mgr.GetCommands().Select(c => c.Alias).Distinct().Count(); bool test = mgr.GetCommands().Count == mgr.GetCommands().Select(c => c.Alias).Distinct().Count();
foreach (var duplicate in mgr.GetCommands().GroupBy(_cmd => _cmd.Alias).Where(_grp => _grp.Count() > 1).Select(_grp => new { Command = _grp.First().Name, Alias = _grp.Key }))
{
Debug.WriteLine($"{duplicate.Command}: {duplicate.Alias}");
}
Assert.True(test, "command aliases are not unique"); Assert.True(test, "command aliases are not unique");
} }
[Fact]
public void AddAndRemoveClientsViaJoinShouldSucceed()
{
var server = Manager.GetServers().First();
var waiters = new Queue<GameEvent>();
int clientStartIndex = 4;
int clientNum = 10;
for (int i = clientStartIndex; i < clientStartIndex + clientNum; i++)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Join,
Origin = new EFClient()
{
Name = $"Player{i}",
NetworkId = i,
ClientNumber = i - 1
},
Owner = server
};
server.Manager.GetEventHandler().AddEvent(e);
waiters.Enqueue(e);
}
while (waiters.Count > 0)
{
waiters.Dequeue().OnProcessed.Wait();
}
Assert.True(server.ClientNum == clientNum, $"client num does not match added client num [{server.ClientNum}:{clientNum}]");
for (int i = clientStartIndex; i < clientStartIndex + clientNum; i++)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Disconnect,
Origin = new EFClient()
{
Name = $"Player{i}",
NetworkId = i,
ClientNumber = i - 1
},
Owner = server
};
server.Manager.GetEventHandler().AddEvent(e);
waiters.Enqueue(e);
}
while (waiters.Count > 0)
{
waiters.Dequeue().OnProcessed.Wait();
}
Assert.True(server.ClientNum == 0, "there are still clients connected");
}
[Fact]
public void AddAndRemoveClientsViaRconShouldSucceed()
{
var server = Manager.GetServers().First();
var waiters = new Queue<GameEvent>();
int clientIndexStart = 1;
int clientNum = 8;
for (int i = clientIndexStart; i < clientNum + clientIndexStart; i++)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Connect,
Origin = new EFClient()
{
Name = $"Player{i}",
NetworkId = i,
ClientNumber = i - 1,
IPAddress = i,
Ping = 50,
CurrentServer = server
},
Owner = server,
};
Manager.GetEventHandler().AddEvent(e);
waiters.Enqueue(e);
}
while (waiters.Count > 0)
{
waiters.Dequeue().OnProcessed.Wait();
}
int actualClientNum = server.GetClientsAsList().Count(p => p.State == EFClient.ClientState.Connected);
Assert.True(actualClientNum == clientNum, $"client connected states don't match [{actualClientNum}:{clientNum}");
for (int i = clientIndexStart; i < clientNum + clientIndexStart; i++)
{
var e = new GameEvent()
{
Type = GameEvent.EventType.Disconnect,
Origin = new EFClient()
{
Name = $"Player{i}",
NetworkId = i,
ClientNumber = i - 1,
IPAddress = i,
Ping = 50,
CurrentServer = server
},
Owner = server,
};
Manager.GetEventHandler().AddEvent(e);
waiters.Enqueue(e);
}
while (waiters.Count > 0)
{
waiters.Dequeue().OnProcessed.Wait();
}
actualClientNum = server.ClientNum;
Assert.True(actualClientNum == 0, "there are clients still connected");
}
[Fact]
public void AddClientViaLog()
{
var resetEvent = new ManualResetEventSlim();
resetEvent.Reset();
Manager.OnServerEvent += (sender, eventArgs) =>
{
if (eventArgs.Event.Type == GameEvent.EventType.Join)
{
eventArgs.Event.OnProcessed.Wait();
Assert.True(false);
}
};
File.AppendAllText("test_mp.log", " 2:33 J;224b3d0bc64ab4f9;0;goober");
resetEvent.Wait(5000);
}
[Fact] [Fact]
public void PrintCommands() public void PrintCommands()
{ {

View File

@ -1,10 +1,113 @@
using System; using IW4MAdmin.Application;
using SharedLibraryCore;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text; using System.Text;
using System.Threading;
using Xunit;
namespace Tests namespace Tests
{ {
class ServerTests [Collection("ManagerCollection")]
public class ServerTests
{ {
private readonly ApplicationManager _manager;
public ServerTests(ManagerFixture fixture)
{
_manager = fixture.Manager;
}
[Fact]
public void AddAndRemoveClientViaLog()
{
var resetEvent = new ManualResetEventSlim();
var server = _manager.Servers[0];
var currentClientCount = server.ClientNum;
int eventsProcessed = 0;
_manager.OnServerEvent += (sender, eventArgs) =>
{
if (eventArgs.Event.Type == GameEvent.EventType.Connect)
{
eventArgs.Event.OnProcessed.Wait();
Assert.False(eventArgs.Event.Failed, "connect event was not processed");
Assert.True(server.ClientNum == currentClientCount + 1, "client count was not incremented");
eventsProcessed++;
resetEvent.Set();
}
if (eventArgs.Event.Type == GameEvent.EventType.Disconnect)
{
eventArgs.Event.OnProcessed.Wait();
Assert.False(eventArgs.Event.Failed, "disconnect event was not processed");
Assert.True(server.ClientNum == currentClientCount, "client count was not decremented");
eventsProcessed++;
resetEvent.Set();
}
};
server.EmulateClientJoinLog();
resetEvent.Wait(15000);
resetEvent.Reset();
Assert.Equal(1, eventsProcessed);
server.EmulateClientQuitLog();
resetEvent.Wait(15000);
Assert.Equal(2, eventsProcessed);
}
[Fact]
public void AddAndRemoveClientViaRcon()
{
var resetEvent = new ManualResetEventSlim();
var server = _manager.Servers[0];
var currentClientCount = server.ClientNum;
int eventsProcessed = 0;
_manager.GetApplicationSettings().Configuration().RConPollRate = 5000;
_manager.OnServerEvent += (sender, eventArgs) =>
{
if (eventArgs.Event.Type == GameEvent.EventType.Connect)
{
eventArgs.Event.OnProcessed.Wait();
Assert.False(eventArgs.Event.Failed, "connect event was not processed");
Assert.True(server.ClientNum == currentClientCount + 1, "client count was not incremented");
eventsProcessed++;
resetEvent.Set();
}
if (eventArgs.Event.Type == GameEvent.EventType.Disconnect)
{
eventArgs.Event.OnProcessed.Wait();
Assert.False(eventArgs.Event.Failed, "disconnect event was not processed");
Assert.True(server.ClientNum == currentClientCount, "client count was not decremented");
eventsProcessed++;
resetEvent.Set();
}
};
(server.RconParser as TestRconParser).FakeClientCount = 1;
resetEvent.Wait(15000);
resetEvent.Reset();
Assert.Equal(1, eventsProcessed);
(server.RconParser as TestRconParser).FakeClientCount = 0;
resetEvent.Wait(15000);
Assert.Equal(2, eventsProcessed);
_manager.GetApplicationSettings().Configuration().RConPollRate = int.MaxValue;
}
} }
} }

View File

@ -0,0 +1,24 @@
using IW4MAdmin.Application;
using SharedLibraryCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Tests
{
internal static class TestHelpers
{
internal static void EmulateClientJoinLog(this Server svr)
{
long guid = svr.ClientNum + 1;
File.AppendAllText(svr.LogPath, $"0:00 J;{guid};{svr.ClientNum};test_client_{svr.ClientNum}\r\n");
}
internal static void EmulateClientQuitLog(this Server svr)
{
long guid = Math.Max(1, svr.ClientNum);
File.AppendAllText(svr.LogPath, $"0:00 Q;{guid};{svr.ClientNum};test_client_{svr.ClientNum}\r\n");
}
}
}

View File

@ -0,0 +1,38 @@
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.RCon;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Tests
{
class TestRconParser : IW4MAdmin.Application.RconParsers.BaseRConParser
{
public int FakeClientCount { get; set; }
public List<EFClient> FakeClients { get; set; } = new List<EFClient>();
public override string Version => "test";
public override async Task<List<EFClient>> GetStatusAsync(Connection connection)
{
var clientList = new List<EFClient>();
for (int i = 0; i < FakeClientCount; i++)
{
clientList.Add(new EFClient()
{
ClientNumber = i,
NetworkId = i + 1,
CurrentAlias = new EFAlias()
{
Name = $"test_bot_{i}",
IPAddress = i + 1
}
});
}
return clientList.Count > 0 ? clientList : FakeClients;
}
}
}

View File

@ -31,7 +31,7 @@ namespace SharedLibraryCore.Commands
public class CRestart : Command public class CRestart : Command
{ {
public CRestart() : public CRestart() :
base("restart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RESTART_DESC"], "rs", EFClient.Permission.Owner, false) base("restart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RESTART_DESC"], "res", EFClient.Permission.Owner, false)
{ } { }
public override Task ExecuteAsync(GameEvent E) public override Task ExecuteAsync(GameEvent E)

View File

@ -205,12 +205,7 @@ namespace SharedLibraryCore.Database.Models
int reportCount = sender.GetAdditionalProperty<int>("_reportCount"); int reportCount = sender.GetAdditionalProperty<int>("_reportCount");
if (Level > sender.Level) if (Equals(sender))
{
e.FailReason = GameEvent.EventFailReason.Permission;
}
else if (Equals(sender))
{ {
e.FailReason = GameEvent.EventFailReason.Invalid; e.FailReason = GameEvent.EventFailReason.Invalid;
} }

View File

@ -110,14 +110,6 @@ namespace SharedLibraryCore.Services
#endif #endif
var aliases = await iqAliases.ToListAsync(); var aliases = await iqAliases.ToListAsync();
// update each of the aliases where this is no IP but the name is identical
foreach (var alias in aliases.Where(_alias => (_alias.IPAddress == null || _alias.IPAddress == 0)))
{
alias.IPAddress = ip;
}
await context.SaveChangesAsync();
// see if they have a matching IP + Name but new NetworkId // see if they have a matching IP + Name but new NetworkId
var existingExactAlias = aliases.FirstOrDefault(a => a.Name == name && a.IPAddress == ip); var existingExactAlias = aliases.FirstOrDefault(a => a.Name == name && a.IPAddress == ip);
bool hasExactAliasMatch = existingExactAlias != null; bool hasExactAliasMatch = existingExactAlias != null;
@ -125,13 +117,21 @@ namespace SharedLibraryCore.Services
// if existing alias matches link them // if existing alias matches link them
var newAliasLink = existingExactAlias?.Link; var newAliasLink = existingExactAlias?.Link;
// if no exact matches find the first IP or LinkId that matches // if no exact matches find the first IP or LinkId that matches
newAliasLink = newAliasLink ?? aliases.FirstOrDefault()?.Link; newAliasLink = newAliasLink ?? aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault()?.Link;
// if no matches are found, use our current one ( it will become permanent ) // if no matches are found, use our current one ( it will become permanent )
newAliasLink = newAliasLink ?? entity.AliasLink; newAliasLink = newAliasLink ?? entity.AliasLink;
bool hasExistingAlias = aliases.Count > 0; bool hasExistingAlias = aliases.Count > 0;
bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId; bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId;
// update each of the aliases where this is no IP but the name is identical
foreach (var alias in aliases.Where(_alias => (_alias.IPAddress == null || _alias.IPAddress == 0)))
{
alias.IPAddress = ip;
}
await context.SaveChangesAsync();
// this happens when the link we found is different than the one we create before adding an IP // this happens when the link we found is different than the one we create before adding an IP
if (isAliasLinkUpdated) if (isAliasLinkUpdated)
{ {