Commit 2a99015a authored by Will Banfield's avatar Will Banfield Committed by Jeremy Mikola

added many many more tests, added getIdFromStream

parent 9d1a9cba
...@@ -161,6 +161,16 @@ class Bucket ...@@ -161,6 +161,16 @@ class Bucket
{ {
return $this->collectionsWrapper->getFilesCollection()->find($filter, $options); return $this->collectionsWrapper->getFilesCollection()->find($filter, $options);
} }
public function getIdFromStream($stream)
{
$metadata = stream_get_meta_data($stream);
if(isset($metadata["wrapper_data"]->id)){
return $metadata["wrapper_data"]->id;
}
return null;
}
public function getCollectionsWrapper() public function getCollectionsWrapper()
{ {
return $this->collectionsWrapper; return $this->collectionsWrapper;
......
...@@ -26,15 +26,17 @@ class GridFsDownload ...@@ -26,15 +26,17 @@ class GridFsDownload
* *
* *
* @param GridFSCollectionsWrapper $collectionsWrapper File options * @param GridFSCollectionsWrapper $collectionsWrapper File options
* @param \MongoDB\BSON\ObjectId $options File options * @param \stdClass $file GridFS file to use
* @param array $options File options * @throws GridFSCorruptFileException
* @throws FileNotFoundException
*/ */
public function __construct( public function __construct(
GridFSCollectionsWrapper $collectionsWrapper, GridFSCollectionsWrapper $collectionsWrapper,
$file $file
) )
{ {
if(!($file instanceof \stdClass)){
throw new \MongoDB\Exception\InvalidArgumentTypeException('"file"', $file, 'stdClass');
}
$this->collectionsWrapper = $collectionsWrapper; $this->collectionsWrapper = $collectionsWrapper;
$this->file = $file; $this->file = $file;
try{ try{
...@@ -81,12 +83,11 @@ class GridFsDownload ...@@ -81,12 +83,11 @@ class GridFsDownload
$this->bufferEmpty=true; $this->bufferEmpty=true;
$bytesLeft = $numToRead - strlen($output); $bytesLeft = $numToRead - strlen($output);
while(strlen($output) < $numToRead && $this->advanceChunks()) { while(strlen($output) < $numToRead && $this->advanceChunks()) {
$bytesLeft = $numToRead - strlen($output); $bytesLeft = $numToRead - strlen($output);
$output .= substr($this->chunksIterator->current()->data->getData(), 0, $bytesLeft); $output .= substr($this->chunksIterator->current()->data->getData(), 0, $bytesLeft);
} }
if ($this->file->length > 0 && $bytesLeft < strlen($this->chunksIterator->current()->data->getData())) { if (!$this->iteratorEmpty && $this->file->length > 0 && $bytesLeft < strlen($this->chunksIterator->current()->data->getData())) {
fwrite($this->buffer, substr($this->chunksIterator->current()->data->getData(), $bytesLeft)); fwrite($this->buffer, substr($this->chunksIterator->current()->data->getData(), $bytesLeft));
$this->bufferEmpty=false; $this->bufferEmpty=false;
} }
......
...@@ -73,14 +73,14 @@ class GridFsUpload ...@@ -73,14 +73,14 @@ class GridFsUpload
if (is_string($options['contentType'])) { if (is_string($options['contentType'])) {
$fileOptions['contentType'] = $options['contentType']; $fileOptions['contentType'] = $options['contentType'];
} else { } else {
throw new InvalidArgumentTypeException('"contentType" option', $options['contentType'], 'string'); throw new \MongoDB\Exception\InvalidArgumentTypeException('"contentType" option', $options['contentType'], 'string');
} }
} }
if (isset($options['aliases'])) { if (isset($options['aliases'])) {
if (\MongoDB\is_string_array($options['aliases'])) { if (\MongoDB\is_string_array($options['aliases'])) {
$fileOptions['aliases'] = $options['aliases']; $fileOptions['aliases'] = $options['aliases'];
} else { } else {
throw new InvalidArgumentTypeException('"aliases" option', $options['aliases'], 'array of strings'); throw new \MongoDB\Exception\InvalidArgumentTypeException('"aliases" option', $options['aliases'], 'array of strings');
} }
} }
...@@ -88,7 +88,7 @@ class GridFsUpload ...@@ -88,7 +88,7 @@ class GridFsUpload
if (is_array($options['metadata']) || is_object($options['metadata'])) { if (is_array($options['metadata']) || is_object($options['metadata'])) {
$fileOptions['metadata'] = $options['metadata']; $fileOptions['metadata'] = $options['metadata'];
} else { } else {
throw new InvalidArgumentTypeException('"metadata" option', $options['metadata'], 'object or array'); throw new \MongoDB\Exception\InvalidArgumentTypeException('"metadata" option', $options['metadata'], 'object or array');
} }
} }
$this->file = array_merge($main_file, $fileOptions); $this->file = array_merge($main_file, $fileOptions);
...@@ -173,6 +173,10 @@ class GridFsUpload ...@@ -173,6 +173,10 @@ class GridFsUpload
{ {
return $this->file; return $this->file;
} }
public function isEOF()
{
return false;
}
private function insertChunk($data) private function insertChunk($data)
{ {
$toUpload = ["files_id" => $this->file['_id'], "n" => $this->chunkOffset, "data" => new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_GENERIC)]; $toUpload = ["files_id" => $this->file['_id'], "n" => $this->chunkOffset, "data" => new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_GENERIC)];
......
...@@ -22,6 +22,7 @@ class StreamWrapper ...@@ -22,6 +22,7 @@ class StreamWrapper
private $mode; private $mode;
private $gridFsStream; private $gridFsStream;
private $collectionsWrapper; private $collectionsWrapper;
public $id;
/** /**
* Register the GridFS stream wrapper. * Register the GridFS stream wrapper.
...@@ -54,7 +55,6 @@ class StreamWrapper ...@@ -54,7 +55,6 @@ class StreamWrapper
{ {
$stat = $this->getStatTemplate(); $stat = $this->getStatTemplate();
$stat[7] = $stat['size'] = $this->gridFsStream->getSize(); $stat[7] = $stat['size'] = $this->gridFsStream->getSize();
$stat[2] = $stat['mode'] = $this->mode;
return $stat; return $stat;
} }
public function stream_open($path, $mode, $options, &$openedPath) public function stream_open($path, $mode, $options, &$openedPath)
...@@ -73,12 +73,14 @@ class StreamWrapper ...@@ -73,12 +73,14 @@ class StreamWrapper
$context = stream_context_get_options($this->context); $context = stream_context_get_options($this->context);
$options =$context['gridfs']['uploadOptions']; $options =$context['gridfs']['uploadOptions'];
$this->gridFsStream = new GridFsUpload($this->collectionsWrapper, $this->identifier, $options); $this->gridFsStream = new GridFsUpload($this->collectionsWrapper, $this->identifier, $options);
$this->id = $this->gridFsStream->getId();
return true; return true;
} }
public function openReadStream() { public function openReadStream() {
$context = stream_context_get_options($this->context); $context = stream_context_get_options($this->context);
$this->gridFsStream = new GridFsDownload($this->collectionsWrapper, $context['gridfs']['file']); $this->gridFsStream = new GridFsDownload($this->collectionsWrapper, $context['gridfs']['file']);
$this->id = $this->gridFsStream->getId();
return true; return true;
} }
......
...@@ -114,20 +114,20 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -114,20 +114,20 @@ class BucketFunctionalTest extends FunctionalTestCase
public function testGetLastVersion() public function testGetLastVersion()
{ {
$idOne = $this->bucket->uploadFromStream("test",$this->generateStream("foo")); $idOne = $this->bucket->uploadFromStream("test",$this->generateStream("foo"));
//$streamTwo = $this->bucket->openUploadStream("test"); $streamTwo = $this->bucket->openUploadStream("test");
//fwrite($streamTwo, "bar"); fwrite($streamTwo, "bar");
//echo "Calling FSTAT\n"; //echo "Calling FSTAT\n";
//$stat = fstat($streamTwo); //$stat = fstat($streamTwo);
//$idTwo = $stat['uid']; $idTwo = $this->bucket->getIdFromStream($streamTwo);
//var_dump //var_dump
//var_dump($idTwo); //var_dump($idTwo);
//fclose($streamTwo); fclose($streamTwo);
$idThree = $this->bucket->uploadFromStream("test",$this->generateStream("baz")); $idThree = $this->bucket->uploadFromStream("test",$this->generateStream("baz"));
$this->assertEquals("baz", stream_get_contents($this->bucket->openDownloadStreamByName("test"))); $this->assertEquals("baz", stream_get_contents($this->bucket->openDownloadStreamByName("test")));
$this->bucket->delete($idThree); $this->bucket->delete($idThree);
//$this->assertEquals("bar", stream_get_contents($this->bucket->openDownloadStreamByName("test"))); $this->assertEquals("bar", stream_get_contents($this->bucket->openDownloadStreamByName("test")));
//$this->bucket->delete($idTwo); $this->bucket->delete($idTwo);
$this->assertEquals("foo", stream_get_contents($this->bucket->openDownloadStreamByName("test"))); $this->assertEquals("foo", stream_get_contents($this->bucket->openDownloadStreamByName("test")));
$this->bucket->delete($idOne); $this->bucket->delete($idOne);
$error = null; $error = null;
...@@ -207,6 +207,42 @@ class BucketFunctionalTest extends FunctionalTestCase ...@@ -207,6 +207,42 @@ class BucketFunctionalTest extends FunctionalTestCase
$testStream = fopen($testPath, "r"); $testStream = fopen($testPath, "r");
$id = $this->bucket->uploadFromStream("BigInsertTest", $testStream); $id = $this->bucket->uploadFromStream("BigInsertTest", $testStream);
} }
public function testGetIdFromStream()
{
$upload = $this->bucket->openUploadStream("test");
$id = $this->bucket->getIdFromStream($upload);
fclose($upload);
$this->assertTrue($id instanceof \MongoDB\BSON\ObjectId);
$download = $this->bucket->openDownloadStream($id);
$id=null;
$id = $this->bucket->getIdFromStream($download);
fclose($download);
$this->assertTrue($id instanceof \MongoDB\BSON\ObjectId);
}
/**
*@dataProvider provideInsertChunks
*/
public function testProvidedMultipleReads($data)
{
$upload = $this->bucket->openUploadStream("test", ["chunkSizeBytes"=>rand(1, 5)]);
fwrite($upload,$data);
$id = $this->bucket->getIdFromStream($upload);
fclose($upload);
$download = $this->bucket->openDownloadStream($id);
$readPos = 0;
while($readPos < strlen($data)){
$numToRead = rand(1, strlen($data) - $readPos);
$expected = substr($data, $readPos, $numToRead);
$actual = fread($download, $numToRead);
$this->assertEquals($expected,$actual);
$readPos+= $numToRead;
}
$actual = fread($download, 5);
$expected = "";
$this->assertEquals($expected,$actual);
fclose($download);
}
private function generateStream($input) private function generateStream($input)
{ {
$stream = fopen('php://temp', 'w+'); $stream = fopen('php://temp', 'w+');
......
...@@ -37,4 +37,26 @@ abstract class FunctionalTestCase extends BaseFunctionalTestCase ...@@ -37,4 +37,26 @@ abstract class FunctionalTestCase extends BaseFunctionalTestCase
return; return;
} }
} }
public function provideInsertChunks()
{
$dataVals = [];
$testArgs[][] = "hello world";
$testArgs[][] = "1234567890";
$testArgs[][] = "~!@#$%^&*()_+";
for($j=0; $j<30; $j++){
$randomTest = "";
for($i=0; $i<100; $i++){
$randomTest .= chr(rand(0, 256));
}
$testArgs[][] = $randomTest;
}
$utf8="";
for($i=0; $i<256; $i++){
$utf8 .= chr($i);
}
$testArgs[][]=$utf8;
return $testArgs;
}
} }
...@@ -10,35 +10,6 @@ use MongoDB\GridFS; ...@@ -10,35 +10,6 @@ use MongoDB\GridFS;
class GridFsStreamTest extends FunctionalTestCase class GridFsStreamTest extends FunctionalTestCase
{ {
/* public function testConstructorOptionTypeChecks(array $options)
{
new \MongoDB\GridFS\Bucket($this->manager, $this->getDatabaseName(), $options);
}
public function provideInvalidConstructorOptions()
{
$options = [];
$invalidBucketNames = [123, 3.14, true, [], new \stdClass];
$invalidChunkSizes = ['foo', 3.14, true, [], new \stdClass];
foreach ($this->getInvalidReadPreferenceValues() as $value) {
$options[][] = ['readPreference' => $value];
}
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
foreach ($invalidBucketNames as $value) {
$options[][] = ['bucketName' => $value];
}
foreach ($invalidChunkSizes as $value) {
$options[][] = ['chunkSizeBytes' => $value];
}
return $options;
}
*/
public function testBasic() public function testBasic()
{ {
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test"); $upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test");
...@@ -177,31 +148,122 @@ class GridFsStreamTest extends FunctionalTestCase ...@@ -177,31 +148,122 @@ class GridFsStreamTest extends FunctionalTestCase
$this->assertEquals($data, stream_get_contents($stream)); $this->assertEquals($data, stream_get_contents($stream));
} }
public function provideInsertChunks() public function testMultiChunkFile()
{ {
$dataVals = []; $toUpload="";
$testArgs[][] = "hello world"; for($i=0; $i<255*1024+1000; $i++){
$testArgs[][] = "1234567890"; $toUpload .= "a";
$testArgs[][] = "~!@#$%^&*()_+";
for($j=0; $j<10; $j++){
$randomTest = "";
for($i=0; $i<100; $i++){
$randomTest .= chr(rand(0, 256));
}
$testArgs[][] = $randomTest;
} }
$utf8=""; $upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test");
for($i=0; $i<256; $i++){ $upload->insertChunks($toUpload);
$utf8 .= chr($i); $upload->close();
$this->assertEquals(1, $this->collectionsWrapper->getFilesCollection()->count());
$this->assertEquals(2, $this->collectionsWrapper->getChunksCollection()->count());
$download = $this->bucket->openDownloadStream($upload->getId());
$this->assertEquals($toUpload, stream_get_contents($download));
}
/**
*@dataProvider provideInsertChunks
*/
public function testSmallChunks($data)
{
$options = ["chunkSizeBytes"=>1];
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test", $options);
$upload->insertChunks($data);
$upload->close();
$this->assertEquals(strlen($data), $this->collectionsWrapper->getChunksCollection()->count());
$this->assertEquals(1, $this->collectionsWrapper->getFilesCollection()->count());
$stream = $this->bucket->openDownloadStream($upload->getId());
$this->assertEquals($data, stream_get_contents($stream));
}
public function testMultipleReads()
{
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test", ["chunkSizeBytes"=>3]);
$upload->insertChunks("hello world");
$upload->close();
$file = $this->collectionsWrapper->getFilesCollection()->findOne(["_id"=>$upload->getId()]);
$download = new \MongoDB\GridFS\GridFsDownload($this->collectionsWrapper, $file);
$this->assertEquals("he", $download->downloadNumBytes(2));
$this->assertEquals("ll", $download->downloadNumBytes(2));
$this->assertEquals("o ", $download->downloadNumBytes(2));
$this->assertEquals("wo", $download->downloadNumBytes(2));
$this->assertEquals("rl", $download->downloadNumBytes(2));
$this->assertEquals("d", $download->downloadNumBytes(2));
$this->assertEquals("", $download->downloadNumBytes(2));
$this->assertEquals("", $download->downloadNumBytes(2));
$download->close();
}
/**
*@dataProvider provideInsertChunks
*/
public function testProvidedMultipleReads($data)
{
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test", ["chunkSizeBytes"=>rand(1, 5)]);
$upload->insertChunks($data);
$upload->close();
$file = $this->collectionsWrapper->getFilesCollection()->findOne(["_id"=>$upload->getId()]);
$download = new \MongoDB\GridFS\GridFsDownload($this->collectionsWrapper, $file);
$readPos = 0;
while($readPos < strlen($data)){
$numToRead = rand(1, strlen($data) - $readPos);
$expected = substr($data, $readPos, $numToRead);
$actual = $download->downloadNumBytes($numToRead);
$this->assertEquals($expected,$actual);
$readPos+= $numToRead;
} }
$testArgs[][]=$utf8; $actual = $download->downloadNumBytes(5);
return $testArgs; $expected = "";
$this->assertEquals($expected,$actual);
$download->close();
} }
private function generateStream($input) /**
* @expectedException \MongoDB\Exception\InvalidArgumentTypeException
* @dataProvider provideInvalidUploadConstructorOptions
*/
public function testUploadConstructorOptionTypeChecks(array $options)
{ {
$stream = fopen('php://temp', 'w+'); new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper,"test", $options);
fwrite($stream, $input); }
rewind($stream);
return $stream; public function provideInvalidUploadConstructorOptions()
{
$options = [];
$invalidContentType = [123, 3.14, true, [], new \stdClass];
$invalidAliases = ['foo', 3.14, true, [12, 34], new \stdClass];
$invalidMetadata = ['foo', 3.14, true];
foreach ($invalidContentType as $value) {
$options[][] = ['contentType' => $value];
}
foreach ($invalidAliases as $value) {
$options[][] = ['aliases' => $value];
}
foreach ($invalidMetadata as $value) {
$options[][] = ['metadata' => $value];
}
return $options;
}
/**
* @expectedException \MongoDB\Exception\InvalidArgumentTypeException
* @dataProvider provideInvalidDownloadConstructorFile
*/
public function testDownloadConstructorFileCheck($file)
{
$download = new \MongoDB\GridFS\GridFsDownload($this->collectionsWrapper, $file);
}
public function provideInvalidDownloadConstructorFile()
{
$files = [];
$invalidFiles = [123, 3.14, true, []];
foreach ($invalidFiles as $value) {
$files[][] = $value;
}
return $files;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment