summaryrefslogtreecommitdiff
path: root/tests/lang
diff options
context:
space:
mode:
authorandy wharmby <wharmby@php.net>2009-06-17 19:07:17 +0000
committerandy wharmby <wharmby@php.net>2009-06-17 19:07:17 +0000
commitfb3132f502265e3602f4ab4bb0f0f5d93ad1fff4 (patch)
tree9e18915db27e8d63cc0d61a371aadbbbcef4f06c /tests/lang
parentb685def15acadf29e0657dc6bce3c53404948f3b (diff)
downloadphp-git-fb3132f502265e3602f4ab4bb0f0f5d93ad1fff4.tar.gz
New foreach tests. Tested on Windows, Linux and Linux 64 bit.
Diffstat (limited to 'tests/lang')
-rw-r--r--tests/lang/foreachLoopIterator.001.phpt134
-rw-r--r--tests/lang/foreachLoopIterator.002.phpt24
-rw-r--r--tests/lang/foreachLoopIteratorAggregate.001.phpt270
-rw-r--r--tests/lang/foreachLoopIteratorAggregate.002.phpt53
-rw-r--r--tests/lang/foreachLoopIteratorAggregate.003.phpt133
-rw-r--r--tests/lang/foreachLoopIteratorAggregate.004.phpt104
6 files changed, 718 insertions, 0 deletions
diff --git a/tests/lang/foreachLoopIterator.001.phpt b/tests/lang/foreachLoopIterator.001.phpt
new file mode 100644
index 0000000000..c049cb7668
--- /dev/null
+++ b/tests/lang/foreachLoopIterator.001.phpt
@@ -0,0 +1,134 @@
+--TEST--
+foreach with Iterator.
+--FILE--
+<?php
+
+class MealIterator implements Iterator {
+ private $pos=0;
+ private $myContent=array("breakfast", "lunch", "dinner");
+
+ public function valid() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->pos<3;
+ }
+
+ public function next() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->myContent[$this->pos++];
+ }
+
+ public function rewind() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ $this->pos=0;
+ }
+
+ public function current() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->myContent[$this->pos];
+ }
+
+ public function key() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return "meal " . $this->pos;
+ }
+
+}
+
+$f = new MealIterator;
+var_dump($f);
+
+echo "-----( Simple iteration: )-----\n";
+foreach ($f as $k=>$v) {
+ echo "$k => $v\n";
+}
+
+$f->rewind();
+
+$indent = " ";
+
+echo "\n\n\n-----( Nested iteration: )-----\n";
+$count=1;
+foreach ($f as $k=>$v) {
+ echo "\nTop level " . $count++ . ": \n";
+ echo "$k => $v\n";
+ $indent = " ";
+ foreach ($f as $k=>$v) {
+ echo " $k => $v\n";
+ }
+ $indent = " ";
+
+}
+
+?>
+===DONE===
+--EXPECTF--
+object(MealIterator)#%d (2) {
+ ["pos":"MealIterator":private]=>
+ int(0)
+ ["myContent":"MealIterator":private]=>
+ array(3) {
+ [0]=>
+ string(9) "breakfast"
+ [1]=>
+ string(5) "lunch"
+ [2]=>
+ string(6) "dinner"
+ }
+}
+-----( Simple iteration: )-----
+--> MealIterator::rewind (0)
+--> MealIterator::valid (0)
+--> MealIterator::current (0)
+--> MealIterator::key (0)
+meal 0 => breakfast
+--> MealIterator::next (0)
+--> MealIterator::valid (1)
+--> MealIterator::current (1)
+--> MealIterator::key (1)
+meal 1 => lunch
+--> MealIterator::next (1)
+--> MealIterator::valid (2)
+--> MealIterator::current (2)
+--> MealIterator::key (2)
+meal 2 => dinner
+--> MealIterator::next (2)
+--> MealIterator::valid (3)
+--> MealIterator::rewind (3)
+
+
+
+-----( Nested iteration: )-----
+ --> MealIterator::rewind (0)
+ --> MealIterator::valid (0)
+ --> MealIterator::current (0)
+ --> MealIterator::key (0)
+
+Top level 1:
+meal 0 => breakfast
+ --> MealIterator::rewind (0)
+ --> MealIterator::valid (0)
+ --> MealIterator::current (0)
+ --> MealIterator::key (0)
+ meal 0 => breakfast
+ --> MealIterator::next (0)
+ --> MealIterator::valid (1)
+ --> MealIterator::current (1)
+ --> MealIterator::key (1)
+ meal 1 => lunch
+ --> MealIterator::next (1)
+ --> MealIterator::valid (2)
+ --> MealIterator::current (2)
+ --> MealIterator::key (2)
+ meal 2 => dinner
+ --> MealIterator::next (2)
+ --> MealIterator::valid (3)
+ --> MealIterator::next (3)
+
+Notice: Undefined offset: 3 in %s on line %d
+ --> MealIterator::valid (4)
+===DONE=== \ No newline at end of file
diff --git a/tests/lang/foreachLoopIterator.002.phpt b/tests/lang/foreachLoopIterator.002.phpt
new file mode 100644
index 0000000000..f40e09b3c3
--- /dev/null
+++ b/tests/lang/foreachLoopIterator.002.phpt
@@ -0,0 +1,24 @@
+--TEST--
+foreach with iterator and &$value reference
+--FILE--
+<?php
+
+class MyIterator implements Iterator {
+ public function valid() { return true; }
+ public function next() { }
+ public function rewind() { }
+ public function current() { }
+ public function key() { }
+}
+
+$f = new MyIterator;
+echo "-----( Try to iterate with &\$value: )-----\n";
+foreach ($f as $k=>&$v) {
+ echo "$k => $v\n";
+}
+
+?>
+--EXPECTF--
+-----( Try to iterate with &$value: )-----
+
+Fatal error: An iterator cannot be used with foreach by reference in %s on line 13 \ No newline at end of file
diff --git a/tests/lang/foreachLoopIteratorAggregate.001.phpt b/tests/lang/foreachLoopIteratorAggregate.001.phpt
new file mode 100644
index 0000000000..b20d3ea3c5
--- /dev/null
+++ b/tests/lang/foreachLoopIteratorAggregate.001.phpt
@@ -0,0 +1,270 @@
+--TEST--
+foreach with iteratorAggregate
+--FILE--
+<?php
+class EnglishMealIterator implements Iterator {
+ private $pos=0;
+ private $myContent=array("breakfast", "dinner", "tea");
+
+ public function valid() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->pos < count($this->myContent);
+ }
+
+ public function next() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ $this->pos++;
+ }
+
+ public function rewind() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ $this->pos=0;
+ }
+
+ public function current() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->myContent[$this->pos];
+ }
+
+ public function key() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return "meal " . $this->pos;
+ }
+
+}
+
+class FrenchMealIterator implements Iterator {
+ private $pos=0;
+ private $myContent=array("petit dejeuner", "dejeuner", "gouter", "dinner");
+
+ public function valid() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->pos < count($this->myContent);
+ }
+
+ public function next() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ $this->pos++;
+ }
+
+ public function rewind() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ $this->pos=0;
+ }
+
+ public function current() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->myContent[$this->pos];
+ }
+
+ public function key() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return "meal " . $this->pos;
+ }
+
+}
+
+
+Class EuropeanMeals implements IteratorAggregate {
+
+ private $storedEnglishMealIterator;
+ private $storedFrenchMealIterator;
+
+ public function __construct() {
+ $this->storedEnglishMealIterator = new EnglishMealIterator;
+ $this->storedFrenchMealIterator = new FrenchMealIterator;
+ }
+
+ public function getIterator() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . "\n";
+
+ //Alternate between English and French meals
+ static $i = 0;
+ if ($i++%2 == 0) {
+ return $this->storedEnglishMealIterator;
+ } else {
+ return $this->storedFrenchMealIterator;
+ }
+ }
+
+}
+
+$f = new EuropeanMeals;
+var_dump($f);
+
+echo "-----( Simple iteration 1: )-----\n";
+foreach ($f as $k=>$v) {
+ echo "$k => $v\n";
+}
+echo "-----( Simple iteration 2: )-----\n";
+foreach ($f as $k=>$v) {
+ echo "$k => $v\n";
+}
+
+
+$indent = " ";
+echo "\n\n\n-----( Nested iteration: )-----\n";
+$count=1;
+foreach ($f as $k=>$v) {
+ echo "\nTop level " . $count++ . ": \n";
+ echo "$k => $v\n";
+ $indent = " ";
+ foreach ($f as $k=>$v) {
+ echo " $k => $v\n";
+ }
+ $indent = " ";
+}
+
+
+?>
+===DONE===
+--EXPECTF--
+object(EuropeanMeals)#%d (2) {
+ ["storedEnglishMealIterator":"EuropeanMeals":private]=>
+ object(EnglishMealIterator)#%d (2) {
+ ["pos":"EnglishMealIterator":private]=>
+ int(0)
+ ["myContent":"EnglishMealIterator":private]=>
+ array(3) {
+ [0]=>
+ string(9) "breakfast"
+ [1]=>
+ string(6) "dinner"
+ [2]=>
+ string(3) "tea"
+ }
+ }
+ ["storedFrenchMealIterator":"EuropeanMeals":private]=>
+ object(FrenchMealIterator)#%d (2) {
+ ["pos":"FrenchMealIterator":private]=>
+ int(0)
+ ["myContent":"FrenchMealIterator":private]=>
+ array(4) {
+ [0]=>
+ string(14) "petit dejeuner"
+ [1]=>
+ string(8) "dejeuner"
+ [2]=>
+ string(6) "gouter"
+ [3]=>
+ string(6) "dinner"
+ }
+ }
+}
+-----( Simple iteration 1: )-----
+--> EuropeanMeals::getIterator
+--> EnglishMealIterator::rewind (0)
+--> EnglishMealIterator::valid (0)
+--> EnglishMealIterator::current (0)
+--> EnglishMealIterator::key (0)
+meal 0 => breakfast
+--> EnglishMealIterator::next (0)
+--> EnglishMealIterator::valid (1)
+--> EnglishMealIterator::current (1)
+--> EnglishMealIterator::key (1)
+meal 1 => dinner
+--> EnglishMealIterator::next (1)
+--> EnglishMealIterator::valid (2)
+--> EnglishMealIterator::current (2)
+--> EnglishMealIterator::key (2)
+meal 2 => tea
+--> EnglishMealIterator::next (2)
+--> EnglishMealIterator::valid (3)
+-----( Simple iteration 2: )-----
+--> EuropeanMeals::getIterator
+--> FrenchMealIterator::rewind (0)
+--> FrenchMealIterator::valid (0)
+--> FrenchMealIterator::current (0)
+--> FrenchMealIterator::key (0)
+meal 0 => petit dejeuner
+--> FrenchMealIterator::next (0)
+--> FrenchMealIterator::valid (1)
+--> FrenchMealIterator::current (1)
+--> FrenchMealIterator::key (1)
+meal 1 => dejeuner
+--> FrenchMealIterator::next (1)
+--> FrenchMealIterator::valid (2)
+--> FrenchMealIterator::current (2)
+--> FrenchMealIterator::key (2)
+meal 2 => gouter
+--> FrenchMealIterator::next (2)
+--> FrenchMealIterator::valid (3)
+--> FrenchMealIterator::current (3)
+--> FrenchMealIterator::key (3)
+meal 3 => dinner
+--> FrenchMealIterator::next (3)
+--> FrenchMealIterator::valid (4)
+
+
+
+-----( Nested iteration: )-----
+ --> EuropeanMeals::getIterator
+ --> EnglishMealIterator::rewind (3)
+ --> EnglishMealIterator::valid (0)
+ --> EnglishMealIterator::current (0)
+ --> EnglishMealIterator::key (0)
+
+Top level 1:
+meal 0 => breakfast
+ --> EuropeanMeals::getIterator
+ --> FrenchMealIterator::rewind (4)
+ --> FrenchMealIterator::valid (0)
+ --> FrenchMealIterator::current (0)
+ --> FrenchMealIterator::key (0)
+ meal 0 => petit dejeuner
+ --> FrenchMealIterator::next (0)
+ --> FrenchMealIterator::valid (1)
+ --> FrenchMealIterator::current (1)
+ --> FrenchMealIterator::key (1)
+ meal 1 => dejeuner
+ --> FrenchMealIterator::next (1)
+ --> FrenchMealIterator::valid (2)
+ --> FrenchMealIterator::current (2)
+ --> FrenchMealIterator::key (2)
+ meal 2 => gouter
+ --> FrenchMealIterator::next (2)
+ --> FrenchMealIterator::valid (3)
+ --> FrenchMealIterator::current (3)
+ --> FrenchMealIterator::key (3)
+ meal 3 => dinner
+ --> FrenchMealIterator::next (3)
+ --> FrenchMealIterator::valid (4)
+ --> EnglishMealIterator::next (0)
+ --> EnglishMealIterator::valid (1)
+ --> EnglishMealIterator::current (1)
+ --> EnglishMealIterator::key (1)
+
+Top level 2:
+meal 1 => dinner
+ --> EuropeanMeals::getIterator
+ --> EnglishMealIterator::rewind (1)
+ --> EnglishMealIterator::valid (0)
+ --> EnglishMealIterator::current (0)
+ --> EnglishMealIterator::key (0)
+ meal 0 => breakfast
+ --> EnglishMealIterator::next (0)
+ --> EnglishMealIterator::valid (1)
+ --> EnglishMealIterator::current (1)
+ --> EnglishMealIterator::key (1)
+ meal 1 => dinner
+ --> EnglishMealIterator::next (1)
+ --> EnglishMealIterator::valid (2)
+ --> EnglishMealIterator::current (2)
+ --> EnglishMealIterator::key (2)
+ meal 2 => tea
+ --> EnglishMealIterator::next (2)
+ --> EnglishMealIterator::valid (3)
+ --> EnglishMealIterator::next (3)
+ --> EnglishMealIterator::valid (4)
+===DONE=== \ No newline at end of file
diff --git a/tests/lang/foreachLoopIteratorAggregate.002.phpt b/tests/lang/foreachLoopIteratorAggregate.002.phpt
new file mode 100644
index 0000000000..eef430237f
--- /dev/null
+++ b/tests/lang/foreachLoopIteratorAggregate.002.phpt
@@ -0,0 +1,53 @@
+--TEST--
+IteratorAggregate::getIterator bad return type
+--FILE--
+<?php
+
+class bad1 implements IteratorAggregate {
+ function getIterator() {
+ return null;
+ }
+}
+
+class bad2 implements IteratorAggregate {
+ function getIterator() {
+ return new stdClass;
+ }
+}
+
+class bad3 implements IteratorAggregate {
+ function getIterator() {
+ return 1;
+ }
+}
+
+class bad4 implements IteratorAggregate {
+ function getIterator() {
+ return array(1,2,3);
+ }
+}
+
+
+function f($className) {
+ try {
+ foreach (new $className as $k=>$v) {
+ echo "$k => $v\n";
+ }
+ } catch (Exception $e) {
+ echo $e->getLine() . ": " . $e->getMessage() ."\n";
+ }
+}
+
+f("bad1");
+f("bad2");
+f("bad3");
+f("bad4");
+
+?>
+===DONE===
+--EXPECTF--
+30: Objects returned by bad1::getIterator() must be traversable or implement interface Iterator
+30: Objects returned by bad2::getIterator() must be traversable or implement interface Iterator
+30: Objects returned by bad3::getIterator() must be traversable or implement interface Iterator
+30: Objects returned by bad4::getIterator() must be traversable or implement interface Iterator
+===DONE=== \ No newline at end of file
diff --git a/tests/lang/foreachLoopIteratorAggregate.003.phpt b/tests/lang/foreachLoopIteratorAggregate.003.phpt
new file mode 100644
index 0000000000..0a0e23c51a
--- /dev/null
+++ b/tests/lang/foreachLoopIteratorAggregate.003.phpt
@@ -0,0 +1,133 @@
+--TEST--
+foreach with nested iteratorAggregates
+--FILE--
+<?php
+class EnglishMealIterator implements Iterator {
+ private $pos=0;
+ private $myContent=array("breakfast", "dinner", "tea");
+
+ public function valid() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->pos<3;
+ }
+
+ public function next() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->myContent[$this->pos++];
+ }
+
+ public function rewind() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ $this->pos=0;
+ }
+
+ public function current() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return $this->myContent[$this->pos];
+ }
+
+ public function key() {
+ global $indent;
+ echo "$indent--> " . __METHOD__ . " ($this->pos)\n";
+ return "meal " . $this->pos;
+ }
+
+}
+
+class A1 implements IteratorAggregate {
+ function getIterator() {
+ return new EnglishMealIterator;
+ }
+}
+
+class A2 implements IteratorAggregate {
+ function getIterator() {
+ return new A1;
+ }
+}
+
+class A3 implements IteratorAggregate {
+ function getIterator() {
+ return new A2;
+ }
+}
+
+echo "\n-----( A1: )-----\n";
+foreach (new A1 as $k=>$v) {
+ echo "$k => $v\n";
+}
+
+echo "\n-----( A2: )-----\n";
+foreach (new A2 as $k=>$v) {
+ echo "$k => $v\n";
+}
+
+echo "\n-----( A3: )-----\n";
+foreach (new A3 as $k=>$v) {
+ echo "$k => $v\n";
+}
+
+?>
+===DONE===
+--EXPECTF--
+-----( A1: )-----
+--> EnglishMealIterator::rewind (0)
+--> EnglishMealIterator::valid (0)
+--> EnglishMealIterator::current (0)
+--> EnglishMealIterator::key (0)
+meal 0 => breakfast
+--> EnglishMealIterator::next (0)
+--> EnglishMealIterator::valid (1)
+--> EnglishMealIterator::current (1)
+--> EnglishMealIterator::key (1)
+meal 1 => dinner
+--> EnglishMealIterator::next (1)
+--> EnglishMealIterator::valid (2)
+--> EnglishMealIterator::current (2)
+--> EnglishMealIterator::key (2)
+meal 2 => tea
+--> EnglishMealIterator::next (2)
+--> EnglishMealIterator::valid (3)
+
+-----( A2: )-----
+--> EnglishMealIterator::rewind (0)
+--> EnglishMealIterator::valid (0)
+--> EnglishMealIterator::current (0)
+--> EnglishMealIterator::key (0)
+meal 0 => breakfast
+--> EnglishMealIterator::next (0)
+--> EnglishMealIterator::valid (1)
+--> EnglishMealIterator::current (1)
+--> EnglishMealIterator::key (1)
+meal 1 => dinner
+--> EnglishMealIterator::next (1)
+--> EnglishMealIterator::valid (2)
+--> EnglishMealIterator::current (2)
+--> EnglishMealIterator::key (2)
+meal 2 => tea
+--> EnglishMealIterator::next (2)
+--> EnglishMealIterator::valid (3)
+
+-----( A3: )-----
+--> EnglishMealIterator::rewind (0)
+--> EnglishMealIterator::valid (0)
+--> EnglishMealIterator::current (0)
+--> EnglishMealIterator::key (0)
+meal 0 => breakfast
+--> EnglishMealIterator::next (0)
+--> EnglishMealIterator::valid (1)
+--> EnglishMealIterator::current (1)
+--> EnglishMealIterator::key (1)
+meal 1 => dinner
+--> EnglishMealIterator::next (1)
+--> EnglishMealIterator::valid (2)
+--> EnglishMealIterator::current (2)
+--> EnglishMealIterator::key (2)
+meal 2 => tea
+--> EnglishMealIterator::next (2)
+--> EnglishMealIterator::valid (3)
+===DONE===
diff --git a/tests/lang/foreachLoopIteratorAggregate.004.phpt b/tests/lang/foreachLoopIteratorAggregate.004.phpt
new file mode 100644
index 0000000000..9a1e612c23
--- /dev/null
+++ b/tests/lang/foreachLoopIteratorAggregate.004.phpt
@@ -0,0 +1,104 @@
+--TEST--
+Duplicate of zend test tests/classes/iterators_002.phpt without expected output from destructor
+--FILE--
+<?php
+class c_iter implements Iterator {
+
+ private $obj;
+ private $num = 0;
+
+ function __construct($obj) {
+ echo __METHOD__ . "\n";
+ $this->obj = $obj;
+ }
+ function rewind() {
+ echo __METHOD__ . "\n";
+ $this->num = 0;
+ }
+ function valid() {
+ $more = $this->num < $this->obj->max;
+ echo __METHOD__ . ' = ' .($more ? 'true' : 'false') . "\n";
+ return $more;
+ }
+ function current() {
+ echo __METHOD__ . "\n";
+ return $this->num;
+ }
+ function next() {
+ echo __METHOD__ . "\n";
+ $this->num++;
+ }
+ function key() {
+ echo __METHOD__ . "\n";
+ switch($this->num) {
+ case 0: return "1st";
+ case 1: return "2nd";
+ case 2: return "3rd";
+ default: return "???";
+ }
+ }
+ function __destruct() {
+ }
+}
+
+class c implements IteratorAggregate {
+
+ public $max = 3;
+
+ function getIterator() {
+ echo __METHOD__ . "\n";
+ return new c_iter($this);
+ }
+ function __destruct() {
+ }
+}
+
+$t = new c();
+
+foreach($t as $k => $v) {
+ foreach($t as $w) {
+ echo "double:$v:$w\n";
+ break;
+ }
+}
+
+unset($t);
+
+?>
+===DONE===
+--EXPECT--
+c::getIterator
+c_iter::__construct
+c_iter::rewind
+c_iter::valid = true
+c_iter::current
+c_iter::key
+c::getIterator
+c_iter::__construct
+c_iter::rewind
+c_iter::valid = true
+c_iter::current
+double:0:0
+c_iter::next
+c_iter::valid = true
+c_iter::current
+c_iter::key
+c::getIterator
+c_iter::__construct
+c_iter::rewind
+c_iter::valid = true
+c_iter::current
+double:1:0
+c_iter::next
+c_iter::valid = true
+c_iter::current
+c_iter::key
+c::getIterator
+c_iter::__construct
+c_iter::rewind
+c_iter::valid = true
+c_iter::current
+double:2:0
+c_iter::next
+c_iter::valid = false
+===DONE===