Skip to content

Commit

Permalink
Context
Browse files Browse the repository at this point in the history
  • Loading branch information
AydinHassan committed May 9, 2024
1 parent be53db0 commit 5c95d08
Show file tree
Hide file tree
Showing 9 changed files with 423 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/Exercise/MockExercise.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace PhpSchool\PhpWorkshop\Exercise;

use PhpSchool\PhpWorkshop\ExerciseDispatcher;

class MockExercise extends AbstractExercise implements ExerciseInterface
{
public function getName(): string
{
return 'Mock Exercise';
}

public function getDescription(): string
{
return 'Mock Exercise';
}

public function getType(): ExerciseType
{
return ExerciseType::CUSTOM();
}

public function getProblem(): string
{
return 'problem-file.md';
}
}
56 changes: 56 additions & 0 deletions src/ExerciseRunner/Context/ExecutionContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace PhpSchool\PhpWorkshop\ExerciseRunner\Context;

use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Utils\Path;
use PhpSchool\PhpWorkshop\Utils\System;

class ExecutionContext
{
public function __construct(
private string $studentExecutionDirectory,
private string $referenceExecutionDirectory,
private ExerciseInterface $exercise,
private Input $input,
) {
}

public function getExercise(): ExerciseInterface
{
return $this->exercise;
}

public function getInput(): Input
{
return $this->input;
}

public function hasStudentSolution(): bool
{
return $this->input->hasArgument('program');
}

public function getEntryPoint(): string
{
if (!$this->hasStudentSolution()) {
throw new NoEntryPoint();
}

return Path::join(
$this->studentExecutionDirectory,
basename($this->input->getRequiredArgument('program'))
);
}

public function getStudentExecutionDirectory(): string
{
return $this->studentExecutionDirectory;
}

public function getReferenceExecutionDirectory(): string
{
return $this->referenceExecutionDirectory;
}
}
13 changes: 13 additions & 0 deletions src/ExerciseRunner/Context/NoEntryPoint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace PhpSchool\PhpWorkshop\ExerciseRunner\Context;

use PhpSchool\PhpWorkshop\Exception\RuntimeException;

class NoEntryPoint extends RuntimeException
{
public function __construct()
{
parent::__construct('No entry point provided');
}
}
102 changes: 102 additions & 0 deletions src/ExerciseRunner/Context/TestContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace PhpSchool\PhpWorkshop\ExerciseRunner\Context;

use PhpSchool\PhpWorkshop\Exception\RuntimeException;
use PhpSchool\PhpWorkshop\Exercise\CgiExercise;
use PhpSchool\PhpWorkshop\Exercise\CliExercise;
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\MockExercise;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Solution\SolutionInterface;
use PhpSchool\PhpWorkshop\Utils\System;
use Symfony\Component\Filesystem\Filesystem;
use PhpSchool\PhpWorkshop\Utils\Path;

class TestContext extends ExecutionContext
{
private Filesystem $filesystem;
private ExerciseInterface $exercise;
private bool $studentSolutionDirWasCreated = false;
private bool $referenceSolutionDirWasCreated = false;

public function __construct(
ExerciseInterface $exercise = null,
Input $input = null,
string $studentDirectory = null,
) {
$this->exercise = $exercise ?? new MockExercise();

$this->filesystem = new Filesystem();

if ($studentDirectory === null) {
$studentDirectory = System::randomTempDir();
}

parent::__construct(
$studentDirectory,
System::randomTempDir(),
$this->exercise,
$input ? $input : new Input('test', ['program' => 'solution.php']),
);
}

public function createStudentSolutionDirectory(): void
{
$this->filesystem->mkdir($this->getStudentExecutionDirectory());
$this->studentSolutionDirWasCreated = true;
}

public function createReferenceSolutionDirectory(): void
{
$this->filesystem->mkdir($this->getReferenceExecutionDirectory());
$this->referenceSolutionDirWasCreated = true;
}

public function importStudentFileFromString(string $content, string $filename = 'solution.php'): void
{
if (!$this->studentSolutionDirWasCreated) {
throw new RuntimeException(
sprintf('Student execution directory not created. Call %s::createStudentSolutionDirectory() first.', self::class)
);
}

file_put_contents(Path::join($this->getStudentExecutionDirectory(), $filename), $content);
}

public function importReferenceFileFromString(string $content, string $filename = 'solution.php'): void
{
if (!$this->referenceSolutionDirWasCreated) {
throw new RuntimeException(
sprintf('Reference execution directory not created. Call %s::createReferenceSolutionDirectory() first.', self::class)
);
}

file_put_contents(Path::join($this->getReferenceExecutionDirectory(), $filename), $content);
}

public static function fromExerciseAndStudentSolution(ExerciseInterface $exercise, string $file): self
{
if (file_exists($file)) {
$file = (string) realpath($file);
}

$input = new Input('test', ['program' => $file]);
return new self(
exercise: $exercise,
input: $input,
studentDirectory: dirname($file)
);
}

public function __destruct()
{
if ($this->studentSolutionDirWasCreated) {
$this->filesystem->remove($this->getStudentExecutionDirectory());
}

if ($this->referenceSolutionDirWasCreated) {
$this->filesystem->remove($this->getReferenceExecutionDirectory());
}
}
}
5 changes: 5 additions & 0 deletions src/Utils/System.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ public static function tempDir(string $path = ''): string
{
return Path::join(self::realpath(sys_get_temp_dir()), 'php-school', $path);
}

public static function randomTempDir(): string
{
return Path::join(self::realpath(sys_get_temp_dir()), 'php-school', bin2hex(random_bytes(4)));
}
}
84 changes: 84 additions & 0 deletions test/ExerciseRunner/Context/ExecutionContextTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace PhpSchool\PhpWorkshopTest\ExerciseRunner\Context;

use PhpSchool\PhpWorkshop\Exercise\MockExercise;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\NoEntryPoint;
use PhpSchool\PhpWorkshop\Input\Input;
use PHPUnit\Framework\TestCase;

class ExecutionContextTest extends TestCase
{
public function testGetters(): void
{
$exercise = new MockExercise();
$input = new Input('test', ['program' => 'solution.php']);
$context = new ExecutionContext(
'/student-dir',
'/reference-dir',
$exercise,
$input
);

static::assertSame($exercise, $context->getExercise());
static::assertSame($input, $context->getInput());
static::assertSame('/student-dir', $context->getStudentExecutionDirectory());
static::assertSame('/reference-dir', $context->getReferenceExecutionDirectory());
}

public function testHasStudentSolution(): void
{
$exercise = new MockExercise();
$input = new Input('test', ['program' => 'solution.php']);
$context = new ExecutionContext(
'/student-dir',
'/reference-dir',
$exercise,
$input
);

static::assertTrue($context->hasStudentSolution());

$exercise = new MockExercise();
$input = new Input('test');
$context = new ExecutionContext(
'/student-dir',
'/reference-dir',
$exercise,
$input
);

static::assertFalse($context->hasStudentSolution());
}

public function testGetEntryPoint(): void
{
$exercise = new MockExercise();
$input = new Input('test', ['program' => 'solution.php']);
$context = new ExecutionContext(
'/student-dir',
'/reference-dir',
$exercise,
$input
);

static::assertSame('/student-dir/solution.php', $context->getEntryPoint());
}

public function testGetEntryPointThrowsExceptionWhenNoStudentSolution(): void
{
static::expectException(NoEntryPoint::class);

$exercise = new MockExercise();
$input = new Input('test');
$context = new ExecutionContext(
'/student-dir',
'/reference-dir',
$exercise,
$input
);

$context->getEntryPoint();
}
}
15 changes: 15 additions & 0 deletions test/ExerciseRunner/Context/NoEntryPointTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace PhpSchool\PhpWorkshopTest\ExerciseRunner\Context;

use PhpSchool\PhpWorkshop\ExerciseRunner\Context\NoEntryPoint;
use PHPUnit\Framework\TestCase;

class NoEntryPointTest extends TestCase
{
public function testException(): void
{
$e = new NoEntryPoint();
static::assertSame('No entry point provided', $e->getMessage());
}
}
Loading

0 comments on commit 5c95d08

Please sign in to comment.