]> granicus.if.org Git - php/commitdiff
New foreach tests. Tested on Windows, Linux and Linux 64 bit.
authorandy wharmby <wharmby@php.net>
Wed, 17 Jun 2009 19:07:15 +0000 (19:07 +0000)
committerandy wharmby <wharmby@php.net>
Wed, 17 Jun 2009 19:07:15 +0000 (19:07 +0000)
tests/lang/foreachLoopIterator.001.phpt [new file with mode: 0644]
tests/lang/foreachLoopIterator.002.phpt [new file with mode: 0644]
tests/lang/foreachLoopIteratorAggregate.001.phpt [new file with mode: 0644]
tests/lang/foreachLoopIteratorAggregate.002.phpt [new file with mode: 0644]
tests/lang/foreachLoopIteratorAggregate.003.phpt [new file with mode: 0644]
tests/lang/foreachLoopIteratorAggregate.004.phpt [new file with mode: 0644]

diff --git a/tests/lang/foreachLoopIterator.001.phpt b/tests/lang/foreachLoopIterator.001.phpt
new file mode 100644 (file)
index 0000000..82b76ee
--- /dev/null
@@ -0,0 +1,135 @@
+--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) {
+  [u"pos":u"MealIterator":private]=>
+  int(0)
+  [u"myContent":u"MealIterator":private]=>
+  array(3) {
+    [0]=>
+    unicode(9) "breakfast"
+    [1]=>
+    unicode(5) "lunch"
+    [2]=>
+    unicode(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 (file)
index 0000000..f40e09b
--- /dev/null
@@ -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 (file)
index 0000000..861a451
--- /dev/null
@@ -0,0 +1,273 @@
+--TEST--
+foreach with iteratorAggregate
+--INI--
+unicode.script_encoding=ISO-8859-1
+unicode.runtime_encoding=ISO-8859-1
+--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) {
+  [u"storedEnglishMealIterator":u"EuropeanMeals":private]=>
+  object(EnglishMealIterator)#%d (2) {
+    [u"pos":u"EnglishMealIterator":private]=>
+    int(0)
+    [u"myContent":u"EnglishMealIterator":private]=>
+    array(3) {
+      [0]=>
+      unicode(9) "breakfast"
+      [1]=>
+      unicode(6) "dinner"
+      [2]=>
+      unicode(3) "tea"
+    }
+  }
+  [u"storedFrenchMealIterator":u"EuropeanMeals":private]=>
+  object(FrenchMealIterator)#%d (2) {
+    [u"pos":u"FrenchMealIterator":private]=>
+    int(0)
+    [u"myContent":u"FrenchMealIterator":private]=>
+    array(4) {
+      [0]=>
+      unicode(14) "petit dejeuner"
+      [1]=>
+      unicode(8) "dejeuner"
+      [2]=>
+      unicode(6) "gouter"
+      [3]=>
+      unicode(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 (file)
index 0000000..eef4302
--- /dev/null
@@ -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 (file)
index 0000000..12426c5
--- /dev/null
@@ -0,0 +1,134 @@
+--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 (file)
index 0000000..9a1e612
--- /dev/null
@@ -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===