You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Test-Miroir/Tests/Tests.php

395 lines
10 KiB

<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use xPaw\SourceQuery\Exception\AuthenticationException;
use xPaw\SourceQuery\Exception\InvalidArgumentException;
use xPaw\SourceQuery\Exception\InvalidPacketException;
use xPaw\SourceQuery\Exception\SocketException;
use xPaw\SourceQuery\Socket\SocketType;
use xPaw\SourceQuery\Socket\TestableSocket;
use xPaw\SourceQuery\SourceQuery;
/**
* @internal
* @coversNothing
*/
final class Tests extends TestCase
{
private TestableSocket $socket;
private SourceQuery $sourceQuery;
/**
* @throws InvalidArgumentException
*/
protected function setUp(): void
{
$this->socket = new TestableSocket(SocketType::SOURCE);
$this->sourceQuery = new SourceQuery($this->socket);
$this->sourceQuery->connect('', 2);
}
/**
* tearDown.
*/
protected function tearDown(): void
{
$this->sourceQuery->disconnect();
$this->socket = null;
$this->sourceQuery = null;
}
/**
* @throws InvalidArgumentException
*/
public function testInvalidTimeout(): void
{
$this->expectException(InvalidArgumentException::class);
$SourceQuery = new SourceQuery($this->socket);
$SourceQuery->connect('', 2, -1);
}
/**
* @throws InvalidPacketException
* @throws SocketException
*/
public function testNotConnectedGetInfo(): void
{
$this->expectException(SocketException::class);
$this->sourceQuery->disconnect();
$this->sourceQuery->getInfo();
}
/**
* @throws SocketException
*/
public function testNotConnectedPing(): void
{
$this->expectException(SocketException::class);
$this->sourceQuery->disconnect();
$this->sourceQuery->ping();
}
/**
* @throws InvalidPacketException
* @throws SocketException
*/
public function testNotConnectedGetPlayers(): void
{
$this->expectException(SocketException::class);
$this->sourceQuery->disconnect();
$this->sourceQuery->getPlayers();
}
/**
* @throws InvalidPacketException
* @throws SocketException
*/
public function testNotConnectedGetRules(): void
{
$this->expectException(SocketException::class);
$this->sourceQuery->disconnect();
$this->sourceQuery->getRules();
}
/**
* @throws SocketException
* @throws AuthenticationException
* @throws InvalidPacketException
*/
public function testNotConnectedSetRconPassword(): void
{
$this->expectException(SocketException::class);
$this->sourceQuery->disconnect();
$this->sourceQuery->setRconPassword('a');
}
/**
* @throws AuthenticationException
* @throws InvalidPacketException
* @throws SocketException
*/
public function testNotConnectedRcon(): void
{
$this->expectException(SocketException::class);
$this->sourceQuery->disconnect();
$this->sourceQuery->rcon('a');
}
/**
* @throws AuthenticationException
* @throws InvalidPacketException
* @throws SocketException
*/
public function testRconWithoutPassword(): void
{
$this->expectException(SocketException::class);
$this->sourceQuery->rcon('a');
}
/**
* @throws InvalidArgumentException
* @throws InvalidPacketException
* @throws SocketException
*
* @dataProvider infoProvider
*/
public function testGetInfo(string $rawInput, array $expectedOutput): void
{
if (isset($expectedOutput['IsMod'])) {
$this->socket = new TestableSocket(SocketType::GOLDSOURCE);
$this->sourceQuery = new SourceQuery($this->socket);
$this->sourceQuery->connect('', 2);
}
$this->socket->queue($rawInput);
$realOutput = $this->sourceQuery->getInfo();
static::assertSame($expectedOutput, $realOutput);
}
/**
* @throws JsonException
*/
public function infoProvider(): array
{
return $this->getData('Info', true);
}
/**
* @throws InvalidPacketException
* @throws SocketException
*
* @dataProvider badPacketProvider
*/
public function testBadGetInfo(string $data): void
{
$this->expectException(InvalidPacketException::class);
$this->socket->queue($data);
$this->sourceQuery->getInfo();
}
/**
* @throws InvalidPacketException
* @throws SocketException
*
* @dataProvider badPacketProvider
*/
public function testBadGetChallengeViaPlayers(string $data): void
{
$this->expectException(InvalidPacketException::class);
$this->socket->queue($data);
$this->sourceQuery->getPlayers();
}
/**
* @throws InvalidPacketException
* @throws SocketException
*
* @dataProvider badPacketProvider
*/
public function testBadGetPlayersAfterCorrectChallenge(string $data): void
{
$this->expectException(InvalidPacketException::class);
$this->socket->queue("\xFF\xFF\xFF\xFF\x41\x11\x11\x11\x11");
$this->socket->queue($data);
$this->sourceQuery->getPlayers();
}
/**
* @throws InvalidPacketException
* @throws SocketException
*
* @dataProvider badPacketProvider
*/
public function testBadGetRulesAfterCorrectChallenge(string $data): void
{
$this->expectException(InvalidPacketException::class);
$this->socket->queue("\xFF\xFF\xFF\xFF\x41\x11\x11\x11\x11");
$this->socket->queue($data);
$this->sourceQuery->getRules();
}
/**
* @return string[][]
*/
public function badPacketProvider(): array
{
return
[
[''],
["\xff\xff\xff\xff"], // No type.
["\xff\xff\xff\xff\x49"], // Correct type, but no data after.
["\xff\xff\xff\xff\x6D"], // Old info packet, but tests are done for source.
["\xff\xff\xff\xff\x11"], // Wrong type.
["\x11\x11\x11\x11"], // Wrong header.
["\xff"], // Should be 4 bytes, but it's 1.
];
}
/**
* @throws InvalidPacketException
* @throws SocketException
*/
public function testGetChallengeTwice(): void
{
$this->socket->queue("\xFF\xFF\xFF\xFF\x41\x11\x11\x11\x11");
$this->socket->queue("\xFF\xFF\xFF\xFF\x45\x01\x00ayy\x00lmao\x00");
static::assertSame(['ayy' => 'lmao'], $this->sourceQuery->getRules());
$this->socket->queue("\xFF\xFF\xFF\xFF\x45\x01\x00wow\x00much\x00");
static::assertSame(['wow' => 'much'], $this->sourceQuery->getRules());
}
/**
* @param string[] $rawInput
*
* @throws InvalidPacketException
* @throws SocketException
*
* @dataProvider rulesProvider
*/
public function testGetRules(array $rawInput, array $expectedOutput): void
{
$data = hex2bin('ffffffff4104fce20e');
if (!$data) {
throw new InvalidPacketException('Bad packet data');
}
$this->socket->queue($data); // Challenge.
foreach ($rawInput as $packet) {
$data = hex2bin($packet);
if (!$data) {
throw new InvalidPacketException('Bad packet data');
}
$this->socket->queue($data);
}
$realOutput = $this->sourceQuery->getRules();
static::assertSame($expectedOutput, $realOutput);
}
/**
* @throws JsonException
*/
public function rulesProvider(): array
{
return $this->getData('Rules');
}
/**
* @param string[] $rawInput
*
* @throws InvalidPacketException
* @throws SocketException
*
* @dataProvider playersProvider
*/
public function testGetPlayers(array $rawInput, array $expectedOutput): void
{
$data = hex2bin('ffffffff4104fce20e');
if (!$data) {
throw new InvalidPacketException('Bad packet data');
}
$this->socket->queue($data); // Challenge.
foreach ($rawInput as $packet) {
$data = hex2bin($packet);
if (!$data) {
throw new InvalidPacketException('Bad packet data');
}
$this->socket->queue($data);
}
$realOutput = $this->sourceQuery->getPlayers();
static::assertSame($expectedOutput, $realOutput);
}
/**
* @throws JsonException
*/
public function playersProvider(): array
{
return $this->getData('Players');
}
/**
* @throws SocketException
*/
public function testPing(): void
{
$this->socket->queue("\xFF\xFF\xFF\xFF\x6A\x00");
static::assertTrue($this->sourceQuery->ping());
$this->socket->queue("\xFF\xFF\xFF\xFF\xEE");
static::assertFalse($this->sourceQuery->ping());
}
/**
* @throws JsonException
*/
private function getData(string $path, bool $hexToBin = false): array
{
$dataProvider = [];
$files = glob(__DIR__ . '/' . $path . '/*.raw', GLOB_ERR);
if (!$files) {
throw new RuntimeException('Could not load test data.');
}
foreach ($files as $file) {
if ($hexToBin) {
$content = file_get_contents($file);
if (!$content) {
throw new RuntimeException('Could not load test data.');
}
$content = hex2bin(trim($content));
} else {
$content = file($file, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
}
$jsonContent = file_get_contents(
str_replace('.raw', '.json', $file)
);
if (!$jsonContent) {
throw new RuntimeException('Could not load test data.');
}
$dataProvider[] =
[
$content,
json_decode(
$jsonContent,
true,
512,
JSON_THROW_ON_ERROR
),
];
}
return $dataProvider;
}
}