From e3f89f116a82ec0f0e3597c09753a074691d1a66 Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Sun, 21 May 2006 18:13:37 +0000 Subject: [PATCH] - MFH . Make code exception safe . Make RecursiveRegexIterator::getChildren pass regex to inner ctor . Fix CachingIterator::__toString() in TOSTRING_USE_KEY mode . Add CachingIterator::getCache() . Add tests --- ext/spl/spl_iterators.c | 178 +++++++++++++++++++---- ext/spl/spl_iterators.h | 1 + ext/spl/tests/iterator_042.phpt | 104 ++++++++++++++ ext/spl/tests/iterator_043.phpt | 20 +++ ext/spl/tests/iterator_044.phpt | 169 ++++++++++++++++++++++ ext/spl/tests/iterator_045.phpt | 244 ++++++++++++++++++++++++++++++++ ext/spl/tests/iterator_046.phpt | 60 ++++++++ ext/spl/tests/iterator_047.phpt | 119 ++++++++++++++++ ext/spl/tests/iterator_048.phpt | 44 ++++++ 9 files changed, 913 insertions(+), 26 deletions(-) create mode 100755 ext/spl/tests/iterator_042.phpt create mode 100755 ext/spl/tests/iterator_043.phpt create mode 100755 ext/spl/tests/iterator_044.phpt create mode 100755 ext/spl/tests/iterator_045.phpt create mode 100755 ext/spl/tests/iterator_046.phpt create mode 100755 ext/spl/tests/iterator_047.phpt create mode 100755 ext/spl/tests/iterator_048.phpt diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index e2ec9f4e48..1bfe01ca05 100755 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -193,6 +193,13 @@ next_step: switch (object->iterators[object->level].state) { case RS_NEXT: iterator->funcs->move_forward(iterator TSRMLS_CC); + if (EG(exception)) { + if (!(object->flags & RIT_CATCH_GET_CHILD)) { + return; + } else { + zend_clear_exception(TSRMLS_C); + } + } case RS_START: if (iterator->funcs->valid(iterator TSRMLS_CC) == FAILURE) { break; @@ -207,6 +214,14 @@ next_step: } else { zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval); } + if (EG(exception)) { + if (!(object->flags & RIT_CATCH_GET_CHILD)) { + object->iterators[object->level].state = RS_NEXT; + return; + } else { + zend_clear_exception(TSRMLS_C); + } + } if (retval) { has_children = zend_is_true(retval); zval_ptr_dtor(&retval); @@ -235,6 +250,13 @@ next_step: zend_call_method_with_0_params(&zthis, object->ce, &object->nextElement, "nextelement", NULL); } object->iterators[object->level].state = RS_NEXT; + if (EG(exception)) { + if (!(object->flags & RIT_CATCH_GET_CHILD)) { + return; + } else { + zend_clear_exception(TSRMLS_C); + } + } return /* self */; case RS_SELF: if (object->nextElement && (object->mode == RIT_SELF_FIRST || object->mode == RIT_CHILD_FIRST)) { @@ -292,6 +314,13 @@ next_step: } if (object->beginChildren) { zend_call_method_with_0_params(&zthis, object->ce, &object->beginChildren, "beginchildren", NULL); + if (EG(exception)) { + if (!(object->flags & RIT_CATCH_GET_CHILD)) { + return; + } else { + zend_clear_exception(TSRMLS_C); + } + } } goto next_step; } @@ -299,6 +328,13 @@ next_step: if (object->level > 0) { if (object->endChildren) { zend_call_method_with_0_params(&zthis, object->ce, &object->endChildren, "endchildren", NULL); + if (EG(exception)) { + if (!(object->flags & RIT_CATCH_GET_CHILD)) { + return; + } else { + zend_clear_exception(TSRMLS_C); + } + } } iterator->funcs->dtor(iterator TSRMLS_CC); zval_ptr_dtor(&object->iterators[object->level].zobject); @@ -317,7 +353,7 @@ static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zt sub_iter = object->iterators[object->level].iterator; sub_iter->funcs->dtor(sub_iter TSRMLS_CC); zval_ptr_dtor(&object->iterators[object->level--].zobject); - if (!object->endChildren || object->endChildren->common.scope != spl_ce_RecursiveIteratorIterator) { + if (!EG(exception) && (!object->endChildren || object->endChildren->common.scope != spl_ce_RecursiveIteratorIterator)) { zend_call_method_with_0_params(&zthis, object->ce, &object->endChildren, "endchildren", NULL); } } @@ -327,7 +363,7 @@ static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zt if (sub_iter->funcs->rewind) { sub_iter->funcs->rewind(sub_iter TSRMLS_CC); } - if (object->beginIteration && !object->in_iteration) { + if (!EG(exception) && object->beginIteration && !object->in_iteration) { zend_call_method_with_0_params(&zthis, object->ce, &object->beginIteration, "beginIteration", NULL); } object->in_iteration = 1; @@ -573,7 +609,11 @@ SPL_METHOD(RecursiveIteratorIterator, callHasChildren) RETURN_FALSE; } else { zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval); - RETURN_ZVAL(retval, 0, 1); + if (retval) { + RETURN_ZVAL(retval, 0, 1); + } else { + RETURN_FALSE; + } } } /* }}} */ @@ -925,6 +965,13 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z } if (instanceof_function(ce, zend_ce_aggregate TSRMLS_CC)) { zend_call_method_with_0_params(&zobject, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval); + if (EG(exception)) { + if (retval) { + zval_ptr_dtor(&retval); + } + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); + return NULL; + } if (!retval || Z_TYPE_P(retval) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(retval), zend_ce_traversable TSRMLS_CC)) { zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "%s::getIterator() must return an object that implememnts Traversable", ce->name); php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); @@ -955,6 +1002,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); return NULL; } + intern->u.regex.regex = estrndup(regex, len); intern->u.regex.pce = pcre_get_compiled_regex_cache(regex, len, &extra, &poptions, &coptions TSRMLS_CC); intern->u.regex.pce->refcount++; break;; @@ -1241,7 +1289,11 @@ SPL_METHOD(RecursiveFilterIterator, hasChildren) intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval); - RETURN_ZVAL(retval, 0, 1); + if (retval) { + RETURN_ZVAL(retval, 0, 1); + } else { + RETURN_FALSE; + } } /* }}} */ /* {{{ proto RecursiveFilterIterator RecursiveFilterIterator::getChildren() @@ -1254,8 +1306,12 @@ SPL_METHOD(RecursiveFilterIterator, getChildren) intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval); - spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval TSRMLS_CC); - zval_ptr_dtor(&retval); + if (!EG(exception) && retval) { + spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval TSRMLS_CC); + } + if (retval) { + zval_ptr_dtor(&retval); + } } /* }}} */ /* {{{ proto void ParentIterator::__construct(RecursiveIterator it) @@ -1275,7 +1331,11 @@ SPL_METHOD(ParentIterator, hasChildren) intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval); - RETURN_ZVAL(retval, 0, 1); + if (retval) { + RETURN_ZVAL(retval, 0, 1); + } else { + RETURN_FALSE; + } } /* }}} */ /* {{{ proto ParentIterator ParentIterator::getChildren() @@ -1288,8 +1348,12 @@ SPL_METHOD(ParentIterator, getChildren) intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval); - spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval TSRMLS_CC); - zval_ptr_dtor(&retval); + if (!EG(exception) && retval) { + spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval TSRMLS_CC); + } + if (retval) { + zval_ptr_dtor(&retval); + } } /* }}} */ #if HAVE_PCRE || HAVE_BUNDLED_PCRE @@ -1319,7 +1383,6 @@ SPL_METHOD(RegexIterator, accept) subject = &tmp[0]; } else { subject_len = intern->current.str_key_len; - /* FIXME: Unicode support??? */ subject = intern->current.str_key; } } else { @@ -1349,6 +1412,28 @@ SPL_METHOD(RecursiveRegexIterator, __construct) { spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveRegexIterator, spl_ce_RecursiveIterator, DIT_RecursiveRegexIterator); } /* }}} */ + +/* {{{ proto RecursiveRegexIterator RecursiveRegexIterator::getChildren() + Return the inner iterator's children contained in a RecursiveRegexIterator */ +SPL_METHOD(RecursiveRegexIterator, getChildren) +{ + spl_dual_it_object *intern; + zval *retval, *regex; + + intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval); + if (!EG(exception)) { + MAKE_STD_ZVAL(regex); + ZVAL_STRING(regex, intern->u.regex.regex, 1); + spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, retval, regex TSRMLS_CC); + zval_ptr_dtor(®ex); + } + if (retval) { + zval_ptr_dtor(&retval); + } +} /* }}} */ + #endif /* {{{ spl_dual_it_free_storage */ @@ -1385,6 +1470,9 @@ static inline void spl_dual_it_free_storage(void *_object TSRMLS_DC) if (object->u.regex.pce) { object->u.regex.pce->refcount--; } + if (object->u.regex.regex) { + efree(object->u.regex.regex); + } } #endif @@ -1477,7 +1565,7 @@ ZEND_END_ARG_INFO(); static zend_function_entry spl_funcs_RecursiveRegexIterator[] = { SPL_ME(RecursiveRegexIterator, __construct, arginfo_rec_regex_it___construct, ZEND_ACC_PUBLIC) SPL_ME(ParentIterator, hasChildren, NULL, ZEND_ACC_PUBLIC) - SPL_ME(ParentIterator, getChildren, NULL, ZEND_ACC_PUBLIC) + SPL_ME(RecursiveRegexIterator, getChildren, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; #endif @@ -1511,9 +1599,11 @@ static inline void spl_limit_it_seek(spl_dual_it_object *intern, long pos TSRMLS spl_dual_it_free(intern TSRMLS_CC); zend_call_method_with_1_params(&intern->inner.zobject, intern->inner.ce, NULL, "seek", NULL, zpos); zval_ptr_dtor(&zpos); - intern->current.pos = pos; - if (spl_limit_it_valid(intern TSRMLS_CC) == SUCCESS) { - spl_dual_it_fetch(intern, 0 TSRMLS_CC); + if (!EG(exception)) { + intern->current.pos = pos; + if (spl_limit_it_valid(intern TSRMLS_CC) == SUCCESS) { + spl_dual_it_fetch(intern, 0 TSRMLS_CC); + } } } else { /* emulate the forward seek, by next() calls */ @@ -1664,25 +1754,43 @@ static inline void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC) if (intern->dit_type == DIT_RecursiveCachingIterator) { zval *retval, *zchildren, zflags; zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval); - if (zend_is_true(retval)) { - zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &zchildren); - if (EG(exception)) { - if (zchildren) { + if (EG(exception)) { + if (retval) { + zval_ptr_dtor(&retval); + } + if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) { + zend_clear_exception(TSRMLS_C); + } else { + return; + } + } else { + if (zend_is_true(retval)) { + zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &zchildren); + if (EG(exception)) { + if (zchildren) { + zval_ptr_dtor(&zchildren); + } + if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) { + zend_clear_exception(TSRMLS_C); + } else { + return; + } + } else { + INIT_PZVAL(&zflags); + ZVAL_LONG(&zflags, intern->u.caching.flags & CIT_PUBLIC); + spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &intern->u.caching.zchildren, 1, zchildren, &zflags TSRMLS_CC); zval_ptr_dtor(&zchildren); } + } + zval_ptr_dtor(&retval); + if (EG(exception)) { if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) { zend_clear_exception(TSRMLS_C); } else { return; } - } else { - INIT_PZVAL(&zflags); - ZVAL_LONG(&zflags, intern->u.caching.flags & CIT_PUBLIC); - spl_instantiate_arg_ex2(spl_ce_RecursiveCachingIterator, &intern->u.caching.zchildren, 1, zchildren, &zflags TSRMLS_CC); - zval_ptr_dtor(&zchildren); } } - zval_ptr_dtor(&retval); } if (intern->u.caching.flags & (CIT_TOSTRING_USE_INNER|CIT_CALL_TOSTRING)) { int use_copy; @@ -1781,7 +1889,7 @@ SPL_METHOD(CachingIterator, __toString) } if (intern->u.caching.flags & CIT_TOSTRING_USE_KEY) { if (intern->current.key_type == HASH_KEY_IS_STRING) { - RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len, 1); + RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len-1, 1); } else { RETVAL_LONG(intern->current.int_key); convert_to_string(return_value); @@ -1897,6 +2005,23 @@ SPL_METHOD(CachingIterator, offsetExists) } /* }}} */ +/* {{{ proto bool CachingIterator::getCache() + Return the cache */ +SPL_METHOD(CachingIterator, getCache) +{ + spl_dual_it_object *intern; + + intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + + if (!(intern->u.caching.flags & CIT_FULL_CACHE)) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name); + return; + } + + RETURN_ZVAL(intern->u.caching.zcache, 1, 0); +} +/* }}} */ + /* {{{ proto int CachingIterator::getFlags() Return the internal flags */ SPL_METHOD(CachingIterator, getFlags) @@ -1980,6 +2105,7 @@ static zend_function_entry spl_funcs_CachingIterator[] = { SPL_ME(CachingIterator, offsetSet, arginfo_caching_it_offsetSet, ZEND_ACC_PUBLIC) SPL_ME(CachingIterator, offsetUnset, arginfo_caching_it_offsetGet, ZEND_ACC_PUBLIC) SPL_ME(CachingIterator, offsetExists, arginfo_caching_it_offsetGet, ZEND_ACC_PUBLIC) + SPL_ME(CachingIterator, getCache, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; @@ -2277,7 +2403,7 @@ SPL_METHOD(AppendIterator, append) APPENDIT_CHECK_CTOR(intern); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &it, zend_ce_iterator) == FAILURE) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "O", &it, zend_ce_iterator) == FAILURE) { return; } spl_array_iterator_append(intern->u.append.zarrayit, it TSRMLS_CC); diff --git a/ext/spl/spl_iterators.h b/ext/spl/spl_iterators.h index 430fe7ec59..8a608def63 100755 --- a/ext/spl/spl_iterators.h +++ b/ext/spl/spl_iterators.h @@ -130,6 +130,7 @@ typedef struct _spl_dual_it_object { struct { int flags; pcre_cache_entry *pce; + char *regex; } regex; #endif } u; diff --git a/ext/spl/tests/iterator_042.phpt b/ext/spl/tests/iterator_042.phpt new file mode 100755 index 0000000000..8615450654 --- /dev/null +++ b/ext/spl/tests/iterator_042.phpt @@ -0,0 +1,104 @@ +--TEST-- +SPL: AppendIterator and its ArrayIterator +--SKIPIF-- + +--FILE-- +append(array()); +$it->append(new ArrayIterator(array(1))); +$it->append(new ArrayIterator(array(21, 22))); + +var_dump($it->getArrayIterator()); + +$it->append(new ArrayIterator(array(31, 32, 33))); + +var_dump($it->getArrayIterator()); + +$idx = 0; + +foreach($it as $k => $v) +{ + echo '===' . $idx++ . "===\n"; + var_dump($it->getIteratorIndex()); + var_dump($k); + var_dump($v); +} + +?> +===DONE=== + +--EXPECTF-- +Error Argument 1 passed to AppendIterator::append() must implement interface Iterator, array given in %siterator_042.php on line %d +object(ArrayIterator)#%d (2) { + [0]=> + object(ArrayIterator)#%d (1) { + [0]=> + int(1) + } + [1]=> + object(ArrayIterator)#%d (2) { + [0]=> + int(21) + [1]=> + int(22) + } +} +object(ArrayIterator)#%d (3) { + [0]=> + object(ArrayIterator)#%d (1) { + [0]=> + int(1) + } + [1]=> + object(ArrayIterator)#%d (2) { + [0]=> + int(21) + [1]=> + int(22) + } + [2]=> + object(ArrayIterator)#5 (3) { + [0]=> + int(31) + [1]=> + int(32) + [2]=> + int(33) + } +} +===0=== +int(0) +int(0) +int(1) +===1=== +int(1) +int(0) +int(21) +===2=== +int(1) +int(1) +int(22) +===3=== +int(2) +int(0) +int(31) +===4=== +int(2) +int(1) +int(32) +===5=== +int(2) +int(2) +int(33) +===DONE=== diff --git a/ext/spl/tests/iterator_043.phpt b/ext/spl/tests/iterator_043.phpt new file mode 100755 index 0000000000..c49e334733 --- /dev/null +++ b/ext/spl/tests/iterator_043.phpt @@ -0,0 +1,20 @@ +--TEST-- +SPL: RecursiveCachingIterator and uninitialized getChildren() +--SKIPIF-- + +--FILE-- +getChildren()); +$it->rewind(); +var_dump($it->getChildren()); + +?> +===DONE=== + +--EXPECTF-- +NULL +NULL +===DONE=== diff --git a/ext/spl/tests/iterator_044.phpt b/ext/spl/tests/iterator_044.phpt new file mode 100755 index 0000000000..e25e0d1dda --- /dev/null +++ b/ext/spl/tests/iterator_044.phpt @@ -0,0 +1,169 @@ +--TEST-- +SPL: CachingIterator and offsetGet/Exists using flag FULL_CACHE +--SKIPIF-- + +--FILE-- + $v) + { + echo "===$k===\n"; + var_dump($v); + var_dump($this->offsetExists($v)); + var_dump($this->offsetGet($v)); + } + } +} + +$it = new MyCachingIterator(new ArrayIterator(array(0, 'foo'=>1, 2, 'bar'=>3, 4))); + +try +{ + var_dump($it->offsetExists(0)); +} +catch(Exception $e) +{ + echo "Exception: " . $e->getMessage() . "\n"; +} + +try +{ + var_dump($it->offsetGet(0)); +} +catch(Exception $e) +{ + echo "Exception: " . $e->getMessage() . "\n"; +} + +$it = new MyCachingIterator(new ArrayIterator(array(0, 'foo'=>1, 2, 'bar'=>3, 4)), CachingIterator::FULL_CACHE); + +var_dump($it->offsetExists()); +var_dump($it->offsetGet()); + +$checks = array(0, new stdClass, new MyFoo, NULL, 2, 'foo', 3); + +$it->test($checks); + +echo "===FILL===\n"; + +foreach($it as $v); // read all into cache + +$it->test($checks); + +?> +===DONE=== + +--EXPECTF-- +Exception: MyCachingIterator does not use a full cache (see CachingIterator::__construct) + +Notice: Undefined index: 0 in %siterator_044.php on line %d +Exception: MyCachingIterator does not use a full cache (see CachingIterator::__construct) + +Warning: CachingIterator::offsetExists() expects exactly 1 parameter, 0 given in %s/iterator_044.php on line %d +NULL + +Warning: CachingIterator::offsetGet() expects exactly 1 parameter, 0 given in %s/iterator_044.php on line %d +NULL +===0=== +int(0) +bool(false) + +Notice: Undefined index: 0 in %siterator_044.php on line %d +NULL +===1=== +object(stdClass)#%d (0) { +} + +Warning: CachingIterator::offsetExists() expects parameter 1 to be string, object given in %siterator_044.php on line %d +NULL + +Warning: CachingIterator::offsetGet() expects parameter 1 to be string, object given in %siterator_044.php on line %d +NULL +===2=== +object(MyFoo)#%d (0) { +} +bool(false) + +Notice: Undefined index: foo in %siterator_044.php on line %d +NULL +===3=== +NULL +bool(false) + +Notice: Undefined index: in %siterator_044.php on line %d +NULL +===4=== +int(2) +bool(false) + +Notice: Undefined index: 2 in %siterator_044.php on line %d +NULL +===5=== +string(3) "foo" +bool(false) + +Notice: Undefined index: foo in %siterator_044.php on line %d +NULL +===6=== +int(3) +bool(false) + +Notice: Undefined index: 3 in %siterator_044.php on line %d +NULL +===FILL=== +===0=== +int(0) +bool(true) +int(0) +===1=== +object(stdClass)#1 (0) { +} + +Warning: CachingIterator::offsetExists() expects parameter 1 to be string, object given in %siterator_044.php on line %d +NULL + +Warning: CachingIterator::offsetGet() expects parameter 1 to be string, object given in %siterator_044.php on line %d +NULL +===2=== +object(MyFoo)#2 (0) { +} +bool(true) +int(1) +===3=== +NULL +bool(false) + +Notice: Undefined index: in %siterator_044.php on line %d +NULL +===4=== +int(2) +bool(true) +int(4) +===5=== +string(3) "foo" +bool(true) +int(1) +===6=== +int(3) +bool(false) + +Notice: Undefined index: 3 in %siterator_044.php on line %d +NULL +===DONE=== diff --git a/ext/spl/tests/iterator_045.phpt b/ext/spl/tests/iterator_045.phpt new file mode 100755 index 0000000000..34dcfa78d1 --- /dev/null +++ b/ext/spl/tests/iterator_045.phpt @@ -0,0 +1,244 @@ +--TEST-- +SPL: CachingIterator and offsetSet/Unset, getCache using flag FULL_CACHE +--SKIPIF-- + +--FILE-- + $v) + { + echo "set($k,$v)\n"; + $this->offsetSet($k, $v); + } + } + + function testUnset($ar) + { + echo __METHOD__ . "()\n"; + foreach($ar as $k => $v) + { + echo "unset($v)\n"; + $this->offsetUnset($v); + } + } + + function fill() + { + echo __METHOD__ . "()\n"; + foreach($this as $v) ; + } + + function show() + { + echo __METHOD__ . "()\n"; + var_dump($this->getCache()); + } +} + +$it = new MyCachingIterator(new ArrayIterator(array(0, 'foo'=>1, 2, 'bar'=>3, 4))); + +try +{ + var_dump($it->offsetSet(0, 0)); +} +catch(Exception $e) +{ + echo "Exception: " . $e->getMessage() . "\n"; +} + +try +{ + var_dump($it->offsetUnset(0)); +} +catch(Exception $e) +{ + echo "Exception: " . $e->getMessage() . "\n"; +} + +$it = new MyCachingIterator(new ArrayIterator(array(0, 1, 2, 3)), CachingIterator::FULL_CACHE); + +var_dump($it->offsetSet()); +var_dump($it->offsetSet(0)); +var_dump($it->offsetUnset()); + +$checks = array(0 => 25, 1 => 42, 3 => 'FooBar'); +$unsets = array(0, 2); + +$it->testSet($checks); +$it->show(); +$it->testUnset($unsets); +$it->show(); +$it->fill(); +$it->show(); +$it->testSet($checks); +$it->show(); +$it->testUnset($unsets); +$it->show(); + +?> +===DONE=== + +--EXPECTF-- +Exception: MyCachingIterator does not use a full cache (see CachingIterator::__construct) +Exception: MyCachingIterator does not use a full cache (see CachingIterator::__construct) + +Warning: CachingIterator::offsetSet() expects exactly 2 parameters, 0 given in %siterator_045.php on line %d +NULL + +Warning: CachingIterator::offsetSet() expects exactly 2 parameters, 1 given in %siterator_045.php on line %d +NULL + +Warning: CachingIterator::offsetUnset() expects exactly 1 parameter, 0 given in %siterator_045.php on line %d +NULL +MyCachingIterator::testSet() +set(0,25) +set(1,42) +set(3,FooBar) +MyCachingIterator::show() +array(3) { + [0]=> + int(25) + [1]=> + int(42) + [3]=> + string(6) "FooBar" +} +MyCachingIterator::testUnset() +unset(0) +unset(2) +MyCachingIterator::show() +array(2) { + [1]=> + int(42) + [3]=> + string(6) "FooBar" +} +MyCachingIterator::fill() +MyCachingIterator::show() +array(4) { + [0]=> + int(0) + [1]=> + int(1) + [2]=> + int(2) + [3]=> + int(3) +} +MyCachingIterator::testSet() +set(0,25) +set(1,42) +set(3,FooBar) +MyCachingIterator::show() +array(4) { + [0]=> + int(25) + [1]=> + int(42) + [2]=> + int(2) + [3]=> + string(6) "FooBar" +} +MyCachingIterator::testUnset() +unset(0) +unset(2) +MyCachingIterator::show() +array(2) { + [1]=> + int(42) + [3]=> + string(6) "FooBar" +} +===DONE=== +--UEXPECTF-- +Exception: MyCachingIterator does not use a full cache (see CachingIterator::__construct) +Exception: MyCachingIterator does not use a full cache (see CachingIterator::__construct) + +Warning: CachingIterator::offsetSet() expects exactly 2 parameters, 0 given in %siterator_045.php on line %d +NULL + +Warning: CachingIterator::offsetSet() expects exactly 2 parameters, 1 given in %siterator_045.php on line %d +NULL + +Warning: CachingIterator::offsetUnset() expects exactly 1 parameter, 0 given in %siterator_045.php on line %d +NULL +MyCachingIterator::testSet() +set(0,25) +set(1,42) +set(3,FooBar) +MyCachingIterator::show() +array(3) { + [0]=> + int(25) + [1]=> + int(42) + [3]=> + unicode(6) "FooBar" +} +MyCachingIterator::testUnset() +unset(0) +unset(2) +MyCachingIterator::show() +array(2) { + [1]=> + int(42) + [3]=> + unicode(6) "FooBar" +} +MyCachingIterator::fill() +MyCachingIterator::show() +array(4) { + [0]=> + int(0) + [1]=> + int(1) + [2]=> + int(2) + [3]=> + int(3) +} +MyCachingIterator::testSet() +set(0,25) +set(1,42) +set(3,FooBar) +MyCachingIterator::show() +array(4) { + [0]=> + int(25) + [1]=> + int(42) + [2]=> + int(2) + [3]=> + unicode(6) "FooBar" +} +MyCachingIterator::testUnset() +unset(0) +unset(2) +MyCachingIterator::show() +array(2) { + [1]=> + int(42) + [3]=> + unicode(6) "FooBar" +} +===DONE=== diff --git a/ext/spl/tests/iterator_046.phpt b/ext/spl/tests/iterator_046.phpt new file mode 100755 index 0000000000..35736c4110 --- /dev/null +++ b/ext/spl/tests/iterator_046.phpt @@ -0,0 +1,60 @@ +--TEST-- +SPL: CachingIterator and __toString using bypassed string keys +--SKIPIF-- + +--FILE-- +1, 'bar'=>2)), CachingIterator::TOSTRING_USE_KEY); + +$it->fill(); +$it->show(); + +?> +===DONE=== + +--EXPECTF-- +MyCachingIterator::fill() +MyCachingIterator::show() +string(1) "0" +string(3) "foo" +string(3) "bar" +===DONE=== +--UEXPECTF-- +MyCachingIterator::fill() +MyCachingIterator::show() +unicode(1) "0" +unicode(3) "foo" +unicode(3) "bar" +===DONE=== diff --git a/ext/spl/tests/iterator_047.phpt b/ext/spl/tests/iterator_047.phpt new file mode 100755 index 0000000000..b313df3012 --- /dev/null +++ b/ext/spl/tests/iterator_047.phpt @@ -0,0 +1,119 @@ +--TEST-- +SPL: RecursiveCachingIterator and exception in has/getChildren +--SKIPIF-- + +--FILE-- + $v) + { + var_dump($k); + var_dump($v); + } + } + catch (Exception $e) + { + echo "Exception: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . "\n"; + } + MyRecursiveArrayIterator::$fail++; + } + } +} + +$it = new MyRecursiveArrayIterator(array(0, array(10), 2, array(30), 4)); +$it = new MyRecursiveCachingIterator($it); + +$it->show(); + +?> +===DONE=== + +--EXPECTF-- +===0=== +MyRecursiveArrayIterator::hasChildren() +int(0) +int(0) +MyRecursiveArrayIterator::hasChildren() +MyRecursiveArrayIterator::getChildren() +MyRecursiveArrayIterator::hasChildren() +int(0) +int(10) +MyRecursiveArrayIterator::hasChildren() +int(2) +int(2) +MyRecursiveArrayIterator::hasChildren() +MyRecursiveArrayIterator::getChildren() +MyRecursiveArrayIterator::hasChildren() +int(0) +int(30) +MyRecursiveArrayIterator::hasChildren() +int(4) +int(4) +===1=== +MyRecursiveArrayIterator::hasChildren() +Exception: State 1: MyRecursiveArrayIterator::hasChildren() in %siterator_047.php on line %d +===2=== +MyRecursiveArrayIterator::hasChildren() +int(0) +int(0) +MyRecursiveArrayIterator::hasChildren() +MyRecursiveArrayIterator::getChildren() +Exception: State 2: MyRecursiveArrayIterator::getChildren() in %siterator_047.php on line %d +===3=== +MyRecursiveArrayIterator::hasChildren() +int(0) +int(0) +MyRecursiveArrayIterator::hasChildren() +MyRecursiveArrayIterator::getChildren() +MyRecursiveArrayIterator::hasChildren() +int(0) +int(10) +MyRecursiveArrayIterator::hasChildren() +int(2) +int(2) +MyRecursiveArrayIterator::hasChildren() +MyRecursiveArrayIterator::getChildren() +MyRecursiveArrayIterator::hasChildren() +int(0) +int(30) +MyRecursiveArrayIterator::hasChildren() +int(4) +int(4) +===DONE=== diff --git a/ext/spl/tests/iterator_048.phpt b/ext/spl/tests/iterator_048.phpt new file mode 100755 index 0000000000..feea20461a --- /dev/null +++ b/ext/spl/tests/iterator_048.phpt @@ -0,0 +1,44 @@ +--TEST-- +SPL: RecursiveCachingIterator and exception in has/getChildren +--SKIPIF-- + +--FILE-- + $v) + { + var_dump($k); + var_dump($v); + } + } + + function accept() + { + return $this->hasChildren() || parent::accept(); + } +} + +$ar = new RecursiveArrayIterator(array('Foo', array('Bar'), 'FooBar', array('Baz'), 'Biz')); +$it = new MyRecursiveRegexIterator($ar, '/Bar/'); + +$it->show(); + +?> +===DONE=== + +--EXPECTF-- +int(0) +string(3) "Bar" +int(2) +string(6) "FooBar" +===DONE=== +--UEXPECTF-- +int(0) +unicode(3) "Bar" +int(2) +unicode(6) "FooBar" +===DONE=== -- 2.40.0