public function testFailureWithNameAndReason() { $failure = Failure::fromNameAndReason('Some Check', 'Something went wrong yo'); $this->assertInstanceOf(ResultInterface::class, $failure); $this->assertEquals('Something went wrong yo', $failure->getReason()); $this->assertEquals('Some Check', $failure->getCheckName()); }
/** * @param EventDispatcher $eventDispatcher */ public function attach(EventDispatcher $eventDispatcher) { $studentClient = CouchDBClient::create(['dbname' => static::$studentDb]); $solutionClient = CouchDBClient::create(['dbname' => static::$solutionDb]); $studentClient->createDatabase($studentClient->getDatabase()); $solutionClient->createDatabase($solutionClient->getDatabase()); $eventDispatcher->listen('verify.start', function (Event $e) use($studentClient, $solutionClient) { $e->getParameter('exercise')->seed($studentClient); $this->replicateDbFromStudentToSolution($studentClient, $solutionClient); }); $eventDispatcher->listen('run.start', function (Event $e) use($studentClient) { $e->getParameter('exercise')->seed($studentClient); }); $eventDispatcher->listen('cli.verify.reference-execute.pre', function (CliExecuteEvent $e) { $e->prependArg('phpschool'); }); $eventDispatcher->listen(['cli.verify.student-execute.pre', 'cli.run.student-execute.pre'], function (CliExecuteEvent $e) { $e->prependArg('phpschool-student'); }); $eventDispatcher->insertVerifier('verify.finish', function (Event $e) use($studentClient) { $verifyResult = $e->getParameter('exercise')->verify($studentClient); if (false === $verifyResult) { return Failure::fromNameAndReason($this->getName(), 'Database verification failed'); } return Success::fromCheck($this); }); $eventDispatcher->listen(['cli.verify.reference-execute.fail', 'verify.finish', 'run.finish'], function (Event $e) use($studentClient, $solutionClient) { $studentClient->deleteDatabase(static::$studentDb); $solutionClient->deleteDatabase(static::$solutionDb); }); }
/** * @param ExerciseDispatcher $exerciseDispatcher */ public function configure(ExerciseDispatcher $exerciseDispatcher) { $eventDispatcher = $exerciseDispatcher->getEventDispatcher(); $appendArgsListener = function (CliExecuteEvent $event) { $event->appendArg('127.0.0.1'); $event->appendArg($this->getRandomPort()); }; $eventDispatcher->listen('cli.verify.reference-execute.pre', $appendArgsListener); $eventDispatcher->listen('cli.verify.student-execute.pre', $appendArgsListener); $eventDispatcher->listen('cli.run.student-execute.pre', $appendArgsListener); $eventDispatcher->listen('cli.verify.reference.executing', function (CliExecuteEvent $event) { $args = $event->getArgs()->getArrayCopy(); $client = $this->socketFactory->createClient(...$args); //wait for server to boot usleep(100000); $client->connect(); $client->readAll(); //wait for shutdown usleep(100000); }); $eventDispatcher->insertVerifier('cli.verify.student.executing', function (CliExecuteEvent $event) { $args = $event->getArgs()->getArrayCopy(); $client = $this->socketFactory->createClient(...$args); //wait for server to boot usleep(100000); try { $client->connect(); } catch (Exception $e) { return Failure::fromNameAndReason($this->getName(), $e->getMessage()); } $out = $client->readAll(); //wait for shutdown usleep(100000); $date = new \DateTime(); //match the current date but any seconds //since we can't mock time in PHP easily if (!preg_match(sprintf('/^%s:([0-5][0-9]|60)\\n$/', $date->format('Y-m-d H:i')), $out)) { return new StdOutFailure($this->getName(), $date->format("Y-m-d H:i:s\n"), $out); } return new Success($this->getName()); }); $eventDispatcher->listen('cli.run.student.executing', function (CliExecuteEvent $event) { /** @var OutputInterface $output */ $output = $event->getParameter('output'); $args = $event->getArgs()->getArrayCopy(); $client = $this->socketFactory->createClient(...$args); //wait for server to boot usleep(100000); $client->connect(); $out = $client->readAll(); //wait for shutdown usleep(100000); $output->write($out); }); }
/** * @param string $fileName * @return ResultInterface */ public function check($fileName) { $statements = $this->parser->parse(file_get_contents($fileName)); $include = null; foreach ($statements as $statement) { if ($statement instanceof Include_) { $include = $statement; break; } } if (null === $include) { return Failure::fromNameAndReason($this->getName(), 'No require statement found'); } return new Success($this->getName()); }
/** * Here we attach to various events to seed, verify and inject the DSN's * to the student & reference solution programs's CLI arguments. * * @param EventDispatcher $eventDispatcher */ public function attach(EventDispatcher $eventDispatcher) { if (file_exists($this->databaseDirectory)) { throw new \RuntimeException(sprintf('Database directory: "%s" already exists', $this->databaseDirectory)); } mkdir($this->databaseDirectory, 0777, true); try { $db = new PDO($this->userDsn); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (\PDOException $e) { rmdir($this->databaseDirectory); throw $e; } $eventDispatcher->listen('verify.start', function (Event $e) use($db) { $e->getParameter('exercise')->seed($db); //make a copy - so solution can modify without effecting database user has access to copy($this->userDatabasePath, $this->solutionDatabasePath); }); $eventDispatcher->listen('run.start', function (Event $e) use($db) { $e->getParameter('exercise')->seed($db); }); $eventDispatcher->listen('cli.verify.reference-execute.pre', function (CliExecuteEvent $e) { $e->prependArg($this->solutionDsn); }); $eventDispatcher->listen(['cli.verify.student-execute.pre', 'cli.run.student-execute.pre'], function (CliExecuteEvent $e) { $e->prependArg($this->userDsn); }); $eventDispatcher->insertVerifier('verify.finish', function (Event $e) use($db) { $verifyResult = $e->getParameter('exercise')->verify($db); if (false === $verifyResult) { return Failure::fromNameAndReason($this->getName(), 'Database verification failed'); } return new Success('Database Verification Check'); }); $eventDispatcher->listen(['cli.verify.reference-execute.fail', 'verify.finish', 'run.finish'], function (Event $e) use($db) { unset($db); @unlink($this->userDatabasePath); @unlink($this->solutionDatabasePath); rmdir($this->databaseDirectory); }); }