-
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.
Introduce new class to prepare environment files
- Loading branch information
1 parent
0e24fd9
commit adaa0d2
Showing
4 changed files
with
172 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
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,68 @@ | ||
<?php | ||
|
||
namespace PhpSchool\PhpWorkshop\ExerciseRunner; | ||
|
||
use PhpSchool\PhpWorkshop\Event\EventDispatcher; | ||
use PhpSchool\PhpWorkshop\Exercise\ProvidesSolution; | ||
use PhpSchool\PhpWorkshop\Exercise\Scenario\ExerciseScenario; | ||
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext; | ||
use PhpSchool\PhpWorkshop\Utils\Path; | ||
use Symfony\Component\Filesystem\Filesystem; | ||
|
||
class EnvironmentManager | ||
{ | ||
public function __construct(private Filesystem $filesystem, private EventDispatcher $eventDispatcher) | ||
{ | ||
} | ||
|
||
public function prepareStudent(ExecutionContext $context, ExerciseScenario $scenario): void | ||
{ | ||
$this->copyExerciseFiles($scenario, $context->getStudentExecutionDirectory()); | ||
|
||
//cleanup the files when the run or verification process is finished | ||
//we do this at late as possible in case any checks or other event listeners need to access the files | ||
$this->eventDispatcher->listen(['run.finish', 'verify.finish'], function () use ($context, $scenario) { | ||
foreach ($scenario->getFiles() as $fileName => $content) { | ||
$this->filesystem->remove(Path::join($context->getStudentExecutionDirectory(), $fileName)); | ||
} | ||
}); | ||
} | ||
|
||
public function prepareReference(ExecutionContext $context, ExerciseScenario $scenario): void | ||
{ | ||
$exercise = $context->getExercise(); | ||
|
||
if (!$exercise instanceof ProvidesSolution) { | ||
return; | ||
} | ||
|
||
$this->filesystem->mkdir($context->getReferenceExecutionDirectory()); | ||
|
||
$solution = $exercise->getSolution(); | ||
|
||
foreach ($solution->getFiles() as $file) { | ||
$this->filesystem->copy( | ||
$file->getAbsolutePath(), | ||
Path::join($context->getReferenceExecutionDirectory(), $file->getRelativePath()) | ||
); | ||
} | ||
|
||
$this->copyExerciseFiles($scenario, $context->getReferenceExecutionDirectory()); | ||
|
||
//cleanup the files when the run or verification process is finished | ||
//we do this at late as possible in case any checks or other event listeners need to access the files | ||
$this->eventDispatcher->listen(['run.finish', 'verify.finish'], function () use ($context) { | ||
$this->filesystem->remove($context->getReferenceExecutionDirectory()); | ||
}); | ||
} | ||
|
||
private function copyExerciseFiles(ExerciseScenario $scenario, string $dir): void | ||
{ | ||
foreach ($scenario->getFiles() as $fileName => $content) { | ||
$this->filesystem->dumpFile( | ||
Path::join($dir, $fileName), | ||
$content | ||
); | ||
} | ||
} | ||
} |
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
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,99 @@ | ||
<?php | ||
|
||
namespace PhpSchool\PhpWorkshopTest\ExerciseRunner; | ||
|
||
use PhpSchool\PhpWorkshop\Event\EventDispatcher; | ||
use PhpSchool\PhpWorkshop\Event\ExerciseRunnerEvent; | ||
use PhpSchool\PhpWorkshop\Exercise\MockExercise; | ||
use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario; | ||
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\TestContext; | ||
use PhpSchool\PhpWorkshop\ExerciseRunner\EnvironmentManager; | ||
use PhpSchool\PhpWorkshop\Input\Input; | ||
use PhpSchool\PhpWorkshop\ResultAggregator; | ||
use PhpSchool\PhpWorkshop\Solution\DirectorySolution; | ||
use PhpSchool\PhpWorkshop\Solution\SingleFileSolution; | ||
use PhpSchool\PhpWorkshopTest\Asset\CliExerciseImpl; | ||
use PHPUnit\Framework\TestCase; | ||
use Symfony\Component\Filesystem\Filesystem; | ||
|
||
class EnvironmentManagerTest extends TestCase | ||
{ | ||
public function testPrepareStudentCopiesAllScenarioFilesToExecutionDirectory(): void | ||
{ | ||
$context = new TestContext(); | ||
$context->createStudentSolutionDirectory(); | ||
|
||
$scenario = (new CliScenario()) | ||
->withFile('file.txt', 'content') | ||
->withFile('file2.txt', 'content2'); | ||
|
||
$manager = new EnvironmentManager(new Filesystem(), new EventDispatcher(new ResultAggregator())); | ||
$manager->prepareStudent($context, $scenario); | ||
|
||
static::assertStringEqualsFile($context->getStudentExecutionDirectory() . '/file.txt', 'content'); | ||
static::assertStringEqualsFile($context->getStudentExecutionDirectory() . '/file2.txt', 'content2'); | ||
} | ||
|
||
public function testPrepareReferenceCopiesAllScenarioFilesAndSolutionFilesToExecutionDirectory(): void | ||
{ | ||
$exercise = new CliExerciseImpl(); | ||
$solution = SingleFileSolution::fromFile(realpath(__DIR__ . '/../res/cli/solution.php')); | ||
$exercise->setSolution($solution); | ||
|
||
$context = new TestContext($exercise); | ||
|
||
$scenario = (new CliScenario()) | ||
->withFile('file.txt', 'content') | ||
->withFile('file2.txt', 'content2'); | ||
|
||
$manager = new EnvironmentManager(new Filesystem(), new EventDispatcher(new ResultAggregator())); | ||
$manager->prepareReference($context, $scenario); | ||
|
||
static::assertFileEquals($context->getReferenceExecutionDirectory() . '/solution.php', __DIR__ . '/../res/cli/solution.php'); | ||
static::assertStringEqualsFile($context->getReferenceExecutionDirectory() . '/file.txt', 'content'); | ||
static::assertStringEqualsFile($context->getReferenceExecutionDirectory() . '/file2.txt', 'content2'); | ||
} | ||
|
||
/** | ||
* @dataProvider finishEvents | ||
*/ | ||
public function testFileAreCleanedUpOnlyWhenFinishEventIsDispatched(string $eventName): void | ||
{ | ||
$exercise = new CliExerciseImpl(); | ||
$solution = SingleFileSolution::fromFile(realpath(__DIR__ . '/../res/cli/solution.php')); | ||
$exercise->setSolution($solution); | ||
|
||
$context = new TestContext($exercise); | ||
$context->createStudentSolutionDirectory(); | ||
|
||
$scenario = (new CliScenario()) | ||
->withFile('file.txt', 'content') | ||
->withFile('file2.txt', 'content2'); | ||
|
||
$eventDispatcher = new EventDispatcher(new ResultAggregator()); | ||
$manager = new EnvironmentManager(new Filesystem(), $eventDispatcher); | ||
$manager->prepareStudent($context, $scenario); | ||
$manager->prepareReference($context, $scenario); | ||
|
||
static::assertFileExists($context->getStudentExecutionDirectory()); | ||
static::assertFileExists($context->getReferenceExecutionDirectory()); | ||
|
||
$eventDispatcher->dispatch(new ExerciseRunnerEvent($eventName, $exercise, new Input('app', ['program' => '']))); | ||
|
||
static::assertFileExists($context->getStudentExecutionDirectory()); | ||
static::assertFileNotExists($context->getReferenceExecutionDirectory() . '/file.txt'); | ||
static::assertFileNotExists($context->getReferenceExecutionDirectory() . '/file2.txt'); | ||
static::assertFileNotExists($context->getReferenceExecutionDirectory()); | ||
} | ||
|
||
/** | ||
* @return array<array{0: string}> | ||
*/ | ||
public function finishEvents(): array | ||
{ | ||
return [ | ||
['run.finish'], | ||
['verify.finish'], | ||
]; | ||
} | ||
} |