]> granicus.if.org Git - php/commitdiff
Adding tests for class features, including __autoload(), property inheritance rules...
authorRobin Fernandes <robinf@php.net>
Wed, 30 Jan 2008 14:24:47 +0000 (14:24 +0000)
committerRobin Fernandes <robinf@php.net>
Wed, 30 Jan 2008 14:24:47 +0000 (14:24 +0000)
70 files changed:
tests/classes/__call_003.phpt [new file with mode: 0644]
tests/classes/autoload_007.phpt [new file with mode: 0644]
tests/classes/autoload_008.phpt [new file with mode: 0644]
tests/classes/autoload_009.phpt [new file with mode: 0644]
tests/classes/autoload_010.phpt [new file with mode: 0644]
tests/classes/autoload_011.phpt [new file with mode: 0644]
tests/classes/autoload_012.phpt [new file with mode: 0644]
tests/classes/autoload_013.phpt [new file with mode: 0644]
tests/classes/autoload_014.phpt [new file with mode: 0644]
tests/classes/autoload_015.phpt [new file with mode: 0644]
tests/classes/autoload_016.phpt [new file with mode: 0644]
tests/classes/autoload_017.phpt [new file with mode: 0644]
tests/classes/autoload_018.phpt [new file with mode: 0644]
tests/classes/autoload_019.phpt [new file with mode: 0644]
tests/classes/autoload_020.phpt [new file with mode: 0644]
tests/classes/constants_basic_001.phpt [new file with mode: 0644]
tests/classes/constants_basic_002.phpt [new file with mode: 0644]
tests/classes/constants_basic_003.inc [new file with mode: 0644]
tests/classes/constants_basic_003.phpt [new file with mode: 0644]
tests/classes/constants_basic_004.phpt [new file with mode: 0644]
tests/classes/constants_basic_005.phpt [new file with mode: 0644]
tests/classes/constants_basic_006.phpt [new file with mode: 0644]
tests/classes/constants_error_001.phpt [new file with mode: 0644]
tests/classes/constants_error_002.phpt [new file with mode: 0644]
tests/classes/constants_error_003.phpt [new file with mode: 0644]
tests/classes/constants_error_004.phpt [new file with mode: 0644]
tests/classes/constants_error_005.phpt [new file with mode: 0644]
tests/classes/constants_error_006.phpt [new file with mode: 0644]
tests/classes/constants_error_007.phpt [new file with mode: 0644]
tests/classes/final_ctor3.phpt [new file with mode: 0644]
tests/classes/inheritance_005.phpt [new file with mode: 0644]
tests/classes/method_call_variation_001.phpt [new file with mode: 0644]
tests/classes/new_001.phpt [new file with mode: 0644]
tests/classes/property_override_privateStatic_private.phpt [new file with mode: 0644]
tests/classes/property_override_privateStatic_privateStatic.phpt [new file with mode: 0644]
tests/classes/property_override_privateStatic_protected.phpt [new file with mode: 0644]
tests/classes/property_override_privateStatic_protectedStatic.phpt [new file with mode: 0644]
tests/classes/property_override_privateStatic_public.phpt [new file with mode: 0644]
tests/classes/property_override_privateStatic_publicStatic.phpt [new file with mode: 0644]
tests/classes/property_override_private_private.phpt [new file with mode: 0644]
tests/classes/property_override_private_privateStatic.phpt [new file with mode: 0644]
tests/classes/property_override_private_protected.phpt [new file with mode: 0644]
tests/classes/property_override_private_protectedStatic.phpt [new file with mode: 0644]
tests/classes/property_override_private_public.phpt [new file with mode: 0644]
tests/classes/property_override_private_publicStatic.phpt [new file with mode: 0644]
tests/classes/property_override_protectedStatic_private.phpt [new file with mode: 0644]
tests/classes/property_override_protectedStatic_privateStatic.phpt [new file with mode: 0644]
tests/classes/property_override_protectedStatic_protected.phpt [new file with mode: 0644]
tests/classes/property_override_protectedStatic_protectedStatic.phpt [new file with mode: 0644]
tests/classes/property_override_protectedStatic_public.phpt [new file with mode: 0644]
tests/classes/property_override_protectedStatic_publicStatic.phpt [new file with mode: 0644]
tests/classes/property_override_protected_private.phpt [new file with mode: 0644]
tests/classes/property_override_protected_privateStatic.phpt [new file with mode: 0644]
tests/classes/property_override_protected_protected.phpt [new file with mode: 0644]
tests/classes/property_override_protected_protectedStatic.phpt [new file with mode: 0644]
tests/classes/property_override_protected_public.phpt [new file with mode: 0644]
tests/classes/property_override_protected_publicStatic.phpt [new file with mode: 0644]
tests/classes/property_override_publicStatic_private.phpt [new file with mode: 0644]
tests/classes/property_override_publicStatic_privateStatic.phpt [new file with mode: 0644]
tests/classes/property_override_publicStatic_protected.phpt [new file with mode: 0644]
tests/classes/property_override_publicStatic_protectedStatic.phpt [new file with mode: 0644]
tests/classes/property_override_publicStatic_public.phpt [new file with mode: 0644]
tests/classes/property_override_publicStatic_publicStatic.phpt [new file with mode: 0644]
tests/classes/property_override_public_private.phpt [new file with mode: 0644]
tests/classes/property_override_public_privateStatic.phpt [new file with mode: 0644]
tests/classes/property_override_public_protected.phpt [new file with mode: 0644]
tests/classes/property_override_public_protectedStatic.phpt [new file with mode: 0644]
tests/classes/property_override_public_public.phpt [new file with mode: 0644]
tests/classes/property_override_public_publicStatic.phpt [new file with mode: 0644]
tests/classes/type_hinting_004.phpt [new file with mode: 0644]

