Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/tests/Integration/Services/Servers/ServerDeletionServiceTest.php
7460 views
1
<?php
2
3
namespace Pterodactyl\Tests\Integration\Services\Servers;
4
5
use Mockery\MockInterface;
6
use GuzzleHttp\Psr7\Request;
7
use GuzzleHttp\Psr7\Response;
8
use Pterodactyl\Models\Database;
9
use Pterodactyl\Models\DatabaseHost;
10
use GuzzleHttp\Exception\BadResponseException;
11
use Pterodactyl\Tests\Integration\IntegrationTestCase;
12
use Pterodactyl\Services\Servers\ServerDeletionService;
13
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
14
use Pterodactyl\Services\Databases\DatabaseManagementService;
15
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
16
17
class ServerDeletionServiceTest extends IntegrationTestCase
18
{
19
private MockInterface $daemonServerRepository;
20
21
private MockInterface $databaseManagementService;
22
23
private static ?string $defaultLogger;
24
25
/**
26
* Stub out services that we don't want to test in here.
27
*/
28
public function setUp(): void
29
{
30
parent::setUp();
31
32
self::$defaultLogger = config('logging.default');
33
// There will be some log calls during this test, don't actually write to the disk.
34
config()->set('logging.default', 'null');
35
36
$this->daemonServerRepository = \Mockery::mock(DaemonServerRepository::class);
37
$this->databaseManagementService = \Mockery::mock(DatabaseManagementService::class);
38
39
$this->app->instance(DaemonServerRepository::class, $this->daemonServerRepository);
40
$this->app->instance(DatabaseManagementService::class, $this->databaseManagementService);
41
}
42
43
/**
44
* Reset the log driver.
45
*/
46
protected function tearDown(): void
47
{
48
config()->set('logging.default', self::$defaultLogger);
49
self::$defaultLogger = null;
50
51
parent::tearDown();
52
}
53
54
/**
55
* Test that a server is not deleted if the force option is not set and an error
56
* is returned by wings.
57
*/
58
public function testRegularDeleteFailsIfWingsReturnsError()
59
{
60
$server = $this->createServerModel();
61
62
$this->expectException(DaemonConnectionException::class);
63
64
$this->daemonServerRepository->expects('setServer->delete')->withNoArgs()->andThrows(
65
new DaemonConnectionException(new BadResponseException('Bad request', new Request('GET', '/test'), new Response()))
66
);
67
68
$this->getService()->handle($server);
69
70
$this->assertDatabaseHas('servers', ['id' => $server->id]);
71
}
72
73
/**
74
* Test that a 404 from Wings while deleting a server does not cause the deletion to fail.
75
*/
76
public function testRegularDeleteIgnores404FromWings()
77
{
78
$server = $this->createServerModel();
79
80
$this->daemonServerRepository->expects('setServer->delete')->withNoArgs()->andThrows(
81
new DaemonConnectionException(new BadResponseException('Bad request', new Request('GET', '/test'), new Response(404)))
82
);
83
84
$this->getService()->handle($server);
85
86
$this->assertDatabaseMissing('servers', ['id' => $server->id]);
87
}
88
89
/**
90
* Test that an error from Wings does not cause the deletion to fail if the server is being
91
* force deleted.
92
*/
93
public function testForceDeleteIgnoresExceptionFromWings()
94
{
95
$server = $this->createServerModel();
96
97
$this->daemonServerRepository->expects('setServer->delete')->withNoArgs()->andThrows(
98
new DaemonConnectionException(new BadResponseException('Bad request', new Request('GET', '/test'), new Response(500)))
99
);
100
101
$this->getService()->withForce()->handle($server);
102
103
$this->assertDatabaseMissing('servers', ['id' => $server->id]);
104
}
105
106
/**
107
* Test that a non-force-delete call does not delete the server if one of the databases
108
* cannot be deleted from the host.
109
*/
110
public function testExceptionWhileDeletingStopsProcess()
111
{
112
$server = $this->createServerModel();
113
$host = DatabaseHost::factory()->create();
114
115
/** @var Database $db */
116
$db = Database::factory()->create(['database_host_id' => $host->id, 'server_id' => $server->id]);
117
118
$server->refresh();
119
120
$this->daemonServerRepository->expects('setServer->delete')->withNoArgs()->andReturnUndefined();
121
$this->databaseManagementService->expects('delete')->with(\Mockery::on(function ($value) use ($db) {
122
return $value instanceof Database && $value->id === $db->id;
123
}))->andThrows(new \Exception());
124
125
$this->expectException(\Exception::class);
126
$this->getService()->handle($server);
127
128
$this->assertDatabaseHas('servers', ['id' => $server->id]);
129
$this->assertDatabaseHas('databases', ['id' => $db->id]);
130
}
131
132
/**
133
* Test that a server is deleted even if the server databases cannot be deleted from the host.
134
*/
135
public function testExceptionWhileDeletingDatabasesDoesNotAbortIfForceDeleted()
136
{
137
$server = $this->createServerModel();
138
$host = DatabaseHost::factory()->create();
139
140
/** @var Database $db */
141
$db = Database::factory()->create(['database_host_id' => $host->id, 'server_id' => $server->id]);
142
143
$server->refresh();
144
145
$this->daemonServerRepository->expects('setServer->delete')->withNoArgs()->andReturnUndefined();
146
$this->databaseManagementService->expects('delete')->with(\Mockery::on(function ($value) use ($db) {
147
return $value instanceof Database && $value->id === $db->id;
148
}))->andThrows(new \Exception());
149
150
$this->getService()->withForce(true)->handle($server);
151
152
$this->assertDatabaseMissing('servers', ['id' => $server->id]);
153
$this->assertDatabaseMissing('databases', ['id' => $db->id]);
154
}
155
156
private function getService(): ServerDeletionService
157
{
158
return $this->app->make(ServerDeletionService::class);
159
}
160
}
161
162