Skip to content

Commit 57db949

Browse files
committed
Tests a'hoy
1 parent 532025a commit 57db949

File tree

5 files changed

+210
-5
lines changed

5 files changed

+210
-5
lines changed

app/Exceptions/DisplayException.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ class DisplayException extends PterodactylException
2828
* @param string $message
2929
* @param Throwable|null $previous
3030
* @param string $level
31-
* @internal param mixed $log
31+
* @param int $code
3232
*/
33-
public function __construct($message, Throwable $previous = null, $level = self::LEVEL_ERROR)
33+
public function __construct($message, Throwable $previous = null, $level = self::LEVEL_ERROR, $code = 0)
3434
{
3535
$this->level = $level;
3636

3737
if (! is_null($previous)) {
3838
Log::{$level}($previous);
3939
}
4040

41-
parent::__construct($message);
41+
parent::__construct($message, $code, $previous);
4242
}
4343

4444
/**
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Tests\Traits;
4+
5+
use Mockery;
6+
use Mockery\MockInterface;
7+
use GuzzleHttp\Exception\RequestException;
8+
9+
trait MocksRequestException
10+
{
11+
/**
12+
* @var \GuzzleHttp\Exception\RequestException|\Mockery\Mock
13+
*/
14+
private $exception;
15+
16+
/**
17+
* @var mixed
18+
*/
19+
private $exceptionResponse;
20+
21+
/**
22+
* Configure the exception mock to work with the Panel's default exception
23+
* handler actions.
24+
*/
25+
public function configureExceptionMock()
26+
{
27+
$this->getExceptionMock()->shouldReceive('getResponse')->andReturn($this->exceptionResponse);
28+
}
29+
30+
/**
31+
* Return a mocked instance of the request exception.
32+
*
33+
* @return \Mockery\MockInterface
34+
*/
35+
private function getExceptionMock(): MockInterface
36+
{
37+
return $this->exception ?? $this->exception = Mockery::mock(RequestException::class);
38+
}
39+
40+
/**
41+
* Set the exception response.
42+
*
43+
* @param mixed $response
44+
*/
45+
protected function setExceptionResponse($response)
46+
{
47+
$this->exceptionResponse = $response;
48+
}
49+
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<?php
2+
3+
namespace Tests\Unit\Services\Allocations;
4+
5+
use Mockery as m;
6+
use Tests\TestCase;
7+
use Pterodactyl\Models\Server;
8+
use Pterodactyl\Models\Allocation;
9+
use Tests\Traits\MocksRequestException;
10+
use GuzzleHttp\Exception\RequestException;
11+
use Illuminate\Database\ConnectionInterface;
12+
use Pterodactyl\Exceptions\PterodactylException;
13+
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
14+
use Pterodactyl\Services\Allocations\SetDefaultAllocationService;
15+
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
16+
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
17+
use Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface as DaemonRepositoryInterface;
18+
19+
class SetDefaultAllocationServiceTest extends TestCase
20+
{
21+
use MocksRequestException;
22+
23+
/**
24+
* @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock
25+
*/
26+
private $connection;
27+
28+
/**
29+
* @var \Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface|\Mockery\Mock
30+
*/
31+
private $daemonRepository;
32+
33+
/**
34+
* @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface|\Mockery\Mock
35+
*/
36+
private $repository;
37+
38+
/**
39+
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock
40+
*/
41+
private $serverRepository;
42+
43+
/**
44+
* Setup tests.
45+
*/
46+
public function setUp()
47+
{
48+
parent::setUp();
49+
50+
$this->connection = m::mock(ConnectionInterface::class);
51+
$this->daemonRepository = m::mock(DaemonRepositoryInterface::class);
52+
$this->repository = m::mock(AllocationRepositoryInterface::class);
53+
$this->serverRepository = m::mock(ServerRepositoryInterface::class);
54+
}
55+
56+
/**
57+
* Test that an allocation can be updated.
58+
*
59+
* @dataProvider useModelDataProvider
60+
*/
61+
public function testAllocationIsUpdated(bool $useModel)
62+
{
63+
$allocations = factory(Allocation::class)->times(2)->make();
64+
$model = factory(Server::class)->make();
65+
if (! $useModel) {
66+
$this->serverRepository->shouldReceive('find')->with(1234)->once()->andReturn($model);
67+
}
68+
69+
$this->repository->shouldReceive('findWhere')->with([['server_id', '=', $model->id]])->once()->andReturn($allocations);
70+
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
71+
$this->serverRepository->shouldReceive('withoutFresh')->withNoArgs()->once()->andReturnSelf();
72+
$this->serverRepository->shouldReceive('update')->with($model->id, [
73+
'allocation_id' => $allocations->first()->id,
74+
])->once()->andReturnNull();
75+
76+
$this->daemonRepository->shouldReceive('setAccessServer')->with($model->uuid)->once()->andReturnSelf();
77+
$this->daemonRepository->shouldReceive('setNode')->with($model->node_id)->once()->andReturnSelf();
78+
$this->daemonRepository->shouldReceive('update')->with([
79+
'build' => [
80+
'default' => [
81+
'ip' => $allocations->first()->ip,
82+
'port' => $allocations->first()->port,
83+
],
84+
'ports|overwrite' => $allocations->groupBy('ip')->map(function ($item) {
85+
return $item->pluck('port');
86+
})->toArray(),
87+
],
88+
])->once()->andReturnNull();
89+
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
90+
91+
$response = $this->getService()->handle($useModel ? $model : 1234, $allocations->first()->id);
92+
$this->assertNotEmpty($response);
93+
$this->assertSame($allocations->first(), $response);
94+
}
95+
96+
/**
97+
* Test that an allocation that doesn't belong to a server throws an exception.
98+
*
99+
* @expectedException \Pterodactyl\Exceptions\Service\Allocation\AllocationDoesNotBelongToServerException
100+
*/
101+
public function testAllocationNotBelongingToServerThrowsException()
102+
{
103+
$model = factory(Server::class)->make();
104+
$this->repository->shouldReceive('findWhere')->with([['server_id', '=', $model->id]])->once()->andReturn(collect());
105+
106+
$this->getService()->handle($model, 1234);
107+
}
108+
109+
/**
110+
* Test that an exception thrown by guzzle is handled properly.
111+
*/
112+
public function testExceptionThrownByGuzzleIsHandled()
113+
{
114+
$this->configureExceptionMock();
115+
116+
$allocation = factory(Allocation::class)->make();
117+
$model = factory(Server::class)->make();
118+
119+
$this->repository->shouldReceive('findWhere')->with([['server_id', '=', $model->id]])->once()->andReturn(collect([$allocation]));
120+
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
121+
$this->serverRepository->shouldReceive('withoutFresh')->withNoArgs()->once()->andReturnSelf();
122+
$this->serverRepository->shouldReceive('update')->with($model->id, [
123+
'allocation_id' => $allocation->id,
124+
])->once()->andReturnNull();
125+
126+
$this->daemonRepository->shouldReceive('setAccessServer->setNode->update')->once()->andThrow($this->getExceptionMock());
127+
$this->connection->shouldReceive('rollBack')->withNoArgs()->once()->andReturnNull();
128+
129+
try {
130+
$this->getService()->handle($model, $allocation->id);
131+
} catch (PterodactylException $exception) {
132+
$this->assertInstanceOf(DaemonConnectionException::class, $exception);
133+
$this->assertInstanceOf(RequestException::class, $exception->getPrevious());
134+
}
135+
}
136+
137+
/**
138+
* Data provider to determine if a model should be passed or an int.
139+
*
140+
* @return array
141+
*/
142+
public function useModelDataProvider(): array
143+
{
144+
return [[false], [true]];
145+
}
146+
147+
/**
148+
* Return an instance of the service with mocked dependencies.
149+
*
150+
* @return \Pterodactyl\Services\Allocations\SetDefaultAllocationService
151+
*/
152+
private function getService(): SetDefaultAllocationService
153+
{
154+
return new SetDefaultAllocationService($this->repository, $this->connection, $this->daemonRepository, $this->serverRepository);
155+
}
156+
}

tests/Unit/Services/Databases/DatabasePasswordServiceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function setUp()
5151
*
5252
* @dataProvider useModelDataProvider
5353
*/
54-
public function testPasswordIsChanged($useModel)
54+
public function testPasswordIsChanged(bool $useModel)
5555
{
5656
$model = factory(Database::class)->make();
5757

tests/Unit/Services/Databases/Hosts/HostDeletionServiceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function testHostIsDeleted()
5151
*
5252
* @dataProvider databaseCountDataProvider
5353
*/
54-
public function testExceptionIsThrownIfDeletingHostWithDatabases($count)
54+
public function testExceptionIsThrownIfDeletingHostWithDatabases(int $count)
5555
{
5656
$this->databaseRepository->shouldReceive('findCountWhere')->with([['database_host_id', '=', 1234]])->once()->andReturn($count);
5757

0 commit comments

Comments
 (0)