diff --git a/tests/classes/__call_003.phpt b/tests/classes/__call_003.phpt
new file mode 100644 (file)
index 0000000..c7aa95c
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Force pass-by-reference to __call 
+--FILE--
+<?php
+  class C
+  {
+      function __call($name, $values)
+      {
+          $values[0][0] = 'changed';
+      }
+  }
+  
+  $a = array('original');
+  
+  $b = array('original');
+  $hack =& $b[0];
+  
+  $c = new C;
+  $c->f($a);
+  $c->f($b);
+  
+  var_dump($a, $b);
+?>
+--EXPECTF--
+array(1) {
+  [0]=>
+  string(8) "original"
+}
+array(1) {
+  [0]=>
+  &string(7) "changed"
+}
+
diff --git a/tests/classes/autoload_007.phpt b/tests/classes/autoload_007.phpt
new file mode 100644 (file)
index 0000000..5652c12
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Ensure instanceof does not trigger autoload.
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  
+  $a = new stdClass;
+  var_dump($a instanceof UndefC);
+?>
+--EXPECTF--
+bool(false)
diff --git a/tests/classes/autoload_008.phpt b/tests/classes/autoload_008.phpt
new file mode 100644 (file)
index 0000000..75a9cd0
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+Ensure catch blocks for unknown exception types do not trigger autoload.
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  
+  function f()
+  {
+      throw new Exception();
+  }
+  try {
+      f();
+  }
+  catch (UndefC $u) {
+      echo "In UndefClass catch block.\n";
+  }
+  catch (Exception $e) {
+      echo "In Exception catch block. Autoload should not have been triggered.\n";
+  }
+?>
+--EXPECTF--
+In Exception catch block. Autoload should not have been triggered.
diff --git a/tests/classes/autoload_009.phpt b/tests/classes/autoload_009.phpt
new file mode 100644 (file)
index 0000000..46f6055
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Ensure type hints for unknown types do not trigger autoload. 
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  
+  function f(UndefClass $x)
+  {
+  }
+  f(new stdClass);
+?>
+--EXPECTF--
+
+Catchable fatal error: Argument 1 passed to f() must be an instance of UndefClass, instance of stdClass given, called in %s
+
+
diff --git a/tests/classes/autoload_010.phpt b/tests/classes/autoload_010.phpt
new file mode 100644 (file)
index 0000000..104f688
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Ensure implements does trigger autoload.
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  
+  class C implements UndefI
+  {
+  }
+?>
+--EXPECTF--
+In autoload: string(6) "UndefI"
+
+Fatal error: Interface 'UndefI' not found in %s on line %d
diff --git a/tests/classes/autoload_011.phpt b/tests/classes/autoload_011.phpt
new file mode 100644 (file)
index 0000000..86858d5
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Ensure extends does trigger autoload.
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  
+  class C extends UndefBase
+  {
+  }
+?>
+--EXPECTF--
+In autoload: string(9) "UndefBase"
+
+Fatal error: Class 'UndefBase' not found in %s on line %d
diff --git a/tests/classes/autoload_012.phpt b/tests/classes/autoload_012.phpt
new file mode 100644 (file)
index 0000000..1f516cb
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Ensure callback methods in unknown classes trigger autoload.
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  call_user_func("UndefC::test");
+?>
+--EXPECTF--
+In autoload: string(6) "UndefC"
+
+Warning: call_user_func(UndefC::test): First argument is expected to be a valid callback in %s on line %d
+
diff --git a/tests/classes/autoload_013.phpt b/tests/classes/autoload_013.phpt
new file mode 100644 (file)
index 0000000..4309cea
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Ensure the ReflectionClass constructor triggers autoload.
+--SKIPIF--
+<?php extension_loaded('reflection') or die('skip'); ?>
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  
+  try {
+      new ReflectionClass("UndefC");
+  }
+  catch (ReflectionException $e) {
+      echo $e->getMessage();
+  }
+?>
+--EXPECTF--
+In autoload: string(6) "UndefC"
+Class UndefC does not exist
diff --git a/tests/classes/autoload_014.phpt b/tests/classes/autoload_014.phpt
new file mode 100644 (file)
index 0000000..a3f04b7
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Ensure the ReflectionMethod constructor triggers autoload.
+--SKIPIF--
+<?php extension_loaded('reflection') or die('skip'); ?>
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  
+  try {
+      new ReflectionMethod("UndefC::test");
+  }
+  catch (ReflectionException $e) {
+      echo $e->getMessage();
+  }
+?>
+--EXPECTF--
+In autoload: string(6) "UndefC"
+Class UndefC does not exist
diff --git a/tests/classes/autoload_015.phpt b/tests/classes/autoload_015.phpt
new file mode 100644 (file)
index 0000000..2b14a0d
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Ensure the ReflectionProperty constructor triggers autoload.
+--SKIPIF--
+<?php extension_loaded('reflection') or die('skip'); ?>
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+  
+  try {
+      new ReflectionProperty('UndefC', 'p');
+  }
+  catch (ReflectionException $e) {
+      echo $e->getMessage();
+  }
+?>
+--EXPECTF--
+In autoload: string(6) "UndefC"
+Class UndefC does not exist
diff --git a/tests/classes/autoload_016.phpt b/tests/classes/autoload_016.phpt
new file mode 100644 (file)
index 0000000..60263ba
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+Ensure ReflectionClass::getProperty() triggers autoload
+--SKIPIF--
+<?php extension_loaded('reflection') or die('skip'); ?>
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+
+  $rc = new ReflectionClass("stdClass");
+  
+  try {
+    $rc->getProperty("UndefC::p");
+  } catch (ReflectionException $e) {
+      echo $e->getMessage();
+  }
+?>
+--EXPECTF--
+In autoload: string(6) "undefc"
+Class undefc does not exist
diff --git a/tests/classes/autoload_017.phpt b/tests/classes/autoload_017.phpt
new file mode 100644 (file)
index 0000000..26de9fd
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+Ensure ReflectionClass::implementsInterface triggers autoload.
+--SKIPIF--
+<?php extension_loaded('reflection') or die('skip'); ?>
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "In autoload: ";
+      var_dump($name);
+  }
+
+  $rc = new ReflectionClass("stdClass");
+  
+  try {
+    $rc->implementsInterface("UndefI");
+  } catch (ReflectionException $e) {
+    echo $e->getMessage();
+  }
+?>
+--EXPECTF--
+In autoload: string(6) "UndefI"
+Interface UndefI does not exist
\ No newline at end of file
diff --git a/tests/classes/autoload_018.phpt b/tests/classes/autoload_018.phpt
new file mode 100644 (file)
index 0000000..59e20e2
--- /dev/null
@@ -0,0 +1,48 @@
+--TEST--
+Ensure __autoload() allows for recursive calls if the class name differs.
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "IN:  " . __METHOD__ . "($name)\n";
+      
+      static $i = 0;
+      if ($i++ > 10) {
+          echo "-> Recursion detected - as expected.\n";
+          return;
+      }
+      
+      class_exists('UndefinedClass' . $i);
+      
+      echo "OUT: " . __METHOD__ . "($name)\n";
+  }
+  
+  var_dump(class_exists('UndefinedClass0'));
+?>
+--EXPECTF--
+IN:  __autoload(UndefinedClass0)
+IN:  __autoload(UndefinedClass1)
+IN:  __autoload(UndefinedClass2)
+IN:  __autoload(UndefinedClass3)
+IN:  __autoload(UndefinedClass4)
+IN:  __autoload(UndefinedClass5)
+IN:  __autoload(UndefinedClass6)
+IN:  __autoload(UndefinedClass7)
+IN:  __autoload(UndefinedClass8)
+IN:  __autoload(UndefinedClass9)
+IN:  __autoload(UndefinedClass10)
+IN:  __autoload(UndefinedClass11)
+-> Recursion detected - as expected.
+OUT: __autoload(UndefinedClass10)
+OUT: __autoload(UndefinedClass9)
+OUT: __autoload(UndefinedClass8)
+OUT: __autoload(UndefinedClass7)
+OUT: __autoload(UndefinedClass6)
+OUT: __autoload(UndefinedClass5)
+OUT: __autoload(UndefinedClass4)
+OUT: __autoload(UndefinedClass3)
+OUT: __autoload(UndefinedClass2)
+OUT: __autoload(UndefinedClass1)
+OUT: __autoload(UndefinedClass0)
+bool(false)
+
diff --git a/tests/classes/autoload_019.phpt b/tests/classes/autoload_019.phpt
new file mode 100644 (file)
index 0000000..7836320
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Ensure __autoload() recursion is guarded for multiple lookups of same class using difference case.
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo __FUNCTION__ . " $name\n";
+      class_exists("undefinedCLASS");
+  }
+  
+  class_exists("unDefinedClass");
+?>
+--EXPECTF--
+__autoload unDefinedClass
diff --git a/tests/classes/autoload_020.phpt b/tests/classes/autoload_020.phpt
new file mode 100644 (file)
index 0000000..a88e561
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Ensure __autoload() is triggered during unserialization.
+--FILE--
+<?php
+  function __autoload($name)
+  {
+      echo "in autoload: $name\n";
+  }
+  
+  var_dump(unserialize('O:1:"C":0:{}'));
+?>
+--EXPECTF--
+in autoload: C
+object(__PHP_Incomplete_Class)#%d (1) {
+  ["__PHP_Incomplete_Class_Name"]=>
+  string(1) "C"
+}
diff --git a/tests/classes/constants_basic_001.phpt b/tests/classes/constants_basic_001.phpt
new file mode 100644 (file)
index 0000000..74b0fcd
--- /dev/null
@@ -0,0 +1,89 @@
+--TEST--
+Class constant declarations
+--FILE--
+<?php
+  define('DEFINED', 1234);
+  $def = 456;
+  define('DEFINED_TO_VAR', $def);
+  define('DEFINED_TO_UNDEF_VAR', $undef);
+  
+  class C
+  {
+      const c0 = UNDEFINED;
+      
+      const c1 = 1, c2 = 1.5;
+      const c3 =  + 1, c4 =  + 1.5;
+      const c5 = -1, c6 = -1.5;
+      
+      const c7 = __LINE__;
+      const c8 = __FILE__;
+      const c9 = __CLASS__;
+      const c10 = __METHOD__;
+      const c11 = __FUNCTION__;
+      
+      const c12 = DEFINED;
+      const c13 = DEFINED_TO_VAR;
+      const c14 = DEFINED_TO_UNDEF_VAR;
+      
+      const c15 = "hello1";
+      const c16 = 'hello2';
+      const c17 = C::c16;
+      const c18 = self::c17;
+  }
+  
+  echo "\nAttempt to access various kinds of class constants:\n";
+  var_dump(C::c0);
+  var_dump(C::c1);
+  var_dump(C::c2);
+  var_dump(C::c3);
+  var_dump(C::c4);
+  var_dump(C::c5);
+  var_dump(C::c6);
+  var_dump(C::c7);
+  var_dump(C::c8);
+  var_dump(C::c9);
+  var_dump(C::c10);
+  var_dump(C::c11);
+  var_dump(C::c12);
+  var_dump(C::c13);
+  var_dump(C::c14);
+  var_dump(C::c15);
+  var_dump(C::c16);
+  var_dump(C::c17);
+  var_dump(C::c18);
+  
+  echo "\nExpecting fatal error:\n";
+  var_dump(C::c19);
+  
+  echo "\nYou should not see this.";
+?>
+--EXPECTF--
+
+Notice: Undefined variable: undef in %s on line 5
+
+Attempt to access various kinds of class constants:
+
+Notice: Use of undefined constant UNDEFINED - assumed 'UNDEFINED' in %s on line %d
+string(9) "UNDEFINED"
+int(1)
+float(1.5)
+int(1)
+float(1.5)
+int(-1)
+float(-1.5)
+int(15)
+string(%d) "%s"
+string(1) "C"
+string(1) "C"
+string(0) ""
+int(1234)
+int(456)
+NULL
+string(6) "hello1"
+string(6) "hello2"
+string(6) "hello2"
+string(6) "hello2"
+
+Expecting fatal error:
+
+Fatal error: Undefined class constant 'c19' in %s on line 53
diff --git a/tests/classes/constants_basic_002.phpt b/tests/classes/constants_basic_002.phpt
new file mode 100644 (file)
index 0000000..0e53ca9
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Basic class support - defining and reading a class constant.
+--FILE--
+<?php
+  class aclass
+  {
+      const myConst = "hello";
+  }
+  
+  echo "\nRead class constant.\n";
+  var_dump(aclass::myConst);
+  
+  echo "\nFail to read class constant from instance.\n";
+  $myInstance = new aclass();
+  var_dump($myInstance->myConst);
+  
+  echo "\nClass constant not visible in object var_dump.\n";
+  var_dump($myInstance)
+?>
+--EXPECTF--
+
+Read class constant.
+string(5) "hello"
+
+Fail to read class constant from instance.
+
+Notice: Undefined property: aclass::$myConst in %s on line 12
+NULL
+
+Class constant not visible in object var_dump.
+object(aclass)#%d (0) {
+}
diff --git a/tests/classes/constants_basic_003.inc b/tests/classes/constants_basic_003.inc
new file mode 100644 (file)
index 0000000..be193e6
--- /dev/null
@@ -0,0 +1,5 @@
+<?php
+class A {
+       const MY_CONST = "hello from A"; 
+}
+?>
\ No newline at end of file
diff --git a/tests/classes/constants_basic_003.phpt b/tests/classes/constants_basic_003.phpt
new file mode 100644 (file)
index 0000000..052af85
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+Ensure class properties and constants can be defined in terms of constants that are not known at compile time.
+--FILE--
+<?php
+  include 'constants_basic_003.inc';
+  class B
+  {
+      public static $a = A::MY_CONST;
+      public static $c = C::MY_CONST;
+      const ca = A::MY_CONST;
+      const cc = C::MY_CONST;
+  }
+  
+  class C
+  {
+      const MY_CONST = "hello from C";
+  }
+  
+  var_dump(B::$a);
+  var_dump(B::$c);
+  var_dump(B::ca);
+  var_dump(B::cc);
+?>
+--EXPECTF--
+string(12) "hello from A"
+string(12) "hello from C"
+string(12) "hello from A"
+string(12) "hello from C"
diff --git a/tests/classes/constants_basic_004.phpt b/tests/classes/constants_basic_004.phpt
new file mode 100644 (file)
index 0000000..cade668
--- /dev/null
@@ -0,0 +1,99 @@
+--TEST--
+Test properties with array default values using class constants as keys and values. 
+--FILE--
+<?php
+  class X
+  {
+      // Static and instance array using class constants
+      public static $sa_x = array(B::KEY => B::VALUE);
+      public $a_x = array(B::KEY => B::VALUE);
+  }
+  
+  class B
+  {
+      const KEY = "key";
+      const VALUE = "value";
+      
+      // Static and instance array using class constants with self
+      public static $sa_b = array(self::KEY => self::VALUE);
+      public $a_b = array(self::KEY => self::VALUE);
+  }
+  
+  class C extends B
+  {
+      // Static and instance array using class constants with parent 
+      public static $sa_c_parent = array(parent::KEY => parent::VALUE);
+      public $a_c_parent = array(parent::KEY => parent::VALUE);
+      
+      // Static and instance array using class constants with self (constants should be inherited)
+      public static $sa_c_self = array(self::KEY => self::VALUE);
+      public $a_c_self = array(self::KEY => self::VALUE);
+      
+      // Should also include inherited properties from B.
+  }
+  
+  echo "\nStatic properties:\n";
+  var_dump(X::$sa_x, B::$sa_b, C::$sa_b, C::$sa_c_parent, C::$sa_c_self);
+  
+  echo "\nInstance properties:\n";
+  $x = new x;
+  $b = new B;
+  $c = new C;
+  var_dump($x, $b, $c);
+?>
+--EXPECTF--
+
+Static properties:
+array(1) {
+  ["key"]=>
+  string(5) "value"
+}
+array(1) {
+  ["key"]=>
+  string(5) "value"
+}
+array(1) {
+  ["key"]=>
+  string(5) "value"
+}
+array(1) {
+  ["key"]=>
+  string(5) "value"
+}
+array(1) {
+  ["key"]=>
+  string(5) "value"
+}
+
+Instance properties:
+object(X)#%d (1) {
+  ["a_x"]=>
+  array(1) {
+    ["key"]=>
+    string(5) "value"
+  }
+}
+object(B)#%d (1) {
+  ["a_b"]=>
+  array(1) {
+    ["key"]=>
+    string(5) "value"
+  }
+}
+object(C)#%d (3) {
+  ["a_c_parent"]=>
+  array(1) {
+    ["key"]=>
+    string(5) "value"
+  }
+  ["a_c_self"]=>
+  array(1) {
+    ["key"]=>
+    string(5) "value"
+  }
+  ["a_b"]=>
+  array(1) {
+    ["key"]=>
+    string(5) "value"
+  }
+}
diff --git a/tests/classes/constants_basic_005.phpt b/tests/classes/constants_basic_005.phpt
new file mode 100644 (file)
index 0000000..c840f53
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Test constants with default values based on other constants. 
+--FILE--
+<?php
+  class C
+  {
+      const CONST_2 = self::CONST_1;
+      const CONST_1 = self::BASE_CONST;
+      const BASE_CONST = 'hello';
+  }
+  var_dump(C::CONST_1, C::CONST_2);
+?>
+--EXPECTF--
+string(5) "hello"
+string(5) "hello"
+
diff --git a/tests/classes/constants_basic_006.phpt b/tests/classes/constants_basic_006.phpt
new file mode 100644 (file)
index 0000000..73cf0ef
--- /dev/null
@@ -0,0 +1,43 @@
+--TEST--
+Ensure class constants are not evaluated when a class is looked up to resolve inheritance during runtime.
+--FILE--
+<?php
+  class C
+  {
+      const X = E::A;
+      public static $a = array(K => D::V, E::A => K);
+  }
+  
+  eval('class D extends C { const V = \'test\'; }');
+  
+  class E extends D
+  {
+      const A = "hello";
+  }
+  
+  define('K', "nasty");
+  
+  var_dump(C::X, C::$a, D::X, D::$a, E::X, E::$a);
+?>
+--EXPECTF--
+string(5) "hello"
+array(2) {
+  ["nasty"]=>
+  string(4) "test"
+  ["hello"]=>
+  string(5) "nasty"
+}
+string(5) "hello"
+array(2) {
+  ["nasty"]=>
+  string(4) "test"
+  ["hello"]=>
+  string(5) "nasty"
+}
+string(5) "hello"
+array(2) {
+  ["nasty"]=>
+  string(4) "test"
+  ["hello"]=>
+  string(5) "nasty"
+}
diff --git a/tests/classes/constants_error_001.phpt b/tests/classes/constants_error_001.phpt
new file mode 100644 (file)
index 0000000..9bb5533
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+Error case: duplicate class constant definition
+--FILE--
+<?php
+  class myclass
+  {
+      const myConst = "hello";
+      const myConst = "hello again";
+  }
+?>
+--EXPECTF--
+
+Fatal error: Cannot redefine class constant myclass::myConst in %s on line 5
diff --git a/tests/classes/constants_error_002.phpt b/tests/classes/constants_error_002.phpt
new file mode 100644 (file)
index 0000000..be27971
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Error case: class constant as an array
+--FILE--
+<?php
+  class myclass
+  {
+      const myConst = array();
+  }
+?>
+--EXPECTF--
+
+Fatal error: Arrays are not allowed in class constants in %s on line 4
diff --git a/tests/classes/constants_error_003.phpt b/tests/classes/constants_error_003.phpt
new file mode 100644 (file)
index 0000000..c67768c
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Basic class support - attempting to pass a class constant by reference.
+--FILE--
+<?php
+  class aclass
+  {
+      const myConst = "hello";
+  }
+  
+  function f(&$a)
+  {
+      $a = "changed";
+  }
+  
+  f(aclass::myConst);
+  var_dump(aclass::myConst);
+?>
+--EXPECTF--
+
+Fatal error: Only variables can be passed by reference in %s on line 12
diff --git a/tests/classes/constants_error_004.phpt b/tests/classes/constants_error_004.phpt
new file mode 100644 (file)
index 0000000..03e6725
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+Class constant whose initial value refereces a non-existent class
+--FILE--
+<?php
+  class C
+  {
+      const c1 = D::hello;
+  }
+  
+  $a = new C();
+?>
+--EXPECTF--
+Fatal error: Class 'D' not found in %s on line %d
diff --git a/tests/classes/constants_error_005.phpt b/tests/classes/constants_error_005.phpt
new file mode 100644 (file)
index 0000000..1283783
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Error case: class constant as an encapsed containing a variable
+--FILE--
+<?php
+  class myclass
+  {
+      const myConst = "$myVar";
+  }
+?>
+--EXPECTF--
+
+Parse error: %s in %s on line %d
diff --git a/tests/classes/constants_error_006.phpt b/tests/classes/constants_error_006.phpt
new file mode 100644 (file)
index 0000000..f3f14b8
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Basic class support - attempting to modify a class constant by assignment
+--FILE--
+<?php
+  class aclass
+  {
+      const myConst = "hello";
+  }
+  
+  echo "\nTrying to modify a class constant directly - should be parse error.\n";
+  aclass::myConst = "no!!";
+  var_dump(aclass::myConst);
+?>
+--EXPECTF--
+
+Parse error: %s in %s on line %d
diff --git a/tests/classes/constants_error_007.phpt b/tests/classes/constants_error_007.phpt
new file mode 100644 (file)
index 0000000..4be8d88
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Basic class support - attempting to create a reference to a class constant
+--FILE--
+<?php
+  class aclass
+  {
+      const myConst = "hello";
+  }
+  
+  echo "\nAttempting to create a reference to a class constant - should be parse error.\n";
+  $a = &aclass::myConst;
+?>
+--EXPECTF--
+
+Parse error: %s in %s on line %d
diff --git a/tests/classes/final_ctor3.phpt b/tests/classes/final_ctor3.phpt
new file mode 100644 (file)
index 0000000..d37e864
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Ensure implicit final inherited old-style constructor cannot be overridden.
+--FILE--
+<?php
+  class A {
+      final function A() { }
+  }
+  class B extends A {
+  }
+  class C extends B {
+      function B() { }
+  }
+?>
+--EXPECTF--
+Fatal error: Cannot override final method A::B() in %s on line 9
diff --git a/tests/classes/inheritance_005.phpt b/tests/classes/inheritance_005.phpt
new file mode 100644 (file)
index 0000000..b6f47b2
--- /dev/null
@@ -0,0 +1,42 @@
+--TEST--
+Check for inherited old-style constructor.
+--FILE--
+<?php
+  class A
+  {
+      function A()
+      {
+          echo "In " . __METHOD__ . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+  }
+  
+  class C extends B
+  {
+  }
+  
+  
+  echo "About to construct new B: ";
+  $b = new B;
+  echo "About to invoke implicit B::B(): ";
+  $b->B();
+  
+  echo "\nAbout to construct new C: ";
+  $c = new C;
+  echo "About to invoke implicit C::B(): ";
+  $c->B();
+  echo "About to invoke implicit C::C(): ";
+  $c->C();
+?>
+--EXPECTF--
+About to construct new B: In A::A
+About to invoke implicit B::B(): In A::A
+
+About to construct new C: In A::A
+About to invoke implicit C::B(): In A::A
+About to invoke implicit C::C(): In A::A
+
+
diff --git a/tests/classes/method_call_variation_001.phpt b/tests/classes/method_call_variation_001.phpt
new file mode 100644 (file)
index 0000000..dd43cfd
--- /dev/null
@@ -0,0 +1,37 @@
+--TEST--
+In $a->$b[Y](), $b[Y] represents a method name on $a. But in $a->X[Y](), $a->X[Y] represents a global function name.
+--FILE--
+<?php
+  class C
+  {
+      function foo($a, $b)
+      {
+          echo "Called C::foo($a, $b)\n";
+      }
+  }
+  
+  $c = new C;
+  
+  $functions[0] = 'foo';
+  $functions[1][2][3][4] = 'foo';
+  
+  $c->$functions[0](1, 2);
+  $c->$functions[1][2][3][4](3, 4);
+  
+  
+  function foo($a, $b)
+  {
+      echo "Called global foo($a, $b)\n";
+  }
+  
+  $c->functions[0] = 'foo';
+  $c->functions[1][2][3][4] = 'foo';
+  
+  $c->functions[0](5, 6);
+  $c->functions[1][2][3][4](7, 8);
+?>
+--EXPECTF--
+Called C::foo(1, 2)
+Called C::foo(3, 4)
+Called global foo(5, 6)
+Called global foo(7, 8)
diff --git a/tests/classes/new_001.phpt b/tests/classes/new_001.phpt
new file mode 100644 (file)
index 0000000..8ef8a71
--- /dev/null
@@ -0,0 +1,46 @@
+--TEST--
+Confirm difference between assigning new directly and by reference.
+--FILE--
+<?php
+  echo "Compile-time strict error message should precede this.\n";
+  
+  class Inc
+  {
+      private static $counter = 0;
+      function __construct()
+      {
+          $this->id = ++Inc::$counter;
+      }
+  }
+  
+  $f = new Inc();
+  $k =& $f;
+  echo "\$f initially points to the first object:\n";
+  var_dump($f);
+  
+  echo "Assigning new object directly to \$k affects \$f:\n";
+  $k = new Inc();
+  var_dump($f);
+  
+  echo "Assigning new object by ref to \$k removes it from \$f's reference set, so \$f is unchanged:\n";
+  $k =& new Inc();
+  var_dump($f);
+?>
+--EXPECTF--
+Strict Standards: Assigning the return value of new by reference is deprecated in %s on line 23
+Compile-time strict error message should precede this.
+$f initially points to the first object:
+object(Inc)#%d (1) {
+  ["id"]=>
+  int(1)
+}
+Assigning new object directly to $k affects $f:
+object(Inc)#%d (1) {
+  ["id"]=>
+  int(2)
+}
+Assigning new object by ref to $k removes it from $f's reference set, so $f is unchanged:
+object(Inc)#%d (1) {
+  ["id"]=>
+  int(2)
+}
diff --git a/tests/classes/property_override_privateStatic_private.phpt b/tests/classes/property_override_privateStatic_private.phpt
new file mode 100644 (file)
index 0000000..ddd2e5d
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited private static property as private.
+--FILE--
+<?php
+  class A
+  {
+      private static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p (static)
+A::p (static)
+B::p
diff --git a/tests/classes/property_override_privateStatic_privateStatic.phpt b/tests/classes/property_override_privateStatic_privateStatic.phpt
new file mode 100644 (file)
index 0000000..d7d645f
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Redeclare inherited private static property as private static.
+--FILE--
+<?php
+  class A
+  {
+      private static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+A::p (static)
+A::p (static)
+B::p (static)
diff --git a/tests/classes/property_override_privateStatic_protected.phpt b/tests/classes/property_override_privateStatic_protected.phpt
new file mode 100644 (file)
index 0000000..d473216
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited private static property as protected.
+--FILE--
+<?php
+  class A
+  {
+      private static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p (static)
+A::p (static)
+B::p
diff --git a/tests/classes/property_override_privateStatic_protectedStatic.phpt b/tests/classes/property_override_privateStatic_protectedStatic.phpt
new file mode 100644 (file)
index 0000000..169ff9a
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Redeclare inherited private static property as protected static.
+--FILE--
+<?php
+  class A
+  {
+      private static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+A::p (static)
+A::p (static)
+B::p (static)
diff --git a/tests/classes/property_override_privateStatic_public.phpt b/tests/classes/property_override_privateStatic_public.phpt
new file mode 100644 (file)
index 0000000..033eb75
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited private static property as public.
+--FILE--
+<?php
+  class A
+  {
+      private static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p (static)
+A::p (static)
+B::p
diff --git a/tests/classes/property_override_privateStatic_publicStatic.phpt b/tests/classes/property_override_privateStatic_publicStatic.phpt
new file mode 100644 (file)
index 0000000..5f2b6bf
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Redeclare inherited private static property as public static.
+--FILE--
+<?php
+  class A
+  {
+      private static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+A::p (static)
+A::p (static)
+B::p (static)
diff --git a/tests/classes/property_override_private_private.phpt b/tests/classes/property_override_private_private.phpt
new file mode 100644 (file)
index 0000000..2b263ee
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited private property as private.
+--FILE--
+<?php
+  class A
+  {
+      private $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p
+A::p
+B::p
diff --git a/tests/classes/property_override_private_privateStatic.phpt b/tests/classes/property_override_private_privateStatic.phpt
new file mode 100644 (file)
index 0000000..606ed21
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited private property as private static.
+--FILE--
+<?php
+  class A
+  {
+      private $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+A::p
+A::p
+B::p (static)
diff --git a/tests/classes/property_override_private_protected.phpt b/tests/classes/property_override_private_protected.phpt
new file mode 100644 (file)
index 0000000..b84ed67
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited private property as protected.
+--FILE--
+<?php
+  class A
+  {
+      private $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p
+A::p
+B::p
diff --git a/tests/classes/property_override_private_protectedStatic.phpt b/tests/classes/property_override_private_protectedStatic.phpt
new file mode 100644 (file)
index 0000000..1bb303d
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited private property as protected static.
+--FILE--
+<?php
+  class A
+  {
+      private $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+A::p
+A::p
+B::p (static)
diff --git a/tests/classes/property_override_private_public.phpt b/tests/classes/property_override_private_public.phpt
new file mode 100644 (file)
index 0000000..badbe91
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited private property as public.
+--FILE--
+<?php
+  class A
+  {
+      private $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p
+A::p
+B::p
diff --git a/tests/classes/property_override_private_publicStatic.phpt b/tests/classes/property_override_private_publicStatic.phpt
new file mode 100644 (file)
index 0000000..9fc58ec
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited private property as public static.
+--FILE--
+<?php
+  class A
+  {
+      private $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+A::p
+A::p
+B::p (static)
diff --git a/tests/classes/property_override_protectedStatic_private.phpt b/tests/classes/property_override_protectedStatic_private.phpt
new file mode 100644 (file)
index 0000000..18e9c78
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited protected static property as private.
+--FILE--
+<?php
+  class A
+  {
+      protected static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18
+
diff --git a/tests/classes/property_override_protectedStatic_privateStatic.phpt b/tests/classes/property_override_protectedStatic_privateStatic.phpt
new file mode 100644 (file)
index 0000000..6886210
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Redeclare inherited protected static property as private static.
+--FILE--
+<?php
+  class A
+  {
+      protected static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Access level to B::$p must be protected (as in class A) or weaker in %s on line 18
+
diff --git a/tests/classes/property_override_protectedStatic_protected.phpt b/tests/classes/property_override_protectedStatic_protected.phpt
new file mode 100644 (file)
index 0000000..0e5fdd3
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited protected static property as protected.
+--FILE--
+<?php
+  class A
+  {
+      protected static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18
+
diff --git a/tests/classes/property_override_protectedStatic_protectedStatic.phpt b/tests/classes/property_override_protectedStatic_protectedStatic.phpt
new file mode 100644 (file)
index 0000000..16f1100
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Redeclare inherited protected static property as protected static.
+--FILE--
+<?php
+  class A
+  {
+      protected static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+A::p (static)
+A::p (static)
+B::p (static)
diff --git a/tests/classes/property_override_protectedStatic_public.phpt b/tests/classes/property_override_protectedStatic_public.phpt
new file mode 100644 (file)
index 0000000..6303325
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited protected static property as public.
+--FILE--
+<?php
+  class A
+  {
+      protected static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18
+
diff --git a/tests/classes/property_override_protectedStatic_publicStatic.phpt b/tests/classes/property_override_protectedStatic_publicStatic.phpt
new file mode 100644 (file)
index 0000000..7e1955d
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+Redeclare inherited protected static property as public static.
+--FILE--
+<?php
+  class A
+  {
+      protected static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot change initial value of property static protected A::$p in class B in %s on line 18
diff --git a/tests/classes/property_override_protected_private.phpt b/tests/classes/property_override_protected_private.phpt
new file mode 100644 (file)
index 0000000..93f0d23
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited protected property as private.
+Included for completeness (duplicates test Zend/tests/errmsg_023.phpt).
+--FILE--
+<?php
+  class A
+  {
+      protected $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Access level to B::$p must be protected (as in class A) or weaker in %s on line 18
diff --git a/tests/classes/property_override_protected_privateStatic.phpt b/tests/classes/property_override_protected_privateStatic.phpt
new file mode 100644 (file)
index 0000000..fb7102c
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited protected property as private static.
+--FILE--
+<?php
+  class A
+  {
+      protected $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18
diff --git a/tests/classes/property_override_protected_protected.phpt b/tests/classes/property_override_protected_protected.phpt
new file mode 100644 (file)
index 0000000..c4b0d43
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited protected property as protected.
+--FILE--
+<?php
+  class A
+  {
+      protected $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p
+B::p
+B::p
diff --git a/tests/classes/property_override_protected_protectedStatic.phpt b/tests/classes/property_override_protected_protectedStatic.phpt
new file mode 100644 (file)
index 0000000..1ce4130
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited protected property as protected static.
+--FILE--
+<?php
+  class A
+  {
+      protected $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18
diff --git a/tests/classes/property_override_protected_public.phpt b/tests/classes/property_override_protected_public.phpt
new file mode 100644 (file)
index 0000000..4702f9a
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited protected property as public.
+--FILE--
+<?php
+  class A
+  {
+      protected $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p
+B::p
+B::p
diff --git a/tests/classes/property_override_protected_publicStatic.phpt b/tests/classes/property_override_protected_publicStatic.phpt
new file mode 100644 (file)
index 0000000..8efdf5f
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited protected property as public static.
+--FILE--
+<?php
+  class A
+  {
+      protected $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18
diff --git a/tests/classes/property_override_publicStatic_private.phpt b/tests/classes/property_override_publicStatic_private.phpt
new file mode 100644 (file)
index 0000000..7abe92c
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited public static property as private.
+--FILE--
+<?php
+  class A
+  {
+      public static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18
+
diff --git a/tests/classes/property_override_publicStatic_privateStatic.phpt b/tests/classes/property_override_publicStatic_privateStatic.phpt
new file mode 100644 (file)
index 0000000..d41db6d
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Redeclare inherited public static property as private static.
+--FILE--
+<?php
+  class A
+  {
+      public static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Access level to B::$p must be public (as in class A) in %s on line 18
+
diff --git a/tests/classes/property_override_publicStatic_protected.phpt b/tests/classes/property_override_publicStatic_protected.phpt
new file mode 100644 (file)
index 0000000..884159f
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited public static property as protected.
+--FILE--
+<?php
+  class A
+  {
+      public static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18
+
diff --git a/tests/classes/property_override_publicStatic_protectedStatic.phpt b/tests/classes/property_override_publicStatic_protectedStatic.phpt
new file mode 100644 (file)
index 0000000..b022ef8
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Redeclare inherited public static property as protected static.
+--FILE--
+<?php
+  class A
+  {
+      public static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Access level to B::$p must be public (as in class A) in %s on line 18
+
diff --git a/tests/classes/property_override_publicStatic_public.phpt b/tests/classes/property_override_publicStatic_public.phpt
new file mode 100644 (file)
index 0000000..d099da0
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited public static property as public.
+--FILE--
+<?php
+  class A
+  {
+      public static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18
+
diff --git a/tests/classes/property_override_publicStatic_publicStatic.phpt b/tests/classes/property_override_publicStatic_publicStatic.phpt
new file mode 100644 (file)
index 0000000..9a86867
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Redeclare inherited public static property as public static.
+--FILE--
+<?php
+  class A
+  {
+      public static $p = "A::p (static)";
+      static function showA()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  A::showA();
+  
+  B::showA();
+  B::showB();
+?>
+--EXPECTF--
+A::p (static)
+A::p (static)
+B::p (static)
diff --git a/tests/classes/property_override_public_private.phpt b/tests/classes/property_override_public_private.phpt
new file mode 100644 (file)
index 0000000..c0f37ad
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited public property as private.
+--FILE--
+<?php
+  class A
+  {
+      public $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Access level to B::$p must be public (as in class A) in %s on line 18
+
diff --git a/tests/classes/property_override_public_privateStatic.phpt b/tests/classes/property_override_public_privateStatic.phpt
new file mode 100644 (file)
index 0000000..36223fd
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited public property as private static.
+--FILE--
+<?php
+  class A
+  {
+      public $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      private static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18
diff --git a/tests/classes/property_override_public_protected.phpt b/tests/classes/property_override_public_protected.phpt
new file mode 100644 (file)
index 0000000..68fdf82
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited public property as protected.
+--FILE--
+<?php
+  class A
+  {
+      public $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+
+Fatal error: Access level to B::$p must be public (as in class A) in %s on line 18
+
diff --git a/tests/classes/property_override_public_protectedStatic.phpt b/tests/classes/property_override_public_protectedStatic.phpt
new file mode 100644 (file)
index 0000000..77e7ebf
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited public property as protected static.
+--FILE--
+<?php
+  class A
+  {
+      public $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      protected static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18
diff --git a/tests/classes/property_override_public_public.phpt b/tests/classes/property_override_public_public.phpt
new file mode 100644 (file)
index 0000000..893fe5d
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Redeclare inherited public property as public.
+--FILE--
+<?php
+  class A
+  {
+      public $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public $p = "B::p";
+      function showB()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  $b->showB();
+?>
+--EXPECTF--
+A::p
+B::p
+B::p
diff --git a/tests/classes/property_override_public_publicStatic.phpt b/tests/classes/property_override_public_publicStatic.phpt
new file mode 100644 (file)
index 0000000..725e947
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Redeclare inherited public property as public static.
+--FILE--
+<?php
+  class A
+  {
+      public $p = "A::p";
+      function showA()
+      {
+          echo $this->p . "\n";
+      }
+  }
+  
+  class B extends A
+  {
+      public static $p = "B::p (static)";
+      static function showB()
+      {
+          echo self::$p . "\n";
+      }
+  }
+  
+  
+  $a = new A;
+  $a->showA();
+  
+  $b = new B;
+  $b->showA();
+  B::showB();
+?>
+--EXPECTF--
+
+Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18
diff --git a/tests/classes/type_hinting_004.phpt b/tests/classes/type_hinting_004.phpt
new file mode 100644 (file)
index 0000000..9068909
--- /dev/null
@@ -0,0 +1,109 @@
+--TEST--
+Ensure type hints are enforced for functions invoked as callbacks.
+--FILE--
+<?php
+  set_error_handler('myErrorHandler', E_RECOVERABLE_ERROR);
+  function myErrorHandler($errno, $errstr, $errfile, $errline) {
+      echo "$errno: $errstr - $errfile($errline)\n";
+      return true;
+  }
+  
+  echo "---> Type hints with callback function:\n";
+  class A  {  }
+  function f1(A $a)  {
+      echo "in f1;\n";
+  }
+  function f2(A $a = null)  {
+      echo "in f2;\n";
+  }
+  call_user_func('f1', 1);
+  call_user_func('f1', new A);
+  call_user_func('f2', 1);
+  call_user_func('f2');
+  call_user_func('f2', new A);
+  call_user_func('f2', null);
+  
+  
+  echo "\n\n---> Type hints with callback static method:\n";
+  class C {
+      static function f1(A $a) {
+          if (isset($this)) {
+              echo "in C::f1 (instance);\n";
+          } else {
+              echo "in C::f1 (static);\n";
+          }
+      }
+      static function f2(A $a = null) {
+          if (isset($this)) {
+              echo "in C::f2 (instance);\n";
+          } else {
+              echo "in C::f2 (static);\n";
+          }
+      }
+  }
+  call_user_func(array('C', 'f1'), 1);
+  call_user_func(array('C', 'f1'), new A);
+  call_user_func(array('C', 'f2'), 1);
+  call_user_func(array('C', 'f2'));
+  call_user_func(array('C', 'f2'), new A);
+  call_user_func(array('C', 'f2'), null);
+  
+  
+  echo "\n\n---> Type hints with callback instance method:\n";
+  class D {
+      function f1(A $a) {
+          if (isset($this)) {
+              echo "in C::f1 (instance);\n";
+          } else {
+              echo "in C::f1 (static);\n";
+          }
+      }
+      function f2(A $a = null) {
+          if (isset($this)) {
+              echo "in C::f2 (instance);\n";
+          } else {
+              echo "in C::f2 (static);\n";
+          }
+      }
+  }
+  $d = new D;
+  call_user_func(array($d, 'f1'), 1);
+  call_user_func(array($d, 'f1'), new A);
+  call_user_func(array($d, 'f2'), 1);
+  call_user_func(array($d, 'f2'));
+  call_user_func(array($d, 'f2'), new A);
+  call_user_func(array($d, 'f2'), null);
+  
+?>
+--EXPECTF--
+---> Type hints with callback function:
+4096: Argument 1 passed to f1() must be an instance of A, integer given%s(10)
+in f1;
+in f1;
+4096: Argument 1 passed to f2() must be an instance of A, integer given%s(13)
+in f2;
+in f2;
+in f2;
+in f2;
+
+
+---> Type hints with callback static method:
+4096: Argument 1 passed to C::f1() must be an instance of A, integer given%s(26)
+in C::f1 (static);
+in C::f1 (static);
+4096: Argument 1 passed to C::f2() must be an instance of A, integer given%s(33)
+in C::f2 (static);
+in C::f2 (static);
+in C::f2 (static);
+in C::f2 (static);
+
+
+---> Type hints with callback instance method:
+4096: Argument 1 passed to D::f1() must be an instance of A, integer given%s(51)
+in C::f1 (instance);
+in C::f1 (instance);
+4096: Argument 1 passed to D::f2() must be an instance of A, integer given%s(58)
+in C::f2 (instance);
+in C::f2 (instance);
+in C::f2 (instance);
+in C::f2 (instance);