Skip to content

Commit 2a99015

Browse files
Will Banfieldjmikola
authored andcommitted
added many many more tests, added getIdFromStream
1 parent 9d1a9cb commit 2a99015

File tree

7 files changed

+202
-65
lines changed

7 files changed

+202
-65
lines changed

src/GridFS/Bucket.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@ public function find($filter, array $options =[])
161161
{
162162
return $this->collectionsWrapper->getFilesCollection()->find($filter, $options);
163163
}
164+
165+
public function getIdFromStream($stream)
166+
{
167+
$metadata = stream_get_meta_data($stream);
168+
if(isset($metadata["wrapper_data"]->id)){
169+
return $metadata["wrapper_data"]->id;
170+
}
171+
return null;
172+
}
173+
164174
public function getCollectionsWrapper()
165175
{
166176
return $this->collectionsWrapper;

src/GridFS/GridFsDownload.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,17 @@ class GridFsDownload
2626
*
2727
*
2828
* @param GridFSCollectionsWrapper $collectionsWrapper File options
29-
* @param \MongoDB\BSON\ObjectId $options File options
30-
* @param array $options File options
31-
* @throws FileNotFoundException
29+
* @param \stdClass $file GridFS file to use
30+
* @throws GridFSCorruptFileException
3231
*/
3332
public function __construct(
3433
GridFSCollectionsWrapper $collectionsWrapper,
3534
$file
3635
)
3736
{
37+
if(!($file instanceof \stdClass)){
38+
throw new \MongoDB\Exception\InvalidArgumentTypeException('"file"', $file, 'stdClass');
39+
}
3840
$this->collectionsWrapper = $collectionsWrapper;
3941
$this->file = $file;
4042
try{
@@ -81,12 +83,11 @@ public function downloadNumBytes($numToRead) {
8183
$this->bufferEmpty=true;
8284

8385
$bytesLeft = $numToRead - strlen($output);
84-
8586
while(strlen($output) < $numToRead && $this->advanceChunks()) {
8687
$bytesLeft = $numToRead - strlen($output);
8788
$output .= substr($this->chunksIterator->current()->data->getData(), 0, $bytesLeft);
8889
}
89-
if ($this->file->length > 0 && $bytesLeft < strlen($this->chunksIterator->current()->data->getData())) {
90+
if (!$this->iteratorEmpty && $this->file->length > 0 && $bytesLeft < strlen($this->chunksIterator->current()->data->getData())) {
9091
fwrite($this->buffer, substr($this->chunksIterator->current()->data->getData(), $bytesLeft));
9192
$this->bufferEmpty=false;
9293
}

src/GridFS/GridFsUpload.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,22 @@ public function __construct(
7373
if (is_string($options['contentType'])) {
7474
$fileOptions['contentType'] = $options['contentType'];
7575
} else {
76-
throw new InvalidArgumentTypeException('"contentType" option', $options['contentType'], 'string');
76+
throw new \MongoDB\Exception\InvalidArgumentTypeException('"contentType" option', $options['contentType'], 'string');
7777
}
7878
}
7979
if (isset($options['aliases'])) {
8080
if (\MongoDB\is_string_array($options['aliases'])) {
8181
$fileOptions['aliases'] = $options['aliases'];
8282
} else {
83-
throw new InvalidArgumentTypeException('"aliases" option', $options['aliases'], 'array of strings');
83+
throw new \MongoDB\Exception\InvalidArgumentTypeException('"aliases" option', $options['aliases'], 'array of strings');
8484
}
8585
}
8686

8787
if (isset($options['metadata'])) {
8888
if (is_array($options['metadata']) || is_object($options['metadata'])) {
8989
$fileOptions['metadata'] = $options['metadata'];
9090
} else {
91-
throw new InvalidArgumentTypeException('"metadata" option', $options['metadata'], 'object or array');
91+
throw new \MongoDB\Exception\InvalidArgumentTypeException('"metadata" option', $options['metadata'], 'object or array');
9292
}
9393
}
9494
$this->file = array_merge($main_file, $fileOptions);
@@ -173,6 +173,10 @@ public function getFile()
173173
{
174174
return $this->file;
175175
}
176+
public function isEOF()
177+
{
178+
return false;
179+
}
176180
private function insertChunk($data)
177181
{
178182
$toUpload = ["files_id" => $this->file['_id'], "n" => $this->chunkOffset, "data" => new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_GENERIC)];

src/GridFS/StreamWrapper.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class StreamWrapper
2222
private $mode;
2323
private $gridFsStream;
2424
private $collectionsWrapper;
25+
public $id;
2526

2627
/**
2728
* Register the GridFS stream wrapper.
@@ -54,7 +55,6 @@ public function stream_stat()
5455
{
5556
$stat = $this->getStatTemplate();
5657
$stat[7] = $stat['size'] = $this->gridFsStream->getSize();
57-
$stat[2] = $stat['mode'] = $this->mode;
5858
return $stat;
5959
}
6060
public function stream_open($path, $mode, $options, &$openedPath)
@@ -73,12 +73,14 @@ public function openWriteStream() {
7373
$context = stream_context_get_options($this->context);
7474
$options =$context['gridfs']['uploadOptions'];
7575
$this->gridFsStream = new GridFsUpload($this->collectionsWrapper, $this->identifier, $options);
76+
$this->id = $this->gridFsStream->getId();
7677
return true;
7778
}
7879

7980
public function openReadStream() {
8081
$context = stream_context_get_options($this->context);
8182
$this->gridFsStream = new GridFsDownload($this->collectionsWrapper, $context['gridfs']['file']);
83+
$this->id = $this->gridFsStream->getId();
8284
return true;
8385
}
8486

tests/GridFS/BucketFunctionalTest.php

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,20 +114,20 @@ public function testUploadEnsureIndexes()
114114
public function testGetLastVersion()
115115
{
116116
$idOne = $this->bucket->uploadFromStream("test",$this->generateStream("foo"));
117-
//$streamTwo = $this->bucket->openUploadStream("test");
118-
//fwrite($streamTwo, "bar");
117+
$streamTwo = $this->bucket->openUploadStream("test");
118+
fwrite($streamTwo, "bar");
119119
//echo "Calling FSTAT\n";
120120
//$stat = fstat($streamTwo);
121-
//$idTwo = $stat['uid'];
121+
$idTwo = $this->bucket->getIdFromStream($streamTwo);
122122
//var_dump
123123
//var_dump($idTwo);
124-
//fclose($streamTwo);
124+
fclose($streamTwo);
125125

126126
$idThree = $this->bucket->uploadFromStream("test",$this->generateStream("baz"));
127127
$this->assertEquals("baz", stream_get_contents($this->bucket->openDownloadStreamByName("test")));
128128
$this->bucket->delete($idThree);
129-
//$this->assertEquals("bar", stream_get_contents($this->bucket->openDownloadStreamByName("test")));
130-
//$this->bucket->delete($idTwo);
129+
$this->assertEquals("bar", stream_get_contents($this->bucket->openDownloadStreamByName("test")));
130+
$this->bucket->delete($idTwo);
131131
$this->assertEquals("foo", stream_get_contents($this->bucket->openDownloadStreamByName("test")));
132132
$this->bucket->delete($idOne);
133133
$error = null;
@@ -207,6 +207,42 @@ public function testBigInsert()
207207
$testStream = fopen($testPath, "r");
208208
$id = $this->bucket->uploadFromStream("BigInsertTest", $testStream);
209209
}
210+
public function testGetIdFromStream()
211+
{
212+
$upload = $this->bucket->openUploadStream("test");
213+
$id = $this->bucket->getIdFromStream($upload);
214+
fclose($upload);
215+
$this->assertTrue($id instanceof \MongoDB\BSON\ObjectId);
216+
217+
$download = $this->bucket->openDownloadStream($id);
218+
$id=null;
219+
$id = $this->bucket->getIdFromStream($download);
220+
fclose($download);
221+
$this->assertTrue($id instanceof \MongoDB\BSON\ObjectId);
222+
}
223+
/**
224+
*@dataProvider provideInsertChunks
225+
*/
226+
public function testProvidedMultipleReads($data)
227+
{
228+
$upload = $this->bucket->openUploadStream("test", ["chunkSizeBytes"=>rand(1, 5)]);
229+
fwrite($upload,$data);
230+
$id = $this->bucket->getIdFromStream($upload);
231+
fclose($upload);
232+
$download = $this->bucket->openDownloadStream($id);
233+
$readPos = 0;
234+
while($readPos < strlen($data)){
235+
$numToRead = rand(1, strlen($data) - $readPos);
236+
$expected = substr($data, $readPos, $numToRead);
237+
$actual = fread($download, $numToRead);
238+
$this->assertEquals($expected,$actual);
239+
$readPos+= $numToRead;
240+
}
241+
$actual = fread($download, 5);
242+
$expected = "";
243+
$this->assertEquals($expected,$actual);
244+
fclose($download);
245+
}
210246
private function generateStream($input)
211247
{
212248
$stream = fopen('php://temp', 'w+');

tests/GridFS/FunctionalTestCase.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,26 @@ public function tearDown()
3737
return;
3838
}
3939
}
40+
41+
public function provideInsertChunks()
42+
{
43+
$dataVals = [];
44+
$testArgs[][] = "hello world";
45+
$testArgs[][] = "1234567890";
46+
$testArgs[][] = "~!@#$%^&*()_+";
47+
for($j=0; $j<30; $j++){
48+
$randomTest = "";
49+
for($i=0; $i<100; $i++){
50+
$randomTest .= chr(rand(0, 256));
51+
}
52+
$testArgs[][] = $randomTest;
53+
}
54+
$utf8="";
55+
for($i=0; $i<256; $i++){
56+
$utf8 .= chr($i);
57+
}
58+
$testArgs[][]=$utf8;
59+
return $testArgs;
60+
}
61+
4062
}

tests/GridFS/GridFsStreamTest.php

Lines changed: 112 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,6 @@
1010
class GridFsStreamTest extends FunctionalTestCase
1111
{
1212

13-
/* public function testConstructorOptionTypeChecks(array $options)
14-
{
15-
new \MongoDB\GridFS\Bucket($this->manager, $this->getDatabaseName(), $options);
16-
}
17-
18-
public function provideInvalidConstructorOptions()
19-
{
20-
$options = [];
21-
$invalidBucketNames = [123, 3.14, true, [], new \stdClass];
22-
$invalidChunkSizes = ['foo', 3.14, true, [], new \stdClass];
23-
24-
25-
foreach ($this->getInvalidReadPreferenceValues() as $value) {
26-
$options[][] = ['readPreference' => $value];
27-
}
28-
29-
foreach ($this->getInvalidWriteConcernValues() as $value) {
30-
$options[][] = ['writeConcern' => $value];
31-
}
32-
foreach ($invalidBucketNames as $value) {
33-
$options[][] = ['bucketName' => $value];
34-
}
35-
foreach ($invalidChunkSizes as $value) {
36-
$options[][] = ['chunkSizeBytes' => $value];
37-
}
38-
39-
return $options;
40-
}
41-
*/
4213
public function testBasic()
4314
{
4415
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test");
@@ -177,31 +148,122 @@ public function testInsertChunks($data)
177148
$this->assertEquals($data, stream_get_contents($stream));
178149
}
179150

180-
public function provideInsertChunks()
151+
public function testMultiChunkFile()
181152
{
182-
$dataVals = [];
183-
$testArgs[][] = "hello world";
184-
$testArgs[][] = "1234567890";
185-
$testArgs[][] = "~!@#$%^&*()_+";
186-
for($j=0; $j<10; $j++){
187-
$randomTest = "";
188-
for($i=0; $i<100; $i++){
189-
$randomTest .= chr(rand(0, 256));
190-
}
191-
$testArgs[][] = $randomTest;
153+
$toUpload="";
154+
for($i=0; $i<255*1024+1000; $i++){
155+
$toUpload .= "a";
192156
}
193-
$utf8="";
194-
for($i=0; $i<256; $i++){
195-
$utf8 .= chr($i);
157+
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test");
158+
$upload->insertChunks($toUpload);
159+
$upload->close();
160+
161+
$this->assertEquals(1, $this->collectionsWrapper->getFilesCollection()->count());
162+
$this->assertEquals(2, $this->collectionsWrapper->getChunksCollection()->count());
163+
164+
$download = $this->bucket->openDownloadStream($upload->getId());
165+
$this->assertEquals($toUpload, stream_get_contents($download));
166+
}
167+
/**
168+
*@dataProvider provideInsertChunks
169+
*/
170+
public function testSmallChunks($data)
171+
{
172+
$options = ["chunkSizeBytes"=>1];
173+
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test", $options);
174+
$upload->insertChunks($data);
175+
$upload->close();
176+
177+
$this->assertEquals(strlen($data), $this->collectionsWrapper->getChunksCollection()->count());
178+
$this->assertEquals(1, $this->collectionsWrapper->getFilesCollection()->count());
179+
180+
$stream = $this->bucket->openDownloadStream($upload->getId());
181+
$this->assertEquals($data, stream_get_contents($stream));
182+
}
183+
public function testMultipleReads()
184+
{
185+
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test", ["chunkSizeBytes"=>3]);
186+
$upload->insertChunks("hello world");
187+
$upload->close();
188+
$file = $this->collectionsWrapper->getFilesCollection()->findOne(["_id"=>$upload->getId()]);
189+
$download = new \MongoDB\GridFS\GridFsDownload($this->collectionsWrapper, $file);
190+
$this->assertEquals("he", $download->downloadNumBytes(2));
191+
$this->assertEquals("ll", $download->downloadNumBytes(2));
192+
$this->assertEquals("o ", $download->downloadNumBytes(2));
193+
$this->assertEquals("wo", $download->downloadNumBytes(2));
194+
$this->assertEquals("rl", $download->downloadNumBytes(2));
195+
$this->assertEquals("d", $download->downloadNumBytes(2));
196+
$this->assertEquals("", $download->downloadNumBytes(2));
197+
$this->assertEquals("", $download->downloadNumBytes(2));
198+
$download->close();
199+
}
200+
/**
201+
*@dataProvider provideInsertChunks
202+
*/
203+
public function testProvidedMultipleReads($data)
204+
{
205+
$upload = new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper, "test", ["chunkSizeBytes"=>rand(1, 5)]);
206+
$upload->insertChunks($data);
207+
$upload->close();
208+
$file = $this->collectionsWrapper->getFilesCollection()->findOne(["_id"=>$upload->getId()]);
209+
$download = new \MongoDB\GridFS\GridFsDownload($this->collectionsWrapper, $file);
210+
211+
$readPos = 0;
212+
while($readPos < strlen($data)){
213+
$numToRead = rand(1, strlen($data) - $readPos);
214+
$expected = substr($data, $readPos, $numToRead);
215+
$actual = $download->downloadNumBytes($numToRead);
216+
$this->assertEquals($expected,$actual);
217+
$readPos+= $numToRead;
196218
}
197-
$testArgs[][]=$utf8;
198-
return $testArgs;
219+
$actual = $download->downloadNumBytes(5);
220+
$expected = "";
221+
$this->assertEquals($expected,$actual);
222+
$download->close();
199223
}
200-
private function generateStream($input)
224+
/**
225+
* @expectedException \MongoDB\Exception\InvalidArgumentTypeException
226+
* @dataProvider provideInvalidUploadConstructorOptions
227+
*/
228+
public function testUploadConstructorOptionTypeChecks(array $options)
201229
{
202-
$stream = fopen('php://temp', 'w+');
203-
fwrite($stream, $input);
204-
rewind($stream);
205-
return $stream;
230+
new \MongoDB\GridFS\GridFsUpload($this->collectionsWrapper,"test", $options);
231+
}
232+
233+
public function provideInvalidUploadConstructorOptions()
234+
{
235+
$options = [];
236+
$invalidContentType = [123, 3.14, true, [], new \stdClass];
237+
$invalidAliases = ['foo', 3.14, true, [12, 34], new \stdClass];
238+
$invalidMetadata = ['foo', 3.14, true];
239+
240+
foreach ($invalidContentType as $value) {
241+
$options[][] = ['contentType' => $value];
242+
}
243+
foreach ($invalidAliases as $value) {
244+
$options[][] = ['aliases' => $value];
245+
}
246+
foreach ($invalidMetadata as $value) {
247+
$options[][] = ['metadata' => $value];
248+
}
249+
return $options;
250+
}
251+
/**
252+
* @expectedException \MongoDB\Exception\InvalidArgumentTypeException
253+
* @dataProvider provideInvalidDownloadConstructorFile
254+
*/
255+
public function testDownloadConstructorFileCheck($file)
256+
{
257+
$download = new \MongoDB\GridFS\GridFsDownload($this->collectionsWrapper, $file);
258+
}
259+
public function provideInvalidDownloadConstructorFile()
260+
{
261+
$files = [];
262+
$invalidFiles = [123, 3.14, true, []];
263+
264+
foreach ($invalidFiles as $value) {
265+
$files[][] = $value;
266+
}
267+
return $files;
206268
}
207269
}

0 commit comments

Comments
 (0)