mirror of
				https://github.com/pelican-dev/panel.git
				synced 2025-11-04 06:26:52 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			228 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace Tests\Unit\Jobs\Schedule;
 | 
						|
 | 
						|
use Mockery as m;
 | 
						|
use Carbon\Carbon;
 | 
						|
use Tests\TestCase;
 | 
						|
use Cake\Chronos\Chronos;
 | 
						|
use Pterodactyl\Models\Task;
 | 
						|
use Pterodactyl\Models\User;
 | 
						|
use GuzzleHttp\Psr7\Response;
 | 
						|
use InvalidArgumentException;
 | 
						|
use Pterodactyl\Models\Server;
 | 
						|
use Pterodactyl\Models\Schedule;
 | 
						|
use Illuminate\Support\Facades\Bus;
 | 
						|
use Pterodactyl\Jobs\Schedule\RunTaskJob;
 | 
						|
use Pterodactyl\Repositories\Eloquent\TaskRepository;
 | 
						|
use Pterodactyl\Services\Backups\InitiateBackupService;
 | 
						|
use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
 | 
						|
use Pterodactyl\Repositories\Wings\DaemonPowerRepository;
 | 
						|
use Pterodactyl\Repositories\Wings\DaemonCommandRepository;
 | 
						|
use Pterodactyl\Contracts\Repository\TaskRepositoryInterface;
 | 
						|
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
 | 
						|
 | 
						|
class RunTaskJobTest extends TestCase
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * @var \Mockery\MockInterface
 | 
						|
     */
 | 
						|
    private $commandRepository;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var \Mockery\MockInterface
 | 
						|
     */
 | 
						|
    private $powerRepository;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var \Mockery\MockInterface
 | 
						|
     */
 | 
						|
    private $initiateBackupService;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var \Mockery\MockInterface
 | 
						|
     */
 | 
						|
    private $taskRepository;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var \Mockery\MockInterface
 | 
						|
     */
 | 
						|
    private $scheduleRepository;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Setup tests.
 | 
						|
     */
 | 
						|
    public function setUp(): void
 | 
						|
    {
 | 
						|
        parent::setUp();
 | 
						|
 | 
						|
        Bus::fake();
 | 
						|
        Carbon::setTestNow(Carbon::now());
 | 
						|
 | 
						|
        $this->commandRepository = m::mock(DaemonCommandRepository::class);
 | 
						|
        $this->powerRepository = m::mock(DaemonPowerRepository::class);
 | 
						|
        $this->taskRepository = m::mock(TaskRepository::class);
 | 
						|
        $this->initiateBackupService = m::mock(InitiateBackupService::class);
 | 
						|
        $this->scheduleRepository = m::mock(ScheduleRepository::class);
 | 
						|
 | 
						|
        $this->app->instance(TaskRepositoryInterface::class, $this->taskRepository);
 | 
						|
        $this->app->instance(ScheduleRepositoryInterface::class, $this->scheduleRepository);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test power option passed to job.
 | 
						|
     */
 | 
						|
    public function testPowerAction()
 | 
						|
    {
 | 
						|
        /** @var \Pterodactyl\Models\Schedule $schedule */
 | 
						|
        $schedule = factory(Schedule::class)->make(['is_active' => true]);
 | 
						|
 | 
						|
        /** @var \Pterodactyl\Models\Task $task */
 | 
						|
        $task = factory(Task::class)->make(['action' => 'power', 'sequence_id' => 1]);
 | 
						|
 | 
						|
        /* @var \Pterodactyl\Models\Server $server */
 | 
						|
        $task->setRelation('server', $server = factory(Server::class)->make());
 | 
						|
        $task->setRelation('schedule', $schedule);
 | 
						|
        $server->setRelation('user', factory(User::class)->make());
 | 
						|
 | 
						|
        $this->taskRepository->expects('getTaskForJobProcess')->with($task->id)->andReturn($task);
 | 
						|
        $this->powerRepository->expects('setServer')->with($task->server)->andReturnSelf()
 | 
						|
            ->getMock()->expects('send')->with($task->payload)->andReturn(new Response);
 | 
						|
 | 
						|
        $this->taskRepository->shouldReceive('update')->with($task->id, ['is_queued' => false])->once()->andReturnNull();
 | 
						|
        $this->taskRepository->shouldReceive('getNextTask')->with($schedule->id, $task->sequence_id)->once()->andReturnNull();
 | 
						|
 | 
						|
        $this->scheduleRepository->shouldReceive('withoutFreshModel->update')->with($schedule->id, [
 | 
						|
            'is_processing' => false,
 | 
						|
            'last_run_at' => Chronos::now()->toDateTimeString(),
 | 
						|
        ])->once()->andReturnNull();
 | 
						|
 | 
						|
        $this->getJobInstance($task->id, $schedule->id);
 | 
						|
 | 
						|
        Bus::assertNotDispatched(RunTaskJob::class);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test command action passed to job.
 | 
						|
     */
 | 
						|
    public function testCommandAction()
 | 
						|
    {
 | 
						|
        $schedule = factory(Schedule::class)->make();
 | 
						|
        $task = factory(Task::class)->make(['action' => 'command', 'sequence_id' => 1]);
 | 
						|
        $task->setRelation('server', $server = factory(Server::class)->make());
 | 
						|
        $task->setRelation('schedule', $schedule);
 | 
						|
        $server->setRelation('user', factory(User::class)->make());
 | 
						|
 | 
						|
        $this->taskRepository->expects('getTaskForJobProcess')->with($task->id)->andReturn($task);
 | 
						|
        $this->commandRepository->expects('setServer')->with($task->server)->andReturnSelf()
 | 
						|
            ->getMock()->expects('send')->with($task->payload)->andReturn(new Response);
 | 
						|
 | 
						|
        $this->taskRepository->expects('update')->with($task->id, ['is_queued' => false])->andReturnNull();
 | 
						|
        $this->taskRepository->expects('getNextTask')->with($schedule->id, $task->sequence_id)->andReturnNull();
 | 
						|
 | 
						|
        $this->scheduleRepository->shouldReceive('withoutFreshModel->update')->with($schedule->id, [
 | 
						|
            'is_processing' => false,
 | 
						|
            'last_run_at' => Chronos::now()->toDateTimeString(),
 | 
						|
        ])->once()->andReturnNull();
 | 
						|
 | 
						|
        $this->getJobInstance($task->id, $schedule->id);
 | 
						|
 | 
						|
        Bus::assertNotDispatched(RunTaskJob::class);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test that the next task in the list is queued if the current one is not the last.
 | 
						|
     */
 | 
						|
    public function testNextTaskQueuedIfExists()
 | 
						|
    {
 | 
						|
        $schedule = factory(Schedule::class)->make();
 | 
						|
        $task = factory(Task::class)->make(['action' => 'command', 'sequence_id' => 1]);
 | 
						|
        $task->setRelation('server', $server = factory(Server::class)->make());
 | 
						|
        $task->setRelation('schedule', $schedule);
 | 
						|
        $server->setRelation('user', factory(User::class)->make());
 | 
						|
 | 
						|
        $this->taskRepository->expects('getTaskForJobProcess')->with($task->id)->andReturn($task);
 | 
						|
        $this->commandRepository->expects('setServer')->with($task->server)->andReturnSelf()
 | 
						|
            ->getMock()->expects('send')->with($task->payload)->andReturn(new Response);
 | 
						|
 | 
						|
        $this->taskRepository->shouldReceive('update')->with($task->id, ['is_queued' => false])->once()->andReturnNull();
 | 
						|
 | 
						|
        $nextTask = factory(Task::class)->make();
 | 
						|
        $this->taskRepository->expects('getNextTask')->with($schedule->id, $task->sequence_id)->andReturn($nextTask);
 | 
						|
        $this->taskRepository->expects('update')->with($nextTask->id, [
 | 
						|
            'is_queued' => true,
 | 
						|
        ])->andReturnNull();
 | 
						|
 | 
						|
        $this->getJobInstance($task->id, $schedule->id);
 | 
						|
 | 
						|
        Bus::assertDispatched(RunTaskJob::class, function ($job) use ($nextTask, $schedule) {
 | 
						|
            $this->assertEquals($nextTask->id, $job->task, 'Assert correct task ID is passed to job.');
 | 
						|
            $this->assertEquals($schedule->id, $job->schedule, 'Assert correct schedule ID is passed to job.');
 | 
						|
            $this->assertEquals($nextTask->time_offset, $job->delay, 'Assert correct job delay time is set.');
 | 
						|
 | 
						|
            return true;
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test that an exception is thrown if an invalid task action is supplied.
 | 
						|
     */
 | 
						|
    public function testInvalidActionPassedToJob()
 | 
						|
    {
 | 
						|
        $this->expectException(InvalidArgumentException::class);
 | 
						|
        $this->expectExceptionMessage('Cannot run a task that points to a non-existent action.');
 | 
						|
 | 
						|
        $schedule = factory(Schedule::class)->make();
 | 
						|
        $task = factory(Task::class)->make(['action' => 'invalid', 'sequence_id' => 1]);
 | 
						|
        $task->setRelation('server', $server = factory(Server::class)->make());
 | 
						|
        $task->setRelation('schedule', $schedule);
 | 
						|
        $server->setRelation('user', factory(User::class)->make());
 | 
						|
 | 
						|
        $this->taskRepository->expects('getTaskForJobProcess')->with($task->id)->andReturn($task);
 | 
						|
 | 
						|
        $this->getJobInstance($task->id, 1234);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test that a schedule marked as disabled does not get processed.
 | 
						|
     */
 | 
						|
    public function testScheduleMarkedAsDisabledDoesNotProcess()
 | 
						|
    {
 | 
						|
        $schedule = factory(Schedule::class)->make(['is_active' => false]);
 | 
						|
        $task = factory(Task::class)->make(['action' => 'invalid', 'sequence_id' => 1]);
 | 
						|
        $task->setRelation('server', $server = factory(Server::class)->make());
 | 
						|
        $task->setRelation('schedule', $schedule);
 | 
						|
        $server->setRelation('user', factory(User::class)->make());
 | 
						|
 | 
						|
        $this->taskRepository->shouldReceive('getTaskForJobProcess')->with($task->id)->once()->andReturn($task);
 | 
						|
 | 
						|
        $this->scheduleRepository->shouldReceive('withoutFreshModel->update')->with($schedule->id, [
 | 
						|
            'is_processing' => false,
 | 
						|
            'last_run_at' => Chronos::now()->toDateTimeString(),
 | 
						|
        ])->once()->andReturn(1);
 | 
						|
 | 
						|
        $this->taskRepository->shouldReceive('update')->with($task->id, ['is_queued' => false])->once()->andReturn(1);
 | 
						|
 | 
						|
        $this->getJobInstance($task->id, $schedule->id);
 | 
						|
        $this->assertTrue(true);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Run the job using the mocks provided.
 | 
						|
     *
 | 
						|
     * @param int $task
 | 
						|
     * @param int $schedule
 | 
						|
     *
 | 
						|
     * @throws \Pterodactyl\Exceptions\Model\DataValidationException
 | 
						|
     */
 | 
						|
    private function getJobInstance($task, $schedule)
 | 
						|
    {
 | 
						|
        return (new RunTaskJob($task, $schedule))->handle(
 | 
						|
            $this->commandRepository,
 | 
						|
            $this->initiateBackupService,
 | 
						|
            $this->powerRepository,
 | 
						|
            $this->taskRepository
 | 
						|
        );
 | 
						|
    }
 | 
						|
}
 |