From 85e35f0bdfbdb0a27bdadc812eb8225c05e59747 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Mon, 25 Sep 2017 23:46:36 -0500 Subject: [PATCH] More tests --- .../DaemonKeyCreationServiceTest.php | 98 +++++++++++ .../DaemonKeyDeletionServiceTest.php | 162 ++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 tests/Unit/Services/DaemonKeys/DaemonKeyCreationServiceTest.php create mode 100644 tests/Unit/Services/DaemonKeys/DaemonKeyDeletionServiceTest.php diff --git a/tests/Unit/Services/DaemonKeys/DaemonKeyCreationServiceTest.php b/tests/Unit/Services/DaemonKeys/DaemonKeyCreationServiceTest.php new file mode 100644 index 000000000..b376b8061 --- /dev/null +++ b/tests/Unit/Services/DaemonKeys/DaemonKeyCreationServiceTest.php @@ -0,0 +1,98 @@ +. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +namespace Tests\Unit\Services\DaemonKeys; + +use Mockery as m; +use Carbon\Carbon; +use Tests\TestCase; +use phpmock\phpunit\PHPMock; +use Illuminate\Contracts\Config\Repository; +use Pterodactyl\Services\DaemonKeys\DaemonKeyCreationService; +use Pterodactyl\Contracts\Repository\DaemonKeyRepositoryInterface; + +class DaemonKeyCreationServiceTest extends TestCase +{ + use PHPMock; + + /** + * @var \Carbon\Carbon|\Mockery\Mock + */ + protected $carbon; + + /** + * @var \Illuminate\Contracts\Config\Repository|\Mockery\Mock + */ + protected $config; + + /** + * @var \Pterodactyl\Contracts\Repository\DaemonKeyRepositoryInterface|\Mockery\Mock + */ + protected $repository; + + /** + * @var \Pterodactyl\Services\DaemonKeys\DaemonKeyCreationService + */ + protected $service; + + /** + * Setup tests. + */ + public function setUp() + { + parent::setUp(); + + $this->carbon = m::mock(Carbon::class); + $this->config = m::Mock(Repository::class); + $this->repository = m::mock(DaemonKeyRepositoryInterface::class); + + $this->service = new DaemonKeyCreationService($this->carbon, $this->config, $this->repository); + } + + /** + * Test that a daemon key is created. + */ + public function testDaemonKeyIsCreated() + { + $this->getFunctionMock('\\Pterodactyl\\Services\\DaemonKeys', 'str_random') + ->expects($this->once())->willReturn('random_string'); + + $this->config->shouldReceive('get')->with('pterodactyl.api.key_expire_time')->once()->andReturn(100); + $this->carbon->shouldReceive('now')->withNoArgs()->once()->andReturnSelf() + ->shouldReceive('addMinutes')->with(100)->once()->andReturnSelf() + ->shouldReceive('toDateTimeString')->withNoArgs()->once()->andReturn('00:00:00'); + + $this->repository->shouldReceive('withoutFresh')->withNoArgs()->once()->andReturnSelf() + ->shouldReceive('create')->with([ + 'user_id' => 1, + 'server_id' => 2, + 'secret' => DaemonKeyRepositoryInterface::INTERNAL_KEY_IDENTIFIER . 'random_string', + 'expires_at' => '00:00:00', + ])->once()->andReturnNull(); + + $response = $this->service->handle(2, 1); + $this->assertNotEmpty($response); + $this->assertEquals('i_random_string', $response); + } +} diff --git a/tests/Unit/Services/DaemonKeys/DaemonKeyDeletionServiceTest.php b/tests/Unit/Services/DaemonKeys/DaemonKeyDeletionServiceTest.php new file mode 100644 index 000000000..85067bf9e --- /dev/null +++ b/tests/Unit/Services/DaemonKeys/DaemonKeyDeletionServiceTest.php @@ -0,0 +1,162 @@ +. + * + * This software is licensed under the terms of the MIT license. + * https://opensource.org/licenses/MIT + */ + +namespace Tests\Unit\Services\DaemonKeys; + +use Mockery as m; +use Tests\TestCase; +use Illuminate\Log\Writer; +use Pterodactyl\Models\Server; +use Pterodactyl\Models\DaemonKey; +use GuzzleHttp\Exception\RequestException; +use Illuminate\Database\ConnectionInterface; +use Pterodactyl\Exceptions\DisplayException; +use Pterodactyl\Exceptions\PterodactylException; +use Pterodactyl\Services\DaemonKeys\DaemonKeyDeletionService; +use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; +use Pterodactyl\Contracts\Repository\DaemonKeyRepositoryInterface; +use Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface as DaemonServerRepositoryInterface; + +class DaemonKeyDeletionServiceTest extends TestCase +{ + /** + * @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock + */ + protected $connection; + + /** + * @var \Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface|\Mockery\Mock + */ + protected $daemonRepository; + + /** + * @var \GuzzleHttp\Exception\RequestException|\Mockery\Mock + */ + protected $exception; + + /** + * @var \Pterodactyl\Contracts\Repository\DaemonKeyRepositoryInterface|\Mockery\Mock + */ + protected $repository; + + /** + * @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock + */ + protected $serverRepository; + + /** + * @var \Pterodactyl\Services\DaemonKeys\DaemonKeyDeletionService + */ + protected $service; + + /** + * @var \Illuminate\Log\Writer|\Mockery\Mock + */ + protected $writer; + + /** + * Setup tests. + */ + public function setUp() + { + parent::setUp(); + + $this->connection = m::mock(ConnectionInterface::class); + $this->daemonRepository = m::mock(DaemonServerRepositoryInterface::class); + $this->exception = m::mock(RequestException::class); + $this->repository = m::mock(DaemonKeyRepositoryInterface::class); + $this->serverRepository = m::mock(ServerRepositoryInterface::class); + $this->writer = m::mock(Writer::class); + + $this->service = new DaemonKeyDeletionService( + $this->connection, + $this->repository, + $this->daemonRepository, + $this->serverRepository, + $this->writer + ); + } + + /** + * Test that a daemon key is deleted correctly. + */ + public function testKeyIsDeleted() + { + $server = factory(Server::class)->make(); + $key = factory(DaemonKey::class)->make(); + + $this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); + $this->repository->shouldReceive('findFirstWhere')->with([ + ['user_id', '=', 100], + ['server_id', '=', $server->id], + ])->once()->andReturn($key); + + $this->repository->shouldReceive('delete')->with($key->id)->once()->andReturnNull(); + $this->daemonRepository->shouldReceive('setNode')->with($server->node_id)->once()->andReturnSelf() + ->shouldReceive('revokeAccessKey')->with($key->secret)->once()->andReturnNull(); + $this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull(); + + $this->service->handle($server, 100); + $this->assertTrue(true); + } + + /** + * Test that a daemon key can be deleted when only a server ID is passed. + */ + public function testKeyIsDeletedIfIdIsPassedInPlaceOfModel() + { + $server = factory(Server::class)->make(); + $key = factory(DaemonKey::class)->make(); + + $this->serverRepository->shouldReceive('find')->with($server->id)->once()->andReturn($server); + $this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); + $this->repository->shouldReceive('findFirstWhere')->with([ + ['user_id', '=', 100], + ['server_id', '=', $server->id], + ])->once()->andReturn($key); + + $this->repository->shouldReceive('delete')->with($key->id)->once()->andReturnNull(); + $this->daemonRepository->shouldReceive('setNode')->with($server->node_id)->once()->andReturnSelf() + ->shouldReceive('revokeAccessKey')->with($key->secret)->once()->andReturnNull(); + $this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull(); + + $this->service->handle($server->id, 100); + $this->assertTrue(true); + } + + /** + * Test that an exception is properly handled if thrown by guzzle. + */ + public function testExceptionReturnedByGuzzleIsHandled() + { + $server = factory(Server::class)->make(); + $key = factory(DaemonKey::class)->make(); + + $this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); + $this->repository->shouldReceive('findFirstWhere')->with([ + ['user_id', '=', 100], + ['server_id', '=', $server->id], + ])->once()->andReturn($key); + + $this->repository->shouldReceive('delete')->with($key->id)->once()->andReturnNull(); + $this->daemonRepository->shouldReceive('setNode')->with($server->node_id)->once()->andThrow($this->exception); + $this->exception->shouldReceive('getResponse')->withNoArgs()->once()->andReturnNull(); + $this->connection->shouldReceive('rollBack')->withNoArgs()->once()->andReturnNull(); + $this->writer->shouldReceive('warning')->with($this->exception)->once()->andReturnNull(); + + try { + $this->service->handle($server, 100); + } catch (PterodactylException $exception) { + $this->assertInstanceOf(DisplayException::class, $exception); + $this->assertEquals(trans('admin/server.exceptions.daemon_exception', [ + 'code' => 'E_CONN_REFUSED', + ]), $exception->getMessage()); + } + } +}