Skip to content

Commit

Permalink
Ensure user-provided SupportVectorMachine paths are valid (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
marmichalski authored and akondas committed Sep 2, 2017
1 parent ba2b8c8 commit 61d2b7d
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 9 deletions.
49 changes: 46 additions & 3 deletions src/Phpml/Exception/InvalidArgumentException.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static function arrayCantBeEmpty()
*/
public static function arraySizeToSmall($minimumSize = 2)
{
return new self(sprintf('The array must have at least %s elements', $minimumSize));
return new self(sprintf('The array must have at least %d elements', $minimumSize));
}

/**
Expand Down Expand Up @@ -73,7 +73,7 @@ public static function invalidClustersNumber()
*/
public static function invalidTarget($target)
{
return new self('Target with value '.$target.' is not part of the accepted classes');
return new self(sprintf('Target with value "%s" is not part of the accepted classes', $target));
}

/**
Expand All @@ -83,7 +83,7 @@ public static function invalidTarget($target)
*/
public static function invalidStopWordsLanguage(string $language)
{
return new self(sprintf('Can\'t find %s language for StopWords', $language));
return new self(sprintf('Can\'t find "%s" language for StopWords', $language));
}

/**
Expand All @@ -110,8 +110,51 @@ public static function invalidClassesNumber()
return new self('Provide at least 2 different classes');
}

/**
* @return InvalidArgumentException
*/
public static function inconsistentClasses()
{
return new self('The provided classes don\'t match the classes provided in the constructor');
}

/**
* @param string $file
*
* @return InvalidArgumentException
*/
public static function fileNotFound(string $file)
{
return new self(sprintf('File "%s" not found', $file));
}

/**
* @param string $file
*
* @return InvalidArgumentException
*/
public static function fileNotExecutable(string $file)
{
return new self(sprintf('File "%s" is not executable', $file));
}

/**
* @param string $path
*
* @return InvalidArgumentException
*/
public static function pathNotFound(string $path)
{
return new self(sprintf('The specified path "%s" does not exist', $path));
}

/**
* @param string $path
*
* @return InvalidArgumentException
*/
public static function pathNotWritable(string $path)
{
return new self(sprintf('The specified path "%s" is not writable', $path));
}
}
51 changes: 45 additions & 6 deletions src/Phpml/SupportVectorMachine/SupportVectorMachine.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Phpml\SupportVectorMachine;

use Phpml\Exception\InvalidArgumentException;
use Phpml\Helper\Trainable;

class SupportVectorMachine
Expand Down Expand Up @@ -140,25 +141,29 @@ public function __construct(
/**
* @param string $binPath
*
* @return $this
* @throws InvalidArgumentException
*/
public function setBinPath(string $binPath)
{
$this->binPath = $binPath;
$this->ensureDirectorySeparator($binPath);
$this->verifyBinPath($binPath);

return $this;
$this->binPath = $binPath;
}

/**
* @param string $varPath
*
* @return $this
* @throws InvalidArgumentException
*/
public function setVarPath(string $varPath)
{
$this->varPath = $varPath;
if (!is_writable($varPath)) {
throw InvalidArgumentException::pathNotWritable($varPath);
}

return $this;
$this->ensureDirectorySeparator($varPath);
$this->varPath = $varPath;
}

/**
Expand Down Expand Up @@ -270,4 +275,38 @@ private function buildTrainCommand(string $trainingSetFileName, string $modelFil
escapeshellarg($modelFileName)
);
}

/**
* @param string $path
*/
private function ensureDirectorySeparator(string &$path)
{
if (substr($path, -1) !== DIRECTORY_SEPARATOR) {
$path .= DIRECTORY_SEPARATOR;
}
}

/**
* @param string $path
*
* @throws InvalidArgumentException
*/
private function verifyBinPath(string $path)
{
if (!is_dir($path)) {
throw InvalidArgumentException::pathNotFound($path);
}

$osExtension = $this->getOSExtension();
foreach (['svm-predict', 'svm-scale', 'svm-train'] as $filename) {
$filePath = $path.$filename.$osExtension;
if (!file_exists($filePath)) {
throw InvalidArgumentException::fileNotFound($filePath);
}

if (!is_executable($filePath)) {
throw InvalidArgumentException::fileNotExecutable($filePath);
}
}
}
}
30 changes: 30 additions & 0 deletions tests/Phpml/SupportVectorMachine/SupportVectorMachineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,34 @@ public function testPredictSampleFromMultipleClassWithRbfKernel()
$this->assertEquals('b', $predictions[1]);
$this->assertEquals('c', $predictions[2]);
}

/**
* @expectedException \Phpml\Exception\InvalidArgumentException
* @expectedExceptionMessage is not writable
*/
public function testThrowExceptionWhenVarPathIsNotWritable()
{
$svm = new SupportVectorMachine(Type::C_SVC, Kernel::RBF);
$svm->setVarPath('var-path');
}

/**
* @expectedException \Phpml\Exception\InvalidArgumentException
* @expectedExceptionMessage does not exist
*/
public function testThrowExceptionWhenBinPathDoesNotExist()
{
$svm = new SupportVectorMachine(Type::C_SVC, Kernel::RBF);
$svm->setBinPath('bin-path');
}

/**
* @expectedException \Phpml\Exception\InvalidArgumentException
* @expectedExceptionMessage not found
*/
public function testThrowExceptionWhenFileIsNotFoundInBinPath()
{
$svm = new SupportVectorMachine(Type::C_SVC, Kernel::RBF);
$svm->setBinPath('var');
}
}

0 comments on commit 61d2b7d

Please sign in to comment.