123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- --TEST--
- User-space streams
- --FILE--
- <?php
- /* This is a fairly aggressive test that looks at
- * user streams and also gives the seek/gets/buffer
- * layer of streams a thorough testing */
- $lyrics = <<<EOD
- ...and the road becomes my bride
- I have stripped of all but pride
- so in her I do confide
- and she keeps me satisfied
- gives me all I need
- ...and with dust in throat I crave
- to the game you stay a slave
- rover wanderer
- nomad vagabond
- call me what you will
- But Ill take my time anywhere
- Free to speak my mind anywhere
- and Ill redefine anywhere
- Anywhere I roam
- Where I lay my head is home
- ...and the earth becomes my throne
- I adapt to the unknown
- under wandering stars Ive grown
- by myself but not alone
- I ask no one
- ...and my ties are severed clean
- the less I have the more I gain
- off the beaten path I reign
- rover wanderer
- nomad vagabond
- call me what you will
- But Ill take my time anywhere
- Free to speak my mind anywhere
- and Ill never mind anywhere
- Anywhere I roam
- Where I lay my head is home
- But Ill take my time anywhere
- Free to speak my mind anywhere
- and Ill take my find anywhere
- Anywhere I roam
- Where I lay my head is home
- carved upon my stone
- my body lie but still I roam
- Wherever I may roam.
- Wherever I May Roam
- EOD;
- /* repeat the data a few times so that it grows larger than
- * the default cache chunk size and that we have something
- * to seek around... */
- $DATA = "";
- for ($i = 0; $i < 30; $i++) {
- if ($i % 2 == 0)
- $DATA .= str_rot13($lyrics);
- else
- $DATA .= $lyrics;
- }
- /* store the data in a regular file so that we can compare
- * the results */
- $tf = tmpfile();
- fwrite($tf, $DATA);
- $n = ftell($tf);
- rewind($tf) or die("failed to rewind tmp file!");
- if (ftell($tf) != 0)
- die("tmpfile is not at start!");
- $DATALEN = strlen($DATA);
- if ($n != $DATALEN)
- die("tmpfile stored $n bytes; should be $DATALEN!");
- class uselessstream
- {
- }
- class mystream
- {
- public $path;
- public $mode;
- public $options;
- public $position;
- public $varname;
- function stream_open($path, $mode, $options, &$opened_path)
- {
- $this->path = $path;
- $this->mode = $mode;
- $this->options = $options;
- $split = parse_url($path);
- $this->varname = $split["host"];
- if (strchr($mode, 'a'))
- $this->position = strlen($GLOBALS[$this->varname]);
- else
- $this->position = 0;
- return true;
- }
- function stream_read($count)
- {
- $ret = substr($GLOBALS[$this->varname], $this->position, $count);
- $this->position += strlen($ret);
- return $ret;
- }
- function stream_tell()
- {
- return $this->position;
- }
- function stream_eof()
- {
- return $this->position >= strlen($GLOBALS[$this->varname]);
- }
- function stream_seek($offset, $whence)
- {
- switch($whence) {
- case SEEK_SET:
- if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) {
- $this->position = $offset;
- return true;
- } else {
- return false;
- }
- break;
- case SEEK_CUR:
- if ($offset >= 0) {
- $this->position += $offset;
- return true;
- } else {
- return false;
- }
- break;
- case SEEK_END:
- if (strlen($GLOBALS[$this->varname]) + $offset >= 0) {
- $this->position = strlen($GLOBALS[$this->varname]) + $offset;
- return true;
- } else {
- return false;
- }
- break;
- default:
- return false;
- }
- }
- }
- try {
- stream_wrapper_register("bogus", "class_not_exist");
- die("Registered a non-existent class!!!???");
- } catch (\TypeError $e) {
- echo $e->getMessage() . \PHP_EOL;
- }
- echo "Not Registered\n";
- if (!stream_wrapper_register("test", "mystream")) {
- die("test wrapper registration failed");
- }
- echo "Registered\n";
- if (!stream_wrapper_register("bogon", "uselessstream")) {
- die("bogon wrapper registration failed");
- }
- echo "Registered\n";
- $b = @fopen("bogon://url", "rb");
- if (is_resource($b)) {
- die("Opened a bogon??");
- }
- $fp = fopen("test://DATA", "rb");
- if (!$fp || !is_resource($fp)) {
- die("Failed to open resource");
- }
- /* some default seeks that will cause buffer/cache misses */
- $seeks = array(
- array(SEEK_SET, 0, 0),
- array(SEEK_CUR, 8450, 8450),
- array(SEEK_CUR, -7904, 546),
- array(SEEK_CUR, 12456, 13002),
- /* end up at BOF so that randomly generated seek offsets
- * below will know where they are supposed to be */
- array(SEEK_SET, 0, 0)
- );
- $whence_map = array(
- SEEK_CUR,
- SEEK_SET,
- SEEK_END
- );
- $whence_names = array(
- SEEK_CUR => "SEEK_CUR",
- SEEK_SET => "SEEK_SET",
- SEEK_END => "SEEK_END"
- );
- /* generate some random seek offsets */
- $position = 0;
- for ($i = 0; $i < 256; $i++) {
- $whence = $whence_map[array_rand($whence_map, 1)];
- switch($whence) {
- case SEEK_SET:
- $offset = rand(0, $DATALEN - 1);
- $position = $offset;
- break;
- case SEEK_END:
- $offset = -rand(0, $DATALEN - 1);
- $position = $DATALEN + $offset;
- break;
- case SEEK_CUR:
- $offset = rand(0, $DATALEN - 1);
- $offset -= $position;
- $position += $offset;
- break;
- }
- $seeks[] = array($whence, $offset, $position);
- }
- /* we compare the results of fgets using differing line lengths to
- * test the fgets layer also */
- $line_lengths = array(1024, 256, 64, 16);
- $fail_count = 0;
- ob_start();
- foreach($line_lengths as $line_length) {
- /* now compare the real stream with the user stream */
- $j = 0;
- rewind($tf);
- rewind($fp);
- foreach($seeks as $seekdata) {
- list($whence, $offset, $position) = $seekdata;
- $rpb = ftell($tf);
- $rr = (int)fseek($tf, $offset, $whence);
- $rpa = ftell($tf);
- $rline = fgets($tf, $line_length);
- (int)fseek($tf, - strlen($rline), SEEK_CUR);
- $upb = ftell($fp);
- $ur = (int)fseek($fp, $offset, $whence);
- $upa = ftell($fp);
- $uline = fgets($fp, $line_length);
- (int)fseek($fp, - strlen($uline), SEEK_CUR);
- printf("\n--[%d] whence=%s offset=%d line_length=%d position_should_be=%d --\n",
- $j, $whence_names[$whence], $offset, $line_length, $position);
- printf("REAL: pos=(%d,%d,%d) ret=%d line[%d]=`%s'\n", $rpb, $rpa, ftell($tf), $rr, strlen($rline), $rline);
- printf("USER: pos=(%d,%d,%d) ret=%d line[%d]=`%s'\n", $upb, $upa, ftell($fp), $ur, strlen($uline), $uline);
- if ($rr != $ur || $rline != $uline || $rpa != $position || $upa != $position) {
- $fail_count++;
- echo "###################################### FAIL!\n";
- $dat = stream_get_meta_data($fp);
- var_dump($dat);
- break;
- }
- $j++;
- }
- if ($fail_count)
- break;
- }
- if ($fail_count == 0) {
- ob_end_clean();
- echo "SEEK: OK\n";
- } else {
- echo "SEEK: FAIL\n";
- ob_end_flush();
- }
- $fail_count = 0;
- fseek($fp, $DATALEN / 2, SEEK_SET);
- fseek($tf, $DATALEN / 2, SEEK_SET);
- if (ftell($fp) != ftell($tf)) {
- echo "SEEK: positions do not match!\n";
- }
- $n = 0;
- while(!feof($fp)) {
- $uline = fgets($fp, 1024);
- $rline = fgets($tf, 1024);
- if ($uline != $rline) {
- echo "FGETS: FAIL\niter=$n user=$uline [pos=" . ftell($fp) . "]\nreal=$rline [pos=" . ftell($tf) . "]\n";
- $fail_count++;
- break;
- }
- }
- if ($fail_count == 0) {
- echo "FGETS: OK\n";
- }
- /* One final test to see if the position is respected when opened for append */
- $fp = fopen("test://lyrics", "a+");
- rewind($fp);
- var_dump(ftell($fp));
- $data = fgets($fp);
- fclose($fp);
- echo $data . "\n";
- ?>
- --EXPECT--
- stream_wrapper_register(): Argument #2 ($class) must be a valid class name, class_not_exist given
- Not Registered
- Registered
- Registered
- SEEK: OK
- FGETS: OK
- int(0)
- ...and the road becomes my bride
|