-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fb82157
commit c0a9650
Showing
13 changed files
with
497 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace PhpSchool\PhpWorkshop\ExerciseRunner\Context; | ||
|
||
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface; | ||
use PhpSchool\PhpWorkshop\Input\Input; | ||
use PhpSchool\PhpWorkshop\Utils\System; | ||
|
||
class ExecutionContextFactory | ||
{ | ||
public function fromInputAndExercise(Input $input, ExerciseInterface $exercise): ExecutionContext | ||
{ | ||
return new ExecutionContext( | ||
dirname($input->getRequiredArgument('program')), | ||
System::randomTempDir(), | ||
$exercise, | ||
$input | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/ExerciseRunner/Context/StaticExecutionContextFactory.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace PhpSchool\PhpWorkshop\ExerciseRunner\Context; | ||
|
||
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface; | ||
use PhpSchool\PhpWorkshop\Input\Input; | ||
use PhpSchool\PhpWorkshop\Utils\System; | ||
use Symfony\Component\Filesystem\Filesystem; | ||
|
||
class StaticExecutionContextFactory extends ExecutionContextFactory | ||
{ | ||
public function __construct(private TestContext $context) | ||
{ | ||
} | ||
|
||
public function fromInputAndExercise(Input $input, ExerciseInterface $exercise): ExecutionContext | ||
{ | ||
return $this->context; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
<?php | ||
|
||
namespace PhpSchool\PhpWorkshop\ExerciseRunner\Context; | ||
|
||
use PhpSchool\PhpWorkshop\Exception\RuntimeException; | ||
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 | ||
{ | ||
public Filesystem $filesystem; | ||
public ExerciseInterface $exercise; | ||
|
||
private function __construct( | ||
ExerciseInterface $exercise = null, | ||
Input $input = null | ||
) { | ||
$this->exercise = $exercise ?? new MockExercise(); | ||
|
||
$this->filesystem = new Filesystem(); | ||
|
||
parent::__construct( | ||
System::randomTempDir(), | ||
System::randomTempDir(), | ||
$this->exercise, | ||
$input ? $input : new Input('test', ['program' => 'solution.php']), | ||
); | ||
} | ||
|
||
public function importStudentSolution(string $file): void | ||
{ | ||
if (!$this->filesystem->exists($this->getStudentExecutionDirectory())) { | ||
throw new RuntimeException( | ||
sprintf('Execution directories not created. Use %s::withDirectories() method instead.', self::class) | ||
); | ||
} | ||
|
||
copy($file, Path::join($this->getStudentExecutionDirectory(), 'solution.php')); | ||
} | ||
|
||
public function importStudentSolutionFolder(string $folder): void | ||
{ | ||
if (!$this->filesystem->exists($this->getStudentExecutionDirectory())) { | ||
throw new RuntimeException( | ||
sprintf('Execution directories not created. Use %s::withDirectories() method instead.', self::class) | ||
); | ||
} | ||
|
||
$this->filesystem->mirror($folder, $this->getStudentExecutionDirectory()); | ||
} | ||
|
||
public function importReferenceSolution(SolutionInterface $solution): void | ||
{ | ||
if (!$this->filesystem->exists($this->getReferenceExecutionDirectory())) { | ||
throw new RuntimeException( | ||
sprintf('Execution directories not created. Use %s::withDirectories() method instead.', self::class) | ||
); | ||
} | ||
|
||
foreach ($solution->getFiles() as $file) { | ||
$this->filesystem->copy( | ||
$file->getAbsolutePath(), | ||
Path::join($this->getReferenceExecutionDirectory(), $file->getRelativePath()) | ||
); | ||
} | ||
} | ||
|
||
public static function withDirectories(Input $input = null, ExerciseInterface $exercise = null): self | ||
{ | ||
$self = new self($exercise, $input); | ||
|
||
$self->filesystem->mkdir($self->getStudentExecutionDirectory()); | ||
$self->filesystem->mkdir($self->getReferenceExecutionDirectory()); | ||
|
||
return $self; | ||
} | ||
|
||
public static function withoutDirectories(Input $input = null, ExerciseInterface $exercise = null): self | ||
{ | ||
return new self($exercise, $input); | ||
} | ||
|
||
public function __destruct() | ||
{ | ||
$this->filesystem->remove($this->getStudentExecutionDirectory()); | ||
$this->filesystem->remove($this->getReferenceExecutionDirectory()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
test/ExerciseRunner/Context/ExecutionContextFactoryTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
namespace PhpSchool\PhpWorkshopTest\ExerciseRunner\Context; | ||
|
||
use PhpSchool\PhpWorkshop\Exercise\MockExercise; | ||
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContextFactory; | ||
use PhpSchool\PhpWorkshop\Input\Input; | ||
use PhpSchool\PhpWorkshop\Utils\System; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
class ExecutionContextFactoryTest extends TestCase | ||
{ | ||
public function testFactory(): void | ||
{ | ||
$factory = new ExecutionContextFactory(); | ||
|
||
$temporaryDirectory = System::randomTempDir(); | ||
|
||
$input = new Input('test', ['program' => $temporaryDirectory . '/solution.php']); | ||
$exercise = new MockExercise(); | ||
|
||
$context = $factory->fromInputAndExercise($input, $exercise); | ||
|
||
//check that student execution directory uses the parent directory of the program from the input | ||
static::assertSame($temporaryDirectory, $context->getStudentExecutionDirectory()); | ||
static::assertSame($temporaryDirectory . '/solution.php', $context->getEntryPoint()); | ||
|
||
//check that reference execution directory is a random temporary directory | ||
static::assertTrue(str_starts_with($context->getReferenceExecutionDirectory(), System::tempDir())); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
} | ||
} |
Oops, something went wrong.