Arquivos
hhvm/hphp/test/test_code_run.cpp
T
2013-02-13 06:42:43 -08:00

34207 linhas
976 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include <test/test_code_run.h>
#include <compiler/parser/parser.h>
#include <compiler/builtin_symbols.h>
#include <compiler/code_generator.h>
#include <compiler/analysis/analysis_result.h>
#include <compiler/analysis/type.h>
#include <util/util.h>
#include <util/process.h>
#include <compiler/option.h>
#include <runtime/base/runtime_option.h>
#include <pcre.h>
#include <hphp/test/test_mysql_info.h>
#include <runtime/ext/ext_file.h>
using std::istringstream;
using std::ostringstream;
///////////////////////////////////////////////////////////////////////////////
const char *TestCodeRun::Filter = 0;
// By default, use shared linking for faster testing.
bool TestCodeRun::FastMode = true;
TestCodeRun::TestCodeRun() : m_perfMode(false), m_test(0) {
Option::GenerateCPPMain = true;
Option::GenerateCPPMetaInfo = true;
Option::GenerateCPPMacros = true;
Option::GenerateCPPComments = true;
Option::GenerateCPPNameSpace = true;
Option::KeepStatementsWithNoEffect = false;
Option::ParserThreadCount = 4;
}
bool TestCodeRun::preTest() {
if (!CleanUp()) return false;
m_infos.clear();
return true;
}
bool TestCodeRun::postTest() {
if (!MultiVerifyCodeRun()) return false;
return true;
}
bool TestCodeRun::CleanUp() {
string out, err;
const char *argv[] = {"", NULL};
Process::Exec("runtime/tmp/cleanup.sh", argv, NULL, out, &err);
if (!err.empty()) {
printf("Failed to clean up runtime/tmp: %s\n", err.c_str());
return false;
}
return true;
}
static bool GenerateMainPHP(const std::string &fullPath,
const char *file, int line,
const char *input) {
Util::mkdir(fullPath.c_str());
std::ofstream f(fullPath.c_str());
if (!f) {
printf("Unable to open %s for write. Run this test from hphp/.\n",
fullPath.c_str());
return false;
}
if (file && !strncmp(input, "<?php", 5)) {
f << "<?php\n# " << file << ":" << line << "\n";
f << (input + 5);
} else {
f << input;
}
f.close();
return true;
}
bool TestCodeRun::GenerateFiles(const char *input,
const char *subdir) {
assert(subdir && subdir[0]);
// generate main.php early, so if we fail, we have a PHP file to debug with
string fullPath = "runtime/tmp";
if (subdir && subdir[0]) fullPath = fullPath + "/" + subdir;
fullPath += "/main.php";
if (!GenerateMainPHP(fullPath, 0, 0, input)) return false;
// load the type hints
Type::ResetTypeHintTypes();
Type::InitTypeHintMap();
BuiltinSymbols::LoadSuperGlobals();
AnalysisResultPtr ar(new AnalysisResult());
string path = string("runtime/tmp/") + subdir;
ar->setOutputPath(path.c_str());
Compiler::Parser::ParseString(input, ar);
BuiltinSymbols::Load(ar);
ar->loadBuiltins();
ar->analyzeProgram();
ar->preOptimize();
ar->analyzeIncludes();
ar->inferTypes();
ar->postOptimize();
ar->analyzeProgramFinal();
ar->outputAllCPP(CodeGenerator::ClusterCPP, 0, NULL);
string target = path + "/Makefile";
const char *argv1[] = {"", "runtime/tmp/single.mk", target.c_str(), NULL};
string out, err;
Process::Exec("cp", argv1, NULL, out, &err);
if (!err.empty()) {
printf("Failed to copy runtime/tmp/single.mk: %s\n", err.c_str());
return false;
}
if (FastMode) {
string sys = string(subdir) + "/sys";
const char *argv2[] = {"", sys.c_str(), NULL};
Process::Exec("runtime/tmp/mergecpp.sh", argv2, NULL, out, &err);
if (!err.empty()) {
printf("Failed to merge runtime/tmp/%s/*.cpp: %s\n",
sys.c_str(), err.c_str());
return false;
}
}
return true;
}
static string filter_distcc(string &msg) {
istringstream is(msg);
ostringstream os;
string line;
while (getline(is, line)) {
if (line.compare(0, 6, "distcc")) {
os << line << '\n';
}
}
return os.str();
}
bool TestCodeRun::CompileFiles() {
string out, err;
const char *argv[] = {"", FastMode ? "SHARED" : "LINK", NULL};
Process::Exec("runtime/makeall.sh", argv, NULL, out, &err);
err = filter_distcc(err);
if (!err.empty()) {
printf("Failed to compile files:\n");
istringstream is(err);
string line;
string buffer;
while (getline(is, line)) {
buffer += line + "\n";
if (!line.compare(0, 4, "make")) {
unsigned int start = 0;
while (start < line.length() && line.compare(start, 4, "Test")) {
start++;
}
if (start < line.length()) {
istringstream isl(line.substr(start + 4));
int seqno;
if (isl >> seqno) {
printf("======================================\n"
"runtime/tmp/Test%d/main.php:\n"
"======================================\n",
seqno);
printf("\n%s:%d\nParsing: [%s]\n%s\n", m_infos[seqno].file,
m_infos[seqno].line, m_infos[seqno].input, buffer.c_str());
buffer = "";
}
}
}
}
if (!buffer.empty()) {
// leftover error messages, if any
printf("\n%s\n", buffer.c_str());
}
return false;
}
return true;
}
static string escape(const std::string &s) {
string ret;
ret.reserve(s.size() + 20);
for (unsigned int i = 0; i < s.length(); i++) {
char ch = s[i];
if (isprint(ch) || ch == '\n') {
ret += ch;
} else {
char buf[10];
snprintf(buf, sizeof(buf), "{\\x%02X}", (unsigned char)ch);
ret += buf;
}
}
return ret;
}
static bool verify_result(const char *input, const char *output, bool perfMode,
const char *file = "", int line = 0,
bool nowarnings = false,
bool fileoutput = false,
const char *subdir = "",
bool fastMode = false) {
// generate main.php
string fullPath = "runtime/tmp";
if (subdir && subdir[0]) fullPath = fullPath + "/" + subdir;
fullPath += "/main.php";
if (!GenerateMainPHP(fullPath, 0, 0, input)) return false;
// get PHP's output if "output" is NULL
string expected;
if (output) {
if (fileoutput) {
String s = f_file_get_contents(output);
expected = string(s.data(), s.size());
} else {
expected = output;
}
} else {
const char *argv1[] = {"", "-ddisplay_errors=stderr",
"-dapc.enable_cli=1",
fullPath.c_str(), NULL};
const char *argv2[] = {"", "-ddisplay_errors=On",
"-dapc.enable_cli=1",
fullPath.c_str(), NULL};
string err;
Process::Exec(php_path, nowarnings ? argv2 : argv1, NULL, expected, &err);
if (!err.empty() && nowarnings) {
printf("%s:%d\nParsing: [%s]\nFailed to run %s: %s\n",
file, line, input, fullPath.c_str(), err.c_str());
return false;
}
}
// run and verify output
{
string actual, err;
string dir = "runtime/tmp/";
if (subdir) dir = dir + subdir + "/";
string repoarg = "-vRepo.Central.Path=" + dir + "hhvm.hhbc";
if (Option::EnableEval < Option::FullEval) {
if (fastMode) {
string path = dir + "libtest.so";
const char *argv[] = {"", "--file=string", "--config=test/config.hdf",
repoarg.c_str(), path.c_str(), NULL};
Process::Exec("runtime/tmp/run.sh", argv, NULL, actual, &err);
} else {
const char *argv[] = {"", "--file=string", "--config=test/config.hdf",
repoarg.c_str(), NULL};
string path = dir + "test";
Process::Exec(path.c_str(), argv, NULL, actual, &err);
}
} else {
string filearg = "--file=" + dir + "main.php";
string jitarg = string("-vEval.Jit=") +
(RuntimeOption::EvalJit ? "true" : "false");
string jit_use_ir = string("-vEval.JitUseIR=") +
(RuntimeOption::EvalJitUseIR ? "true" : "false");
string jit_rename = string("-vEval.JitEnableRenameFunction=") +
(RuntimeOption::EvalJit ? "true" : "false");
const char *argv[] = {"", filearg.c_str(),
"--config=test/config.hdf",
repoarg.c_str(),
jitarg.c_str(),
jit_use_ir.c_str(),
jit_rename.c_str(),
NULL};
Process::Exec(HHVM_PATH, argv, NULL, actual, &err);
}
if (perfMode) {
string sinput = input;
const char *marker = "/* INPUT */";
int pos1 = sinput.find(marker);
int pos2 = sinput.find(marker, pos1+1);
pos1 += strlen(marker);
sinput = sinput.substr(pos1, pos2 - pos1);
if (sinput.size() > 1000) sinput = "(long program)";
// we have to adjust timing by removing loop cost, which is the 1st test
static int adj1 = -1;
static int adj2 = -1;
int ms1 = atoi(expected.c_str());
int ms2 = atoi(actual.c_str());
if (adj1 == -1) adj1 = ms1;
if (adj2 == -1) adj2 = ms2;
int msAdj1 = ms1 - adj1;
int msAdj2 = ms2 - adj2;
double x = 0.0; // how many times faster
double p = 0.0; // percentage
if (msAdj2 != 0) {
x = ((double)(int)(msAdj1 * 100 / msAdj2)) / 100;
}
if (msAdj1 != 0) {
p = ((double)(int)(msAdj2 * 10000 / msAdj1)) / 100;
}
printf("----------------------------------------------------------\n"
"%s\n\n"
" PHP C++\n"
"===========================================\n"
" %6d ms %6d ms\n"
" -%6d ms %6d ms\n"
"===========================================\n"
" %6d ms %6d ms = %2.4gx or %2.4g%%\n\n",
sinput.c_str(), ms1, ms2, adj1, adj2, msAdj1, msAdj2, x, p);
return true;
}
bool out_ok = actual == expected;
if (!out_ok || (!nowarnings && !err.empty())) {
if (out_ok &&
err.find("symbol lookup error:") != string::npos &&
err.find("undefined symbol: ") != string::npos) {
printf("%s: Ignoring loader error: %s\n",
fullPath.c_str(), err.c_str());
} else {
printf("======================================\n"
"%s:\n"
"======================================\n"
"%s:%d\nParsing: [%s]\nBet %d:\n"
"--------------------------------------\n"
"%s"
"--------------------------------------\n"
"Got %d:\n"
"--------------------------------------\n"
"%s"
"--------------------------------------\n"
"Err: [%s]\n", fullPath.c_str(), file, line, input,
(int)expected.length(), escape(expected).c_str(),
(int)actual.length(), escape(actual).c_str(),
err.c_str());
return false;
}
}
}
return true;
}
bool TestCodeRun::RecordMulti(const char *input, const char *output,
const char *file, int line, bool nowarnings,
bool fileoutput) {
if (Filter) {
const char *errptr;
int erroffset;
pcre *re = pcre_compile(Filter, PCRE_CASELESS, &errptr, &erroffset, 0);
if (re && pcre_exec(re, 0, input, strlen(input), 0, 0, 0, 0) >= 0) {
return true;
}
}
string fullPath = "runtime/tmp/" + Test::s_suite + "/" + test_name + "/tcr-" +
boost::lexical_cast<string>(m_test++);
if (!GenerateMainPHP(fullPath + "/main.php", file, line, input)) return false;
if (nowarnings) {
std::ofstream((fullPath + "/nowarnings").c_str());
}
if (!m_compileOptions.empty()) {
std::ofstream s((fullPath + "/build.opts").c_str());
s << m_compileOptions;
}
if (!m_runtimeOptions.empty()) {
std::ofstream s((fullPath + "/test.opts").c_str());
s << m_runtimeOptions;
}
if (!m_envVars.empty()) {
std::ofstream s((fullPath + "/test.env").c_str());
s << m_envVars;
}
if (output) {
std::ofstream s((fullPath + "/test.result").c_str());
if (fileoutput) {
String expected = f_file_get_contents(output);
s << string(expected.data(), expected.size());
} else {
s << output;
}
}
return true;
}
bool TestCodeRun::MultiVerifyCodeRun() {
return true;
if (Option::EnableEval < Option::FullEval) {
CompileFiles();
}
bool ret = true;
for (unsigned i = 0; i < m_infos.size(); i++) {
assert(m_infos[i].input);
ostringstream os;
os << "Test" << i;
if (!Count(verify_result(m_infos[i].input, m_infos[i].output, m_perfMode,
m_infos[i].file, m_infos[i].line,
m_infos[i].nowarnings,
m_infos[i].fileoutput, os.str().c_str(),
FastMode))) {
ret = false;
}
}
return ret;
}
bool TestCodeRun::VerifyCodeRun(const char *input, const char *output,
const char *file /* = "" */,
int line /* = 0 */,
bool nowarnings /* = false */,
bool fileoutput /* = false */) {
assert(input);
if (!CleanUp()) return false;
if (Option::EnableEval < Option::FullEval) {
if (!GenerateFiles(input, "Test0") || !CompileFiles()) {
return false;
}
}
return verify_result(input, output, m_perfMode,
file, line, nowarnings, fileoutput, "Test0", FastMode);
}
///////////////////////////////////////////////////////////////////////////////
#define GEN_TEST(test) \
if (!which.empty() && which != #test) { \
} else { \
test_name = #test; \
test(); \
}
bool TestCodeRun::RunTests(const std::string &which) {
CleanUp();
bool ret = true;
GEN_TEST(TestSanity);
GEN_TEST(TestInnerFunction);
GEN_TEST(TestInnerClass);
GEN_TEST(TestVariableArgument);
GEN_TEST(TestArgumentHandling);
GEN_TEST(TestListAssignment);
GEN_TEST(TestExceptions);
GEN_TEST(TestPredefined);
GEN_TEST(TestLabels);
GEN_TEST(TestPerfectVirtual);
GEN_TEST(TestBoolean);
GEN_TEST(TestInteger);
GEN_TEST(TestDouble);
GEN_TEST(TestString);
GEN_TEST(TestLocale);
GEN_TEST(TestArray);
GEN_TEST(TestArrayInit);
GEN_TEST(TestArrayCopy);
GEN_TEST(TestArrayEscalation);
GEN_TEST(TestArrayOffset);
GEN_TEST(TestArrayAccess);
GEN_TEST(TestArrayIterator);
GEN_TEST(TestArrayForEach);
GEN_TEST(TestArrayAssignment);
GEN_TEST(TestArrayFunctions);
GEN_TEST(TestArrayCSE);
GEN_TEST(TestScalarArray);
GEN_TEST(TestRange);
GEN_TEST(TestVariant);
GEN_TEST(TestObject);
GEN_TEST(TestObjectProperty);
GEN_TEST(TestObjectMethod);
GEN_TEST(TestClassMethod);
GEN_TEST(TestObjectMagicMethod);
GEN_TEST(TestObjectInvokeMethod);
GEN_TEST(TestObjectAssignment);
GEN_TEST(TestNewObjectExpression);
GEN_TEST(TestObjectPropertyExpression);
GEN_TEST(TestCollectionClasses);
GEN_TEST(TestComparisons);
GEN_TEST(TestReference);
GEN_TEST(TestUnset);
GEN_TEST(TestDynamicConstants);
GEN_TEST(TestDynamicVariables);
GEN_TEST(TestDynamicProperties);
GEN_TEST(TestDynamicFunctions);
GEN_TEST(TestRenameFunction);
GEN_TEST(TestIntercept);
GEN_TEST(TestMaxInt);
GEN_TEST(TestDynamicMethods);
GEN_TEST(TestVolatile);
GEN_TEST(TestHereDoc);
GEN_TEST(TestProgramFunctions);
GEN_TEST(TestCompilation);
GEN_TEST(TestReflection);
GEN_TEST(TestReflectionClasses);
GEN_TEST(TestErrorHandler);
GEN_TEST(TestAssertOptions);
GEN_TEST(TestExtMisc);
GEN_TEST(TestInvalidArgument);
GEN_TEST(TestSuperGlobals);
GEN_TEST(TestGlobalStatement);
GEN_TEST(TestStaticStatement);
GEN_TEST(TestIfStatement);
GEN_TEST(TestBreakStatement);
GEN_TEST(TestContinueStatement);
GEN_TEST(TestReturnStatement);
GEN_TEST(TestAdd);
GEN_TEST(TestMinus);
GEN_TEST(TestMultiply);
GEN_TEST(TestDivide);
GEN_TEST(TestModulus);
GEN_TEST(TestOperationTypes);
GEN_TEST(TestUnaryOperators);
GEN_TEST(TestSilenceOperator);
GEN_TEST(TestPrint);
GEN_TEST(TestVarExport);
GEN_TEST(TestLogicalOperators);
GEN_TEST(TestGetClass);
GEN_TEST(TestGetParentClass);
GEN_TEST(TestRedeclaredFunctions);
GEN_TEST(TestRedeclaredClasses);
GEN_TEST(TestReassignThis);
GEN_TEST(TestClone);
GEN_TEST(TestEvalOrder);
GEN_TEST(TestGetObjectVars);
GEN_TEST(TestSerialization);
GEN_TEST(TestJson);
GEN_TEST(TestThrift);
GEN_TEST(TestExit);
GEN_TEST(TestCreateFunction);
GEN_TEST(TestConstructorDestructor);
GEN_TEST(TestConcat);
GEN_TEST(TestConstant);
GEN_TEST(TestClassConstant);
GEN_TEST(TestConstantFunction);
GEN_TEST(TestDefined);
GEN_TEST(TestSimpleXML);
GEN_TEST(TestXML);
GEN_TEST(TestDOMDocument);
GEN_TEST(TestFile);
GEN_TEST(TestDirectory);
GEN_TEST(TestAssignment);
GEN_TEST(TestBadFunctionCalls);
GEN_TEST(TestConstructor);
GEN_TEST(TestIntIsset);
GEN_TEST(TestTernary);
GEN_TEST(TestUselessAssignment);
GEN_TEST(TestTypes);
GEN_TEST(TestSwitchStatement);
GEN_TEST(TestExtString);
GEN_TEST(TestExtArray);
GEN_TEST(TestExtFile);
GEN_TEST(TestExtDate);
GEN_TEST(TestExtImage);
GEN_TEST(TestExtSplFile);
GEN_TEST(TestExtIterator);
GEN_TEST(TestExtSoap);
GEN_TEST(TestExtCollator);
GEN_TEST(TestExtSocket);
GEN_TEST(TestAPC);
GEN_TEST(TestInlining);
GEN_TEST(TestCopyProp);
GEN_TEST(TestParser);
GEN_TEST(TestTypeAssertions);
GEN_TEST(TestSerialize);
if (Option::EnableEval == Option::FullEval) {
// hphpc is intentionally more liberal with its hoisting rules
GEN_TEST(TestHoisting);
}
// PHP 5.3 features
GEN_TEST(TestVariableClassName);
GEN_TEST(TestLateStaticBinding);
GEN_TEST(TestCallStatic);
GEN_TEST(TestNowDoc);
GEN_TEST(TestTernaryShortcut);
GEN_TEST(TestGoto);
GEN_TEST(TestClosure);
if (!hhvm) {
GEN_TEST(TestNamespace);
}
// PHP 5.4 features
GEN_TEST(TestTraits);
// PHP 5.5 features
GEN_TEST(TestUConverter);
// HipHop features
GEN_TEST(TestYield);
GEN_TEST(TestHint);
GEN_TEST(TestUserAttributes);
#ifdef TAINTED
GEN_TEST(TestTaint);
GEN_TEST(TestTaintExt);
#endif
GEN_TEST(TestStrictMode);
GEN_TEST(TestAdHoc);
{
// We have a still unresolved repo contention issues with more
// than 20 jobs. t1394416
int cpus = std::min(20, Process::GetCPUCount());
int jobs = cpus;
char* hphp_slow_tests_jobs = getenv("HPHP_SLOW_TESTS_JOBS");
if (hphp_slow_tests_jobs) {
int n = atoi(hphp_slow_tests_jobs);
if (n > 0) jobs = n;
}
string cmd =
"env -u MFLAGS -u MAKEFLAGS "
"make -f runtime/tmp/test.mk --no-print-directory "
"SUITE="+Test::s_suite +
" -j" + boost::lexical_cast<string>(jobs);
if (::system(cmd.c_str())) {
printf("Failed to run testsuite: %s\n", Test::s_suite.c_str());
return false;
}
std::ifstream in(("runtime/tmp/"+Test::s_suite+"/results").c_str());
if (in.fail()) return false;
in >> fail_count;
in >> pass_count;
int total;
in >> total;
Test::s_passed = pass_count;
Test::s_total = total;
return total == pass_count && !fail_count;
}
return ret;
}
///////////////////////////////////////////////////////////////////////////////
// code generation
bool TestCodeRun::TestSanity() {
MVCR("<?php print 'Hello, World!';");
MVCR("Hello, World!");
MVCR("#!/usr/bin/php\n"
"<?php\n");
MVCR("#!/usr/bin/php\n"
"\n"
"<?php\n");
MVCR("#!/usr/bin/env <?php\n"
"#!/usr/bin/env php\n"
"a /* show or not */ b\n"
"Hello, World! # comments\n"
"<?php\n"
"print 'hello'; # comments");
MVCR("<?php if (true) { ?>#<?php } ?>");
return true;
}
bool TestCodeRun::TestInnerFunction() {
MVCR("<?php function test() { print 'test';} test();");
MVCR("<?php function test() { function inner() { print 'test';} inner();} "
"test();");
return true;
}
bool TestCodeRun::TestInnerClass() {
MVCR("<?php class test { function p() { print 'test';} } "
"$obj = new Test(); $obj->p();");
MVCR("<?php class test { function p() { function inner() { print 'test';} "
"inner();} } $obj = new Test(); $obj->p();");
MVCR("<?php function test() { class test { function p() { print 'test';} }} "
"test(); $obj = new Test(); $obj->p();");
return true;
}
bool TestCodeRun::TestVariableArgument() {
MVCR("<?php function test() { "
" $n = func_num_args(); "
" var_dump($n);"
" $args = func_get_args();"
" var_dump($args);"
"} "
"test(); test(1); test(1, 2);");
MVCR("<?php function test() { "
" var_dump(func_get_arg(0));"
" var_dump(func_get_arg(1));"
"} "
"test(2, 'ok');");
MVCR("<?php function test($a) { "
" $n = func_num_args(); "
" var_dump($n);"
" $args = func_get_args();"
" var_dump($args);"
"} "
"test(1); test(1, 2); test(1, 2, 3);");
MVCR("<?php function test($a) { "
" var_dump(func_get_arg(0));"
" var_dump(func_get_arg(1));"
" var_dump(func_get_arg(2));"
"} "
"test(2, 'ok', array(1));");
MVCR("<?php function test($a, $b) { "
" $n = func_num_args(); "
" var_dump($n);"
" $args = func_get_args();"
" var_dump($args);"
"} "
"test(1, 2); test(1, 2, 3); test(1, 2, 3, 4);");
MVCR("<?php function test() { "
" var_dump(func_get_arg(0));"
" var_dump(func_get_arg(1));"
" var_dump(func_get_arg(2));"
" var_dump(func_get_arg(3));"
"} "
"test(2, 'ok', 0, 'test');");
MVCR("<?php function test($a) { "
" $n = func_num_args(); "
" var_dump($n);"
" $args = func_get_args();"
" var_dump($args);"
"} "
"test('test'); test(1, 2); test(1, 2, 3);");
MVCR("<?php class A { public function test($a) {"
" var_dump(func_num_args());"
" var_dump(func_get_args());"
"}} $obj = new A(); $obj->test('test'); $obj->test(1, 2, 3);");
MVCR("<?php class A { public function __construct($a) {"
" var_dump(func_num_args());"
" var_dump(func_get_args());"
"}} $obj = new A(1, 2, 3); $obj = new A('test');");
MVCR("<?php function test($a = 10) { "
" var_dump($a);"
" var_dump(func_get_args());"
"} "
"test(); test(1); test(1, 2);");
MVCR("<?php function test($a, $b = 10) { "
" var_dump($a);"
" var_dump($b);"
" var_dump(func_get_args());"
"} "
"test(1); test(1, 2); test(1, 2, 3);");
// testing variable argument + reference parameter
MVCR("<?php $ar1 = array(10, 100, 100, 0); $ar2 = array(1, 3, 2, 4);"
"array_multisort($ar1, $ar2); var_dump($ar1, $ar2);");
MVCR("<?php "
"class Foo {"
" public static function Add($x, $y) {}"
"}"
"$x = 0;"
"if (!call_user_func(array('Foo', 'add'), $x, 0)) {"
" echo 'foo';"
"}");
MVCR("<?php "
"function f1($a, $b) {"
" $c = func_num_args();"
" $args = func_get_args();"
" $args[0] = 5;"
" $args[1] = 6;"
" $args[2] = 7;"
" var_dump($c);"
" var_dump($args);"
"}"
"function f2($a, &$b) {"
" $c = func_num_args();"
" $args = func_get_args();"
" $args[0] = 5;"
" $args[1] = 6;"
" $args[2] = 7;"
" var_dump($c);"
" var_dump($args);"
"}"
"function f3(&$a, $b) {"
" $c = func_num_args();"
" $args = func_get_args();"
" $args[0] = 5;"
" $args[1] = 6;"
" $args[2] = 7;"
" var_dump($c);"
" var_dump($args);"
"}"
"function f4(&$a, &$b) {"
" $c = func_num_args();"
" $args = func_get_args();"
" var_dump($args);"
" $args[0] = 5;"
" $args[1] = 6;"
" $args[2] = 7;"
" var_dump($c);"
" var_dump($args);"
"}"
"function f5($a, $b) {"
" $arg0 = func_get_arg(0);"
" $arg1 = func_get_arg(1);"
" $arg2 = func_get_arg(2);"
" $arg0 = 5;"
" $arg1 = 6;"
" $arg2 = 7;"
" var_dump($arg0, $arg1, $arg2);"
"}"
"function f6($a, &$b) {"
" $arg0 = func_get_arg(0);"
" $arg1 = func_get_arg(1);"
" $arg2 = func_get_arg(2);"
" $arg0 = 5;"
" $arg1 = 6;"
" $arg2 = 7;"
" var_dump($arg0, $arg1, $arg2);"
"}"
"function f7(&$a, $b) {"
" $arg0 = func_get_arg(0);"
" $arg1 = func_get_arg(1);"
" $arg2 = func_get_arg(2);"
" $arg0 = 5;"
" $arg1 = 6;"
" $arg2 = 7;"
" var_dump($arg0, $arg1, $arg2);"
"}"
"function f8(&$a, &$b) {"
" $arg0 = func_get_arg(0);"
" $arg1 = func_get_arg(1);"
" $arg2 = func_get_arg(2);"
" $arg0 = 5;"
" $arg1 = 6;"
" $arg2 = 7;"
" var_dump($arg0, $arg1, $arg2);"
"}"
"function bar() {"
" $a = 1;"
" f1($a, $a, $a);"
" var_dump($a);"
" $a = 1;"
" f2($a, $a, $a);"
" var_dump($a);"
" $a = 1;"
" f3($a, $a, $a);"
" var_dump($a);"
" $a = 1;"
" f4($a, $a, $a);"
" var_dump($a);"
" $a = 1;"
" f5($a, $a, $a);"
" var_dump($a);"
" $a = 1;"
" f6($a, $a, $a);"
" var_dump($a);"
" $a = 1;"
" f7($a, $a, $a);"
" var_dump($a);"
" $a = 1;"
" f8($a, $a, $a);"
" var_dump($a);"
"}"
"bar();");
MVCR("<?php "
"class Y { function __destruct() { } };"
"class X extends Y {"
" function __get($a) {"
" var_dump(func_get_args());"
" var_dump(func_get_arg(0));"
" var_dump(func_num_args());"
" return 42;"
" }"
" function __destruct() {"
" var_dump(func_get_args());"
" var_dump(func_get_arg(0));"
" var_dump(func_num_args());"
" return 2442;"
" }"
"}"
"$x = new X;"
"var_dump($x->buz);"
"unset($x);");
if (!hhvm) {
MVCR("<?php "
"function foo($a, $b, $c = 5) {"
" if ($a) $b++;"
" var_dump(func_get_args());"
"}"
"foo(1,2,3,4,5);"
"function bar($a, &$b, $c = 5) {"
" if ($a) $b++;"
" var_dump(func_get_args());"
"}"
"$b = 2;"
"bar(1,$b,3,4,5);"
"function baz($a, &$b, $c = 5) {"
" if ($a) unset($b);"
" var_dump(func_get_args());"
"}"
"$b = 2;"
"baz(1,$b,3,4,5);");
}
MVCR("<?php\n"
"function f() {\n"
" var_dump(func_get_args());\n"
"}\n"
"function g($x) {\n"
" if ($x) $f = 'f';\n"
" else $f = '__nocall__';\n"
" call_user_func_array($f, "
" array('x' => 10, 'y' => 20, 'z' => 30, 'j' => 40));\n"
" call_user_func_array($f, "
" array(3 => 10, 80 => 20, 10 => 30, 30 => 40));\n"
"}\n"
"g(10);\n");
MVCR("<?php\n"
"function f() {\n"
" var_dump(func_get_arg(-1));\n"
" var_dump(func_get_arg(0));\n"
" var_dump(func_get_arg(1));\n"
" if (func_get_arg(2)) {\n"
" $x = 0;\n"
" } else {\n"
" $x = 1;\n"
" }\n"
" var_dump(func_get_arg($x++));\n"
"}\n"
"function g($x, &$y) {\n"
" var_dump(func_get_arg(-1));\n"
" var_dump(func_get_arg(0));\n"
" var_dump(func_get_arg(1));\n"
" var_dump(func_get_arg(2));\n"
" var_dump(func_get_arg(3));\n"
"}\n"
"function h($x, &$y, array $z) {\n"
" var_dump(func_get_arg(-1));\n"
" var_dump(func_get_arg(0));\n"
" var_dump(func_get_arg(1));\n"
" var_dump(func_get_arg(2));\n"
" var_dump(func_get_arg(3));\n"
" var_dump(func_get_arg(4));\n"
"}\n"
"function i(&$x) {\n"
" $x = 30;\n"
" var_dump(func_get_args());\n"
" var_dump(func_get_arg(0));\n"
" $y =& func_get_arg(0);\n"
" $y = 40;\n"
" var_dump(func_get_arg(0));\n"
"}\n"
"f(10);\n"
"$x = 1;\n"
"g(0, $x, 2);\n"
"h(0, $x, array(1, 2), 3);\n"
"$x = 10;\n"
"i($x);\n"
"i();\n");
return true;
}
bool TestCodeRun::TestArgumentHandling() {
MVCR("<?php\n"
"function test($str) {\n"
" return strlen($str);\n"
"}\n"
"var_dump(strlen());\n"
"var_dump(test());\n"
"\n"
"var_dump(strlen('test'));\n"
"var_dump(test('test'));\n"
"\n"
"var_dump(strlen('test', 123));\n"
"var_dump(test('test', 123));\n"
);
MVCR("<?php "
"function f($x) { $b = $x; $b++; }"
"$a = 1;"
"f(&$a);"
"var_dump($a);");
return true;
}
bool TestCodeRun::TestListAssignment() {
MVCR("<?php $a = 'old'; var_dump(list($a) = false); var_dump($a);");
MVCR("<?php $a = 'old'; var_dump(list($a) = 'test'); var_dump($a);");
MVCR("<?php $a = 'old'; var_dump(list($a) = 123); var_dump($a);");
MVCR("<?php list() = array(1,2,3);");
MVCR("<?php list(,) = array(1,2,3);");
MVCR("<?php var_dump(list($a,) = array(1,2,3)); var_dump($a);");
MVCR("<?php var_dump(list(,$b) = array(1,2,3)); var_dump($b);");
MVCR("<?php var_dump(list($b) = array(1,2,3)); var_dump($b);");
MVCR("<?php var_dump(list($a,$b) = array(1,2,3)); "
"var_dump($a); var_dump($b);");
MVCR("<?php var_dump(list($a,list($c),$b) = array(1,array(2),3));"
"var_dump($a); var_dump($b); var_dump($c);");
MVCR("<?php $c = 'old'; var_dump(list($a,list($c),$b) = array(1,'test',3));"
"var_dump($a); var_dump($b); var_dump($c);");
MVCR("<?php var_dump(list($a,list(),$b) = array(1,array(2),3));"
"var_dump($a); var_dump($b);");
MVCR("<?php $info = array('coffee', 'brown', 'caffeine');"
"list($a[0], $a[1], $a[2]) = $info;"
"var_dump($a);");
MVCR("<?php "
"class obj implements arrayaccess {"
" private $container = array();"
" public function __construct() {"
" $this->container = array("
" 'one' => 1,"
" 'two' => 2,"
" 'three' => 3,"
" );"
" }"
" public function offsetSet($offset, $value) {"
" $this->container[$offset] = $value;"
" }"
" public function offsetExists($offset) {"
" return isset($this->container[$offset]);"
" }"
" public function offsetUnset($offset) {"
" unset($this->container[$offset]);"
" }"
" public function offsetGet($offset) {"
" return isset($this->container[$offset]) ? $this->container[$offset] : null;"
" }"
"}"
"class SetTest {"
" private $_vals = array("
" 'one' => 1,"
" 'two' => 2,"
" 'three' => 3,"
" );"
" public function __set($name, $value) {"
" $this->_vals[$name] = $value;"
" }"
"}"
"$o = new obj;"
"$q = list($o['one'], $o['two'], list($o['three'])) ="
" array('eins', 'zwei', array('drei'));"
"var_dump($o);"
"var_dump($q);"
"$x = new SetTest;"
"$qq = list($x->one, $x->two, list($x->three)) = 1;"
"var_dump($x);"
"$qq = list($x->one, $x->two, list($x->three)) = $q;"
"var_dump($x);"
"var_dump($qq);");
MVCR("<?php "
"function test($a) {"
" list($a[0], $a[1], $a) = $a;"
" var_dump($a);"
"}"
"test(array('abc', 'cde', 'fgh'));");
MVCR("<?php "
"function test() {"
" $a = array('abc', 'cde', 'fgh');"
" list($a[0], $a[1], $a) = $a;"
" var_dump($a);"
"}"
"test();");
MVCR("<?php "
"function test($a, $b, $i) {"
" list($a[$i++], $a[$i++], $a[$i++]) = $b;"
" var_dump($a);"
" }"
"test(array(), array('x', 'y', 'z'), 0);");
MVCR("<?php "
"$i = 0; "
"list($a[$i++], list($a[$i++], $a[$i++]), $a[$i++]) = "
" array('x', array('y1', 'y2'), 'z'); "
"var_dump($a);");
MVCR("<?php "
"function foo($a) {"
" list($x, $y) = 'x'.$a;"
" return $x + $y;"
"}");
MVCR("<?php "
"class X implements ArrayAccess {"
" function offsetget($n) { return $n; }"
" function offsetset($n,$v) { }"
" function offsetexists($n) { return true; }"
" function offsetunset($n) {}"
"}"
"list($a,$b) = new X;"
"var_dump($a, $b);"
"$x = 'foo';"
"$y = 'bar';"
"list($a, $b) = $x.$y;"
"var_dump($a,$b);"
"$z = $x.$y;"
"list($a, $b) = $z;"
"var_dump($a, $b);");
MVCR("<?php "
"class X {"
" static public $val = array(1,2,3);"
" function foo() {"
" list($a, $b) = self::$val;"
" var_dump($a, $b);"
" }"
"}"
"$x = new X;"
"$x->foo();"
"X::$val = null;");
return true;
}
bool TestCodeRun::TestExceptions() {
MVCR("<?php\n"
"class MyException extends Exception {\n"
" public function __construct() {\n"
" }\n"
"}\n"
"function thrower() {\n"
" throw new MyException();\n"
"}\n"
"try {\n"
" thrower();\n"
"} catch (Exception $exn) {\n"
" $a = $exn->getTrace(); foreach ($a as &$b) $b['file'] = 'string';\n"
" var_dump($a);\n"
" var_dump($exn->getLine());\n"
"}\n"
);
MVCR("<?php\n"
"\n"
"class Exception1 extends Exception {\n"
" public function __Construct() {\n"
" parent::__construct();\n"
" }\n"
"}\n"
"\n"
"class Exception2 extends Exception1 {\n"
" public function exception2() {\n"
" parent::__construct();\n"
" }\n"
"}\n"
"\n"
"function foo() {\n"
" throw new Exception2();\n"
"}\n"
"\n"
"function bar() {\n"
" try {\n"
" foo();\n"
" } catch (Exception $exn) {\n"
" $a = $exn->getTrace(); foreach ($a as &$b) $b['file'] = 'string';\n"
" var_dump($a);\n"
" var_dump($exn->getLine());\n"
" }\n"
"}\n"
"\n"
"bar();\n");
MVCR("<?php try { throw new Exception('test');} "
"catch (Exception $e) {}");
MVCR("<?php try { try { throw new Exception('test');} "
"catch (InvalidArgumentException $e) {} } "
"catch (Exception $e) { print 'ok';}");
MVCR("<?php class E extends Exception {} "
"try { throw new E(); } catch (E $e) { print 'ok';}");
MVCR("<?php class E extends Exception {} class F extends E {}"
"try { throw new F(); } catch (E $e) { print 'ok';}");
MVCR("<?php class E extends Exception { function __toString(){ return 'E';}} "
"class F extends E { function __toString() { return 'F';}}"
"try { throw new F(); } catch (E $e) { print $e;}");
MVCR("<?php "
"class a extends Exception {"
" function __destruct() {"
" var_dump('__destruct');"
" }"
"};"
"function foo() {"
" $ex = null;"
" try {"
" throw new A;"
" } catch (Exception $ex) {"
" var_dump(1);"
" }"
" var_dump(2);"
"}"
"foo();");
MVCR("<?php "
"function foo($a, $b) { return $a + $b; }"
"function myErrorHandler($errno, $errstr, $errfile, $errline) {"
" var_dump($errstr, $errline);"
"}"
"$old_error_handler = set_error_handler('myErrorHandler');"
""
"function bar($a, $b) {"
" if ($a) {"
" $value = $a * foo(1, 2);"
" }"
" return 1 / $b;"
"}"
"set_error_handler('myErrorHandler');"
"$r = bar(1, 0);");
MVCR("<?php "
"class a extends Exception {};"
"class b extends a {"
" function dump() {"
" echo 'c:', $this->code, '\nm:', $this->message, '\n';"
" echo 'x:', $this->x, '\ny:', $this->y, '\n';"
" }"
"}"
"if (0) { class a extends Exception {} }"
"try {"
" throw(new b(1, 2));"
"} catch (b $e) {"
" $e->dump();"
"}");
MVCR("<?php "
"class X {"
" static function eh($errno, $errstr) {"
" echo \"eh: $errno\\n\";"
" die;"
" }};"
"set_error_handler(array('X', 'eh'));"
"$g = array();"
"echo $g['foobar'];");
MVCR("<?php\n"
"function f() { throw new Exception('foo'); }\n"
"class X {\n"
" function foo() {\n"
" try {\n"
" f();\n"
" } catch (Exception $this) {\n"
" return $this;\n"
" }\n"
" }\n"
"}\n"
"$x = new X;\n"
"$ex = $x->foo();\n"
"var_dump($ex->getMessage());\n");
MVCR("<?php"
"ini_set('memory_limit','4M');"
"function test() {"
" for ($i = 0; $i < 4000; $i++) {"
" try {"
" call_user_func('bar');"
" } catch (Exception $e) {"
" }"
" }"
" var_dump('ok');"
"}"
"function bar() {"
" throw new Exception;"
"}"
"test();");
MVCR("<?php "
"function foo($a) {"
" $flag = true;"
" try {"
" f($a);"
" $flag = false;"
" } catch (Exception $e) {"
" }"
" var_dump($flag);"
"}"
"function f($a) { if ($a) throw new Exception('What?'); }"
"foo(1);");
if (Option::EnableEval >= Option::FullEval) {
MVCRNW("<?php "
"error_reporting(-1);"
"set_error_handler('handle');"
"function handle() { throw new exception; }"
"function foo($a,$b=null) { return $a; }"
"function test1() {"
" if (foo(0)) $a=1;"
" $x = new StdClass;"
" return $a;"
"}"
"function test2() {"
" if (foo(0)) $a=1;"
" return $a | new StdClass;"
"}"
"function test3() {"
" if (foo(0)) $a=1;"
" $x = new StdClass;"
" return $a::foo;"
"}"
"function test($f) {"
" try {"
" $f();"
" } catch (Exception $e) {"
" var_dump($f.':Caught');"
" }"
"}"
"test('test1');"
"test('test2');"
"test('test3');"
"var_dump('not reached');");
}
MVCRO("<?php\n"
"class C {\n"
" function g() {\n"
" $ex = new Exception();\n"
" $bt = $ex->getTrace();\n"
" foreach ($bt as $k => $_) {\n"
" $frame = $bt[$k];\n"
" unset($frame['file']);\n"
" unset($frame['line']);\n"
" unset($frame['args']);\n"
" ksort($frame);\n"
" $bt[$k] = $frame;\n"
" }\n"
" var_dump($bt);\n"
" }\n"
" function f() {\n"
" $this->g();\n"
" }\n"
"}\n"
"$obj = new C;\n"
"$obj->f();\n"
"echo \"==========\\n\";\n"
"Exception::setTraceOptions(true);\n"
"$obj->f();\n"
,
"array(2) {\n"
" [0]=>\n"
" array(3) {\n"
" [\"class\"]=>\n"
" string(1) \"C\"\n"
" [\"function\"]=>\n"
" string(1) \"g\"\n"
" [\"type\"]=>\n"
" string(2) \"->\"\n"
" }\n"
" [1]=>\n"
" array(3) {\n"
" [\"class\"]=>\n"
" string(1) \"C\"\n"
" [\"function\"]=>\n"
" string(1) \"f\"\n"
" [\"type\"]=>\n"
" string(2) \"->\"\n"
" }\n"
"}\n"
"==========\n"
"array(2) {\n"
" [0]=>\n"
" array(4) {\n"
" [\"class\"]=>\n"
" string(1) \"C\"\n"
" [\"function\"]=>\n"
" string(1) \"g\"\n"
" [\"object\"]=>\n"
" object(C)#1 (0) {\n"
" }\n"
" [\"type\"]=>\n"
" string(2) \"->\"\n"
" }\n"
" [1]=>\n"
" array(4) {\n"
" [\"class\"]=>\n"
" string(1) \"C\"\n"
" [\"function\"]=>\n"
" string(1) \"f\"\n"
" [\"object\"]=>\n"
" object(C)#1 (0) {\n"
" }\n"
" [\"type\"]=>\n"
" string(2) \"->\"\n"
" }\n"
"}\n"
);
if (!hhvm) {
FinallyStatement w(this);
MVCRO("<?php\n"
"$var = 1;\n"
"try {\n"
" $var += 2;\n"
"} catch (Exception $e) {\n"
" $var += 4;\n"
"} finally {\n"
" $var += 8;\n"
"}\n"
"print $var;",
"11");
MVCRO("<?php\n"
"$var = 1;\n"
"try {\n"
" try {\n"
" $var += 2;\n"
" throw new Exception();\n"
" $var += 4;\n"
" } finally {\n"
" $var += 8;\n"
" }\n"
"} catch (Exception $e) {\n"
" $var += 16;\n"
"}\n"
"print $var;",
"27");
MVCRO("<?php\n"
"function throwemup() {\n"
" try {\n"
" throw new Exception('Exception 1', 9);\n"
" } catch (Exception $e) {\n"
" throw new Exception('Exception 2', 8, $e);\n"
" } finally {\n"
" $tmp = new Exception('Exception 3', 7);\n"
" throw new Exception('Exception 4', 6, $tmp);\n"
" }\n"
"}\n"
"try {\n"
" throwemup();\n"
"} catch (Exception $e) {\n"
" for ($i = 4; $i--;) {\n"
" print $e->getMessage();\n"
" $e = $e->getPrevious();\n"
" }\n"
"}\n",
"Exception 4"
"Exception 3"
"Exception 2"
"Exception 1");
MVCRO("<?php\n"
"try {\n"
"} finally {\n"
" $a = 1;\n"
"}\n"
"print $a;\n",
"1");
MVCRO("<?php\n"
"function func() {\n"
" try {} finally {}\n"
" try {\n"
" $a = 1;\n"
" throw new Exception();\n"
" $a += 2;\n"
" } catch (Exception $e) {\n"
" } finally {\n"
" $a += 4;\n"
" }\n"
" print $a;\n"
"}\n"
"func();",
"5");
}
MVCR("<?php "
"function runstuff() {"
" throw new Exception;"
"}"
"function main() {"
" try {"
" $start_time = 1;"
" runstuff();"
" return;"
" } catch (Exception $se) {"
" $elapsed = 2 - $start_time;"
" var_dump($elapsed);"
" }"
"}"
"main();");
return true;
}
bool TestCodeRun::TestPredefined() {
MVCR("<?php \n\n\nvar_dump(/*__FILE__, */__LINE__);");
MVCR("<?php function Test() { var_dump(__FUNCTION__);} "
"var_dump(__FUNCTION__); test();");
MVCR("<?php class A { "
"function TestR() { var_dump(__CLASS__, __METHOD__);} "
"static function Testm() { var_dump(__CLASS__, __METHOD__);}} "
"function Testf() { var_dump(__CLASS__, __METHOD__);} "
"testf(); A::testm(); $obj = new A(); $obj->testr();");
MVCR("<?php class A { const Foo = __METHOD__;} var_dump(A::Foo);");
return true;
}
bool TestCodeRun::TestLabels() {
MVCR("<?php\n"
"$modalit\xe9 = 'extended ASCII'; var_dump($modalit\xe9);\n"
"${\"a-b\"} = 'dash'; var_dump(${\"a-b\"});\n"
"${'a\"b'} = 'quote'; var_dump(${'a\"b'});\n"
"${'a$b'} = 'dollar'; var_dump(${'a$b'});\n");
MVCR("<?php\n"
"define('modalit\xe9', 123); var_dump(modalit\xe9);");
MVCR("<?php\n"
"function modalit\xe9($a) { var_dump($a);} modalit\xe9(123);");
MVCR("<?php\n"
"class modalit\xe9 { static function odalit\xe9() { var_dump(123);} } "
"modalit\xe9::odalit\xe9();");
return true;
}
bool TestCodeRun::TestPerfectVirtual() {
MVCR("<?php "
"class A { function foo() { var_dump(__CLASS__);}} "
"class B extends A { function foo() { var_dump(__CLASS__);}} "
"function bar() { "
" $obj = new A; $obj->foo();"
" $obj = new B; $obj->foo();"
"} bar();"
);
MVCR("<?php "
"class A { function foo($a = 123) { var_dump(__CLASS__);}} "
"class B extends A { function foo($b = 123) { var_dump(__CLASS__);}} "
"function bar() { "
" $obj = new A; $obj->foo();"
" $obj = new B; $obj->foo();"
"} bar();"
);
MVCR("<?php "
"class A { function foo() { "
"$args = func_get_args(); var_dump(__CLASS__, $args);}} "
"class B extends A { function foo() { "
"$args = func_get_args(); var_dump(__CLASS__, $args);}} "
"function bar() { "
" $obj = new A; $obj->foo(123);"
" $obj = new B; $obj->foo(123, 456);"
"} bar();"
);
MVCR("<?php "
"class A { const X=1; function foo($a = self::X) { var_dump($a);}} "
"class B extends A { const X=2; function foo($b = self::X) {"
" var_dump($b);}} "
"function bar() { "
" $obj = new A; $obj->foo();"
" $obj = new B; $obj->foo();"
"} bar();"
);
MVCR("<?php "
"class X {"
" function foo($a) { return $a; }"
"}"
"class Y extends X {"
" function &foo($a) { return $a; }"
"}"
"function test(X $x) {"
" $y = $x->foo(5);"
" return ++$y;"
"}"
"test(new Y);");
return true;
}
///////////////////////////////////////////////////////////////////////////////
// type system
bool TestCodeRun::TestBoolean() {
MVCR("<?php var_dump(true);");
MVCR("<?php var_dump(false);");
MVCR("<?php $a = 1; $b = ($a == 1); var_dump($b);");
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool TestCodeRun::TestInteger() {
MVCR("<?php var_dump(1);");
MVCR("<?php var_dump(0);");
MVCR("<?php var_dump(-1);");
MVCR("<?php var_dump(8589934592);");
MVCR("<?php var_dump(-8589934592);");
MVCR("<?php $a = 1; var_dump($a);");
MVCR("<?php $a = 0; var_dump($a);");
MVCR("<?php $a = -1; var_dump($a);");
MVCR("<?php $a = 8589934592; var_dump($a);");
MVCR("<?php $a = -8589934592; var_dump($a);");
MVCR("<?php $a = 10; var_dump(~$a);");
MVCR("<?php $a = 10; $b = 9; var_dump($a & $b);");
MVCR("<?php $a = 10; $b = 9; var_dump($a | $b);");
MVCR("<?php $a = 10; $b = 9; var_dump($a ^ $b);");
MVCR("<?php $a = 10; var_dump($a << 2);");
MVCR("<?php $a = 10; var_dump($a >> 2);");
MVCR("<?php $a = 10; $b = 9; $a &= $b; var_dump($a);");
MVCR("<?php $a = 10; $b = 9; $a |= $b; var_dump($a);");
MVCR("<?php $a = 10; $b = 9; $a ^= $b; var_dump($a);");
MVCR("<?php $a = 10; $b = 9; $a <<= 2; var_dump($a);");
MVCR("<?php $a = 10; $b = 9; $a >>= 2; var_dump($a);");
MVCR("<?php "
"var_dump((integer)'10');"
"var_dump((integer)'0x10');"
"var_dump((integer)'010');"
"var_dump(10 + 0x10);"
"var_dump(10 + 010);");
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool TestCodeRun::TestDouble() {
MVCR("<?php var_dump(1.0);");
MVCR("<?php var_dump(0.0);");
MVCR("<?php var_dump(-1.0);");
MVCR("<?php var_dump(1/3);");
MVCR("<?php $a = 1/3; var_dump($a);");
MVCR("<?php $a = 1/3; $b = $a; var_dump($b);");
MVCR("<?php "
"$a = 1.234;"
"echo $a;"
"$b = 1.2e3;"
"echo $b;"
"$c = 7E-10;"
"echo $c;"
"echo floor((0.1+0.7)*10);"
"echo round((69.1-floor(69.1)));"
"echo round(69.1-floor(69.1));"
"echo (63.1-floor(63.1));"
"echo (64.0-floor(64.0));"
"echo round(64.1-floor(64.1));"
"echo round(3.1415927,2);"
"echo round(1092,-2);");
MVCR("<?php "
"$foo = 1 + \"10.5\";"
"print(\"$foo \");"
"$foo = 1 + \"-1.3e3\";"
"print(\"$foo \");"
"$foo = 1 + \"bob-1.3e3\";"
"print(\"$foo \");"
"$foo = 1 + \"bob3\";"
"print(\"$foo \");"
"$foo = 1 + \"10 Small Pigs\";"
"print(\"$foo \");"
"$foo = 4 + \"10.2 Little Piggies\";"
"print(\"$foo \");"
"$foo = \"10.0 pigs \" + 1;"
"print(\"$foo \");"
"$foo = \"10.0 pigs \" + 1.0;"
"print(\"$foo \");");
MVCR("<?php "
"var_dump(1E1);"
"var_dump(1E2);"
"var_dump(1E3);"
"var_dump(1E4);"
"var_dump(1E5);"
"var_dump(1E6);"
"var_dump(1E7);"
"var_dump(1E8);"
"var_dump(1E9);"
"var_dump(1E10);"
"var_dump(1E11);"
"var_dump(1E12);"
"var_dump(1E13);"
"var_dump(1E14);"
"var_dump(1E15);"
"var_dump(1E16);"
"var_dump(1E17);"
"var_dump(1E18);"
"var_dump(1E19);"
"var_dump(1E20);");
MVCR("<?php "
"var_dump((double)'10');"
"var_dump((double)'0x10');"
"var_dump((double)'010');"
"var_dump(10.0 + 0x10);"
"var_dump(10.0 + 010.0);");
MVCR("<?php "
"$t=floor(1316700000/300)*300;"
"var_dump($t);");
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool TestCodeRun::TestString() {
MVCR("<?php print '\\'\\\\\"';");
MVCR("<?php print 'test\nok';");
MVCR("<?php print \"test\nok\";");
MVCR("<?php print \"test\\n\\r\\t\\v\\f\\\\\\$\\\"\";");
MVCR("<?php print \"\\1\\12\\123\\1234\\xA\\xAB\";");
MVCR("<?php print 'test\\n';");
MVCR("<?php $a = 'test'; $b = $a; print $b;");
MVCR("<?php $a = 'test'; $b = $a; $a = 'changed'; print $b;");
MVCR("<?php $a = 'test'; $b = $a; $a = 'changed'; print $a;");
MVCR("<?php $a = 'test'; $b = $a; $b = 'changed'; print $a;");
MVCR("<?php $a = 'a'; $b = 'b'; $c = 'a' . 'b'; print $c;");
MVCR("<?php $a = 'a'; $b = 'b'; $c = $a . 'b'; print $c;");
MVCR("<?php $a = 'a'; $b = 'b'; $c = 'a' . $b ; print $c;");
MVCR("<?php $a = 'a'; $b = 'b'; $b .= $a; print $b;");
MVCR("<?php $a = 'test'; print $a{0};");
MVCR("<?php $a = 'test'; print '['.$a{-1}.']';");
MVCR("<?php $a = 'test'; print '['.$a{100}.']';");
MVCR("<?php $a = 'test'; print $a[0];");
MVCR("<?php $a = 'test'; print $a['junk'];");
MVCR("<?php $a = 'test'; print '['.$a[-1].']';");
MVCR("<?php $a = 'test'; print '['.$a[100].']';");
MVCR("<?php $a = 'test'; $a[0] = 'ABC'; var_dump($a);")
MVCR("<?php $a = 'test'; $a[10] = 'ABC'; var_dump($a);")
MVCR("<?php $a = 'test'; $b = $a; $a[0] = 'ABC'; var_dump($a); var_dump($b);")
MVCR("<?php $a = 'test'; $b = $a; $a[10] = 'ABC'; var_dump($a);var_dump($b);")
MVCR("<?php $a = 'test'; $b = $a; $b[0] = 'ABC'; var_dump($a); var_dump($b);")
MVCR("<?php $a = 'test'; $b = $a; $b[10] = 'ABC'; var_dump($a);var_dump($b);")
MVCR("<?php $a = 'test'; var_dump(~$a);");
MVCR("<?php $a = 'test'; $b = 'zzz'; var_dump($a & $b);");
MVCR("<?php $a = 'test'; $b = 'zzz'; var_dump($a | $b);");
MVCR("<?php $a = 'test'; $b = 'zzz'; var_dump($a ^ $b);");
MVCR("<?php $a = 'test'; $b = 'zzz'; $a &= $b; var_dump($a);");
MVCR("<?php $a = 'test'; $b = 'zzz'; $a |= $b; var_dump($a);");
MVCR("<?php $a = 'test'; $b = 'zzz'; $a ^= $b; var_dump($a);");
MVCR("<?php $a = 'zzz'; $b = 'test'; var_dump($a & $b);");
MVCR("<?php $a = 'zzz'; $b = 'test'; var_dump($a | $b);");
MVCR("<?php $a = 'zzz'; $b = 'test'; var_dump($a ^ $b);");
MVCR("<?php $a = 'zzz'; $b = 'test'; $a &= $b; var_dump($a);");
MVCR("<?php $a = 'zzz'; $b = 'test'; $a |= $b; var_dump($a);");
MVCR("<?php $a = 'zzz'; $b = 'test'; $a ^= $b; var_dump($a);");
MVCR("<?php $a = 'zzz'; $a++; var_dump($a);");
MVCR("<?php $a = 'zzz'; ++$a; var_dump($a);");
MVCR("<?php $a = 'zzz'; $a--; var_dump($a);");
MVCR("<?php $a = 'zzz'; --$a; var_dump($a);");
MVCR("<?php $a = 'abc'; var_dump(isset($a[1], $a[2], $a[3]));");
// serialization of binary string
MVCR("<?php var_dump(bin2hex(serialize(\"a\\x00b\")));");
MVCR("<?php var_dump(json_encode(\"\\0001\"));");
MVCR("<?php "
"$a = array('x'=>'foo');"
"$b = 'qqq';"
"class c {}"
"$c = new c;"
"$c->p = 'zzz';"
"var_dump(\"AAA ${a['x']} $a[x] $b $c->p\");");
MVCR("<?php "
"function test($a, $b) {"
" $buf = 'hello';"
" foreach ($a as $v) {"
" $buf .= $v . ';';"
" foreach ($b as $w) {"
" $buf .= $w;"
" }"
" }"
" var_dump($buf);"
"}"
"test(array('a', 'b', 'c'), array('u', 'v'));"
"function test2($a, $b) {"
" $buf = 'hello';"
" foreach ($a as $v) {"
" $buf .= $v . ';';"
" foreach ($b as $w) {"
" $buf .= $w;"
" }"
" echo $buf;"
" }"
" var_dump($buf);"
"}"
"test2(array('a', 'b', 'c'), array('u', 'v'));"
"function test3($a, $b) {"
" $buf = 'hello';"
" foreach ($a as $v) {"
" $buf .= $v . ';';"
" foreach ($b as $w) {"
" echo ($buf .= $w);"
" }"
" }"
" var_dump($buf);"
"}"
"test3(array('a', 'b', 'c'), array('u', 'v'));");
MVCR("<?php "
"function f() { return 'x'; }"
"function g() {}"
"function test1($a) {"
" $buf = '';"
" foreach ($a as $s) {"
" $buf .= f() . g() . 'h' . f() . 'h' . g();"
" }"
" foreach ($a as $s) {"
" $buf .= ($s . 'h' . $s);"
" }"
" return $buf;"
"}"
"var_dump(test1(array(1)));"
"function test2() {"
" return f() . g() . f() . g();"
"}"
"var_dump(test2());"
"function test3() {"
" return f() . g() . f() . g() . f() . g() . f() . g() . f();"
"}"
"var_dump(test3());"
"function test4() {"
" $s = f();"
" $s .="
" ('foo'."
" 'bar'."
" f()."
" 'foo'."
" 'baz'."
" f()."
" 'fuz'."
" 'boo'."
" f()."
" 'fiz'."
" 'faz');"
""
" $s .= f();"
" return $s;"
"}"
"var_dump(test4());"
"function test5() {"
" return g().g().g().g();"
"}"
"var_dump(test5());"
"function test6() {"
" return g().f().g();"
"}"
"var_dump(test6());");
MVCR("<?php "
"class X {"
" static function g() {}"
"};"
"echo 'abc' . X::g() . 'efg';");
MVCR("<?php "
"$s = 'x';"
"var_dump(strrpos($s.'0', $s));"
"for ($i = -7; $i < 7; $i++) {"
" echo $i,':';var_dump(strrpos('xabcay', 'a',$i));"
"}");
MVCR("<?php\n"
"$a = 'zz';\n"
"$a++;\n"
"$b = 'zz';\n" // $b should remain 'zz'
"var_dump($a, $b);\n");
MVCR("<?php\n"
"function test($s) {\n"
" $a = array('abc' => 1, 'abcd' => 2);\n"
" $s .= 'c'; var_dump($a[$s]);\n"
" $s .= 'd'; var_dump($a[$s]);\n" // should find 'abcd' in $a
"}\n"
"test('ab');\n");
MVCR("<?php\n"
"function foo() {"
" $a = '';"
" $a++;"
" var_dump($a);"
" $a = '';"
" ++$a;"
" var_dump($a);"
" $a = '';"
" $a--;"
" var_dump($a);"
" $a = '';"
" --$a;"
" var_dump($a);"
" $a = '@';"
" $a++;"
" var_dump($a);"
" $a = '@';"
" ++$a;"
" var_dump($a);"
" $a = '@';"
" $a--;"
" var_dump($a);"
" $a = '@';"
" --$a;"
" var_dump($a);"
"}"
"foo();");
MVCRO("<?php "
"var_dump(strncmp('foo', 'foo', -100));"
"var_dump(strncasecmp('foo', 'foo', -100));"
"var_dump(substr_compare('foo', 'foo', 0, -100, true));"
"var_dump(substr_compare('foo', 'bar', -3));",
"int(0)\n" // zend returns false
"int(0)\n" // zend returns false
"bool(false)\n"
"int(1)\n");
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool TestCodeRun::TestArray() {
HipHopSyntax w(this);
MVCR("<?php var_dump(array('b' => '2', 'a' => '1'));");
MVCR("<?php var_dump(array(1 => 'a', 0 => 'b'));");
MVCR("<?php $a = array(); var_dump($a);");
MVCR("<?php $a = array(1); var_dump($a);");
MVCR("<?php $a = array(2, 1); var_dump($a);");
MVCR("<?php $a = array('1'); var_dump($a);");
MVCR("<?php $a = array('2', '1'); var_dump($a);");
MVCR("<?php $a = array('a' => 1); var_dump($a);");
MVCR("<?php $a = array('b' => 2, 'a' => 1); var_dump($a);");
MVCR("<?php $a = array('a' => '1'); var_dump($a);");
MVCR("<?php $a = array('b' => '2', 'a' => '1'); var_dump($a);");
MVCR("<?php $a = array('a' => 1, 'a' => 2); var_dump($a);");
MVCR("<?php $a = array('a' => 1, 'b' => 2, 'a' => 3); var_dump($a);");
MVCR("<?php $a = array(1); $b = $a; var_dump($b);");
MVCR("<?php $a = array(1); $b = $a; $a = array(2); var_dump($b);");
MVCR("<?php $a = array(1); $b = $a; $a = array(2); var_dump($a);");
MVCR("<?php $a = array(1); $b = $a; $b = array(2); var_dump($a);");
MVCR("<?php $a = array(); foreach ($a as $item) print '['.$item.']';");
MVCR("<?php $a = array(1); foreach ($a as $item) print '['.$item.']';");
MVCR("<?php $a = array(2,1); foreach ($a as $item) print '['.$item.']';");
MVCR("<?php $a = array('b' => 2, 'a' => 1); "
"foreach ($a as $item) print '['.$item.']';");
MVCR("<?php $a = array('b' => 2, 'a' => 1); "
"foreach ($a as $name => $item) print '['.$name.'=>'.$item.']';");
MVCR("<?php $a = array(2,1); var_dump($a[0]);");
MVCR("<?php $a = array(2,1); var_dump($a[-1]);");
MVCR("<?php $a = array(2,1); var_dump($a[3]);");
MVCR("<?php $a = array('b' => 2, 'a' => 1); var_dump($a['b']);");
MVCR("<?php $a = array('b' => 2, 'a' => 1); var_dump($a['bogus']);");
MVCR("<?php $a = array(2, 'test' => 1); var_dump($a);");
MVCR("<?php $a = array(1.2 => 'test'); var_dump($a[1]);");
MVCR("<?php $a = array(1, 'test'); var_dump($a);");
MVCR("<?php $a = array(); $a[] = 3; $a[] = 'test'; var_dump($a);");
MVCR("<?php $a = array(); $a['test'] = 3; var_dump($a);");
MVCR("<?php $a = array(1); $a['test'] = 3; var_dump($a);");
MVCR("<?php $a = array(1, 2); $a[10] = 3; var_dump($a);");
MVCR("<?php $a = array(1, 2); $a['10'] = 3; var_dump($a);");
MVCR("<?php $a = array(1, 2); $b = $a; $a['10'] = 3; var_dump($b);");
MVCR("<?php $a = array(1, 2); $b = $a; $a['10'] = 3; var_dump($a);");
MVCR("<?php $a[] = 3; var_dump($a);");
MVCR("<?php $a = array(); $a[] = 3; var_dump($a);");
MVCR("<?php $a = array(1); $a[] = 3; var_dump($a);");
MVCR("<?php $a = array(1,2); $a[] = 3; var_dump($a);");
MVCR("<?php $a = ''; $a[] = 'test'; var_dump($a);");
MVCR("<?php $a = array(1, 2); "
"foreach ($a as $item) { "
" print 'A['.$item.']'; "
" if ($item == 1) $a[] = 'new item'; "
"} "
"foreach ($a as $item) { "
" print 'B['.$item.']'; "
"}"
"var_dump($a);");
MVCR("<?php $a = array(1); $b = array(2); $c = $a + $b; var_dump($c);");
MVCR("<?php $a = array(1,2); $b = array(2,3); $c = $a + $b; var_dump($c);");
MVCR("<?php $a = array(1,2); $b = array(2); $c = $a + $b; var_dump($c);");
MVCR("<?php $a = array(1); $b = array(2,3); $c = $a + $b; var_dump($c);");
MVCR("<?php "
"$array_variables = array("
" array(),"
" array(NULL),"
" array("")"
");"
"foreach ($array_variables as $array_var) {"
" $keys = array_keys($array_var);"
" foreach ($keys as $key_value) {"
" echo $key_value;"
" }"
"}");
MVCR("<?php $a = array('a' => 1, 'b' => 2);"
"foreach ($a as $b => $c) {"
" var_dump($b);"
" unset($a['b']);"
"}");
MVCR("<?php $a = array('a' => 1, 'b' => 2);"
"foreach ($a as $b => &$c) {"
" var_dump($b);"
" unset($a['b']);"
"}");
MVCRO("<?php "
"function gen() {"
" $a = array('a' => 1, 'b' => 2);"
" foreach ($a as $b => &$c) {"
" yield null;"
" var_dump($b);"
" unset($a['b']);"
" }"
"}"
"foreach (gen() as $_) {}"
,
"string(1) \"a\"\n"
);
MVCR("<?php "
"$foo = array(1,2,3,4);"
"foreach ($foo as $key => $val) {"
" if($val == 2) {"
" $foo[$key] = 0;"
" } else if($val == 3) {"
" unset($foo[$key]);"
" } else {"
" $foo[$key] = $val + 1;"
" }"
"}"
"var_dump($foo);");
MVCR("<?php "
"$foo = array(1,2,3,4);"
"foreach ($foo as $key => &$val) {"
" if($val == 2) {"
" $foo[$key] = 0;"
" } else if($val == 3) {"
" unset($foo[$key]);"
" } else {"
" $val++;"
" }"
"}"
"var_dump($foo);");
MVCRO("<?php "
"function gen() {"
" $foo = array(1,2,3,4);"
" foreach ($foo as $key => &$val) {"
" if($val == 2) {"
" $foo[$key] = 0;"
" } else if($val == 3) {"
" unset($foo[$key]);"
" } else {"
" $val++;"
" }"
" }"
" var_dump($foo);"
" yield null;"
"}"
"foreach (gen() as $_) {}"
,
"array(3) {\n"
" [0]=>\n"
" int(2)\n"
" [1]=>\n"
" int(0)\n"
" [3]=>\n"
" &int(5)\n"
"}\n"
);
MVCR("<?php "
"$a = array('a' => 'apple', 'b' => 'banana', 'c' => 'citrus');"
"foreach ($a as $k1 => &$v1) {"
" foreach ($a as $k2 => &$v2) {"
" if ($k2 == 'a') {"
" unset($a[$k2]);"
" }"
" var_dump($v1, $v2);"
" }"
"}");
MVCRO("<?php "
"function gen() {"
" $a = array('a' => 'apple', 'b' => 'banana', 'c' => 'citrus');"
" foreach ($a as $k1 => &$v1) {"
" foreach ($a as $k2 => &$v2) {"
" if ($k2 == 'a') {"
" unset($a[$k2]);"
" }"
" var_dump($v1, $v2);"
" }"
" }"
" yield null;"
"}"
"foreach (gen() as $_) {}"
,
"string(5) \"apple\"\n"
"string(5) \"apple\"\n"
"string(5) \"apple\"\n"
"string(6) \"banana\"\n"
"string(5) \"apple\"\n"
"string(6) \"citrus\"\n"
"string(6) \"banana\"\n"
"string(6) \"banana\"\n"
"string(6) \"banana\"\n"
"string(6) \"citrus\"\n"
"string(6) \"citrus\"\n"
"string(6) \"banana\"\n"
"string(6) \"citrus\"\n"
"string(6) \"citrus\"\n"
);
MVCR("<?php "
"$stack = array();"
"function push_stack()"
"{"
" global $stack;"
" static $index = 0;"
" $val = $index++;"
" array_push($stack, $val);"
"}"
"function pop_stack()"
"{"
" global $stack;"
" if ($stack) {"
" array_pop($stack);"
" }"
"}"
"push_stack();"
"pop_stack();"
"pop_stack();"
"pop_stack();"
"push_stack();"
"pop_stack();"
"push_stack();"
"$info = array(count($stack), $stack[count($stack)-1], $stack);"
"var_dump($info);");
MVCR("<?php "
"class A { function f($a) { var_dump($a === null); } }"
"$a = true; $a = new A();"
"$a->f(array());");
MVCR("<?php "
"function test($a) {"
" var_dump(current($a));"
" while (next($a)) echo '.';"
" $a[] = 2;"
" $a[] = 3;"
" var_dump(current($a));"
" var_dump(next($a));"
" var_dump(next($a));"
" var_dump(current($a));"
" $a[17] = 4;"
" var_dump(current($a));"
" $a[18] = 5;"
" var_dump(current($a));"
" while(next($a)) echo '.';"
" var_dump(current($a));"
" $a[1] = 5;"
" var_dump(current($a));"
"}"
"test(array(1));"
"test(array(1,2,3,4,5,6,7,8,9));");
MVCR("<?php "
"function foo() {"
" $a = array();"
" $a[] = '1.1';"
" $a[] = '2.2';"
" $a[] = '3.3';"
" var_dump(array_sum($a));"
" var_dump(array_product($a));"
"}"
"foo();");
MVCR("<?php "
"$array = array('1' => array(2 => 'test'));"
"unset($array['1'][2]);"
"var_dump($array['1']);");
MVCR("<?php "
"$x['1'] += 1;"
"var_dump($x);");
MVCR("<?php "
"function foo($x) { var_dump($x); }"
"function test() {"
" $data = null;"
" $data['bar']['baz'] = 1;"
" foo($data);"
"}"
"test();");
MVCR("<?php "
"class A {"
" public function __call($method, $args) {"
" foreach ($args as $a) { var_dump($a); }"
" var_dump(array_pop($args));"
" if (isset($args[1])) { var_dump($args[1]); }"
" reset($args);"
" if (key($args) === 0) {"
" $args = array(5);"
" }"
" if (current($args) === 0) {"
" $args = array(5);"
" }"
" if (next($args) === 0) {"
" $args = array(5);"
" }"
" var_dump($args['1']);"
" var_dump($args['hi']);"
" $args = $args + array(2 => 0, 3 => true, 4 => true); "
" var_dump($args);"
" }"
"}"
"$obj = new A;"
"$obj->foo(1, 2, 3);");
MVCRO("<?php "
"class A {"
" public function __call($method, $args) {"
" for ($o = new MutableArrayIterator($args);"
" $o->valid(); $o->next()) {"
" $v = &$o->currentRef();"
" var_dump($v);"
" var_dump($v);"
" }"
" var_dump(array_key_exists('foo', $args));"
" var_dump(array_unshift($args, 4));"
" var_dump(array_pop($args));"
" if (isset($args['foo'])) {}"
" var_dump(each($args));"
" var_dump(array_shift($args));"
" }"
"}"
"$obj = new A;"
"$obj->foo(1, 2, 3);",
"int(1)\n"
"int(1)\n"
"int(2)\n"
"int(2)\n"
"int(3)\n"
"int(3)\n"
"bool(false)\n"
"int(4)\n"
"int(3)\n"
"array(4) {\n"
" [1]=>\n"
" int(4)\n"
" [\"value\"]=>\n"
" int(4)\n"
" [0]=>\n"
" int(0)\n"
" [\"key\"]=>\n"
" int(0)\n"
"}\n"
"int(4)\n");
MVCR("<?php "
"function test($q, $a, $b, $c) {"
" $x = array($a, 'foo'=> $a);"
" if ($x) {"
" var_dump(isset($x[0][1]), isset($x['foo'][1]));"
" var_dump(isset($x[$b][1]), isset($x[$c][1]));"
" var_dump(end($x[0]));"
" }"
"}"
"test(5, array(0,1), 0, 'foo');");
MVCR("<?php "
"class X { function __destruct() { var_dump('two'); } }"
"function test($a) {"
" $x = array(new X);"
" $a['foo'] = $x;"
" var_dump('one');"
" var_dump($x);"
"}"
"test(1);"
"var_dump('three');");
return true;
}
bool TestCodeRun::TestArrayInit() {
MVCR("<?php\n"
"class MyClass { function __toString() { return 'foo'; } }\n"
"$obj = new MyClass();\n"
"$arr = array($obj => 1, new MyClass() => 2, "
"false => 3, true => 4, count(array(1,2,3)) => 5);\n"
"var_dump($arr);\n");
MVCR("<?php\n"
"function f() { throw new Exception(); }\n"
"function test() {\n"
" $a = array(1, f(), 2, f(), 3);\n"
" var_dump($a);\n"
"}\n"
"try { test(); } catch (Exception $e) { }\n");
MVCR("<?php\n"
"function test($x, $y) {"
"$a = array($x, $y);"
"$a[] = 3;"
"return $a;"
"}"
"var_dump(test(1,2));");
MVCR("<?php\n"
"function foo($p) {"
" $a = array('a', 'b', $p);"
" $a[] = 'd';"
" var_dump($a);"
" $a = array(0 => 'a', 1 => 'b', 2 => $p);"
" $a[] = 'd';"
" var_dump($a);"
" $a = array(2 => 'a', 4 => 'b', 6 => $p);"
" $a[] = 'd';"
" var_dump($a);"
" $a = array(-2 => 'a', -4 => 'b', -6 => $p);"
" $a[] = 'd';"
" var_dump($a);"
" $a = array(0 => 'a');"
" $a[] = 'b';"
" var_dump($a);"
"}"
"foo('c');");
MVCR("<?php\n"
"$v = 1;"
"function foo($a) {"
" $arr = array($a, $a++, $a);"
" var_dump($arr);"
"}"
"foo($v);");
return true;
}
bool TestCodeRun::TestArrayCopy() {
MVCR("<?php function h1() {\n"
" $x = array(1,2,3,4);\n"
" next($x);\n"
" $y = $x;\n"
" unset($y[2]);\n"
" var_dump(current($x));\n"
" var_dump(current($y));\n"
"}\n"
"h1();\n");
MVCR("<?php function h2() {\n"
" $x = array(1,2,3,4);\n"
" next($x);\n"
" $y = $x;\n"
" $y[] = 4;\n"
" var_dump(current($x));\n"
" var_dump(current($y));\n"
"}\n"
"h2();\n");
MVCR("<?php function h3() {\n"
" $x = array(1,2,3,4);\n"
" next($x);\n"
" $y = $x;\n"
" array_pop($y);\n"
" var_dump(current($x));\n"
" var_dump(current($y));\n"
"}\n"
"h3();\n");
/**
* Zend PHP 5.2 outputs:
* bool(false)
* int(1)
*
* The difference in behavior is intentional. Under Zend PHP, the first call
* to current triggers an array copy, and because the original array's
* internal iterator points past the end, the copy's internal iterator is
* reset. This behavior exposes information to user code about when array
* copies are triggered.
*
* Under HPHP, we always leave the internal iterator intact when making an
* array copy. The advantage here is that we do not expose information about
* when array copies are triggered to user code.
*/
MVCRO("<?php function h4() {\n"
" $x = array(1,2,3,4);\n"
" end($x);\n"
" next($x);\n"
" $y = $x;\n"
" unset($y[2]);\n"
" var_dump(current($x));\n"
" var_dump(current($y));\n"
"}\n"
"h4();\n"
,
"bool(false)\n"
"bool(false)\n"
);
/**
* Zend PHP 5.2 outputs:
* bool(false)
* int(1)
*
* The difference in behavior is intentional. Under Zend PHP, when 4 is
* appended to $y, it triggers an array copy which resets $y's internal
* iterator. This is why current($y) returns 1.
*
* Under HPHP, when 4 is appended to $y, it triggers an array copy. However,
* $y's internal iterator is not reset; it continues to point past the last
* element. Then when the append operation actually executes, it updates the
* internal iterator to point to the newly appended element. For more info
* see the h4 testcase.
*/
MVCRO("<?php function h5() {\n"
" $x = array(1,2,3,4);\n"
" end($x);\n"
" next($x);\n"
" $y = $x;\n"
" $y[] = 4;\n"
" var_dump(current($x));\n"
" var_dump(current($y));\n"
"}\n"
"h5();\n"
,
"bool(false)\n"
"int(4)\n"
);
MVCR("<?php function h6() {\n"
" $x = array(1,2,3,4);\n"
" end($x);\n"
" next($x);\n"
" $y = $x;\n"
" array_pop($y);\n"
" var_dump(current($x));\n"
" var_dump(current($y));\n"
"}\n"
"h6();\n");
/**
* Zend PHP 5.2 outputs:
* int(0)
* bool(false)
*
* The difference in behavior is intentional. For more info see testcase h4.
*/
MVCRO("<?php function h7() {\n"
" $arr = array(0,1,2,3,4);\n"
" end($arr);\n"
" next($arr);\n"
" $arr2 = $arr;\n"
" var_dump(current($arr));\n"
" var_dump(current($arr2));\n"
"}\n"
"h7();\n"
,
"bool(false)\n"
"bool(false)\n"
);
/**
* Zend PHP 5.2 outputs:
* int(0)
* bool(false)
*
* The difference in behavior is intentional. For more info see testcase h4.
*/
MVCRO("<?php function h8() {\n"
" $arr = array(0,1,2,3,4);\n"
" end($arr);\n"
" next($arr);\n"
" $arr2 = $arr;\n"
" var_dump(current($arr2));\n"
" var_dump(current($arr));\n"
"}\n"
"h8();\n"
,
"bool(false)\n"
"bool(false)\n"
);
MVCR("<?php\n"
"function f($a) { $a[0] = $a; var_dump($a); }\n"
"f(false);\n");
MVCR("<?php\n"
"function f($b) {\n"
" $a = $b ? 0 : array('x' => $b);\n"
" $a[0] = $a; var_dump($a);\n"
"}\n"
"f(false);\n");
MVCR("<?php\n"
"function f($a) { $a[] = $a; var_dump($a); }\n"
"f(false);\n");
/**
* Even Zend PHP 5.3 does not get this right. It generates a recursive array.
*/
MVCRO("<?php\n"
"function f($b) {\n"
" $a = $b ? 0 : array('x' => $b);\n"
" $a2 = &$a; $a[] = $a2; var_dump($a);\n"
"}\n"
"f(false);\n"
,
"array(2) {\n"
" [\"x\"]=>\n"
" bool(false)\n"
" [0]=>\n"
" array(1) {\n"
" [\"x\"]=>\n"
" bool(false)\n"
" }\n"
"}\n");
MVCR("<?php\n"
"function f($b) {\n"
" $a = $b ? 0 : array($b);\n"
" $a[1][0] = $a; var_dump($a);\n"
"}\n"
"f(false);\n");
return true;
}
bool TestCodeRun::TestScalarArray() {
MVCR("<?php "
"$a1 = array();"
"$a2 = array(null);"
"$a3 = array(true);"
"$a4 = array(false);"
"$a5 = array(0);"
"$a6 = array(1);"
"$a7 = array(1.0);"
"$a8 = array('1.0');"
"$a9 = array(1.23456789e+34);"
"$a13 = array(1.7976931348623157e+308);"
"$a10 = array(1E666);"
"$a11 = array(1E666/1E666);"
"$a12 = array(\"a bc\");"
"$a13 = array(\"\\xc1 bc\");"
"$a14 = array(null, true, false, 0, 1, 1.0,"
" '1.0', 1.23456789e+34,"
" 1.7976931348623157e+308, 1E666,"
" 1E666/1E666, \"a bc\","
" \"\\xc1 bc\");"
"$a15 = array(null => true, false => 0, 1 => 1.0,"
" '1.0' => 1.23456789e+34,"
" 1.7976931348623157e+308 => 1E666,"
" 1E666/1E666 => \"a bc\","
" \"\\xc1 bc\");"
"$a16 = array(null => true, false => 0, 1 => 1.0,"
" '1.0' => 1.23456789e+34,"
" 1.7976931348623157e+308 => 1E666,"
" 1E666/1E666 => \"a bc\","
" \"\\xc1 bc\","
" array(null => true, array(),"
" false => 0, 1 => 1.0,"
" '1.0' => 1.23456789e+34,"
" 1.7976931348623157e+308 => 1E666,"
" 1E666/1E666 => \"a bc\","
" \"\\xc1 bc\"));"
"var_dump($a1);"
"var_dump($a2);"
"var_dump($a3);"
"var_dump($a4);"
"var_dump($a5);"
"var_dump($a6);"
"var_dump($a7);"
"var_dump($a8);"
"var_dump($a9);"
"var_dump($a10);"
"var_dump($a11);"
"var_dump($a12);"
"var_dump($a13);"
"var_dump($a14);"
"var_dump($a15);"
"var_dump($a16);");
MVCR("<?php\n"
"function test1() { $a = array(__FUNCTION__, __LINE__); return $a; }\n"
"function test2() { $a = array(__FUNCTION__, __LINE__); return $a; }\n"
"var_dump(test1()); var_dump(test2());");
MVCR("<?php "
"define('VALUE', 1);"
"function func($params) {"
" var_dump($params);"
"}"
"func(array('key' => @VALUE));");
return true;
}
bool TestCodeRun::TestRange() {
MVCR("<?php "
"foreach (range(\"0 xxx\", \"12 yyy\") as $number) {"
" echo $number . \"\n\";"
"}"
"foreach (range(\"0\", \"12\") as $number) {"
" echo $number . \"\n\";"
"}"
"foreach (range('a', 'i') as $letter) {"
" echo $letter;"
"}"
"foreach (range('c', 'a') as $letter) {"
" echo $letter;"
"}"
"foreach (range('a xxx', 'i yyy') as $letter) {"
" echo $letter;"
"}"
"foreach (range('c xxx', 'a yyy') as $letter) {"
" echo $letter;"
"}");
return true;
}
#define TEST_ARRAY_CONVERT(exp) \
MVCR("<?php $a = " exp "; $a[] = 1; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[] = 'test'; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[] = array(0); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[0] = 1; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[0] = 'test'; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[0] = array(0); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[1] = 1; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[1] = 'test'; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[1] = array(0); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[2] = 1; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[2] = 'test'; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a[2] = array(0); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a['test'] = 1; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a['test'] = 'test'; var_dump($a);"); \
MVCR("<?php $a = " exp "; $a['test'] = array(0); var_dump($a);"); \
#define TEST_ARRAY_PLUS(exp) \
MVCR("<?php $a = " exp "; $a += array(); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a += array(20); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a += array('b'); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a += array(array(3)); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a += array('c' => 20); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a += array('c' => 'b'); var_dump($a);"); \
MVCR("<?php $a = " exp "; $a += array('c' => array(3)); var_dump($a);"); \
bool TestCodeRun::TestArrayEscalation() {
TEST_ARRAY_CONVERT("array()");
TEST_ARRAY_CONVERT("array(10)");
TEST_ARRAY_CONVERT("array('test')");
TEST_ARRAY_CONVERT("array(array(0))");
TEST_ARRAY_CONVERT("array('a' => 10)");
TEST_ARRAY_CONVERT("array('a' => 'va')");
TEST_ARRAY_CONVERT("array('a' => array(1))");
TEST_ARRAY_PLUS("array()");
TEST_ARRAY_PLUS("array(10)");
TEST_ARRAY_PLUS("array('test')");
TEST_ARRAY_PLUS("array(array(0))");
TEST_ARRAY_PLUS("array('a' => 10)");
TEST_ARRAY_PLUS("array('a' => 'va')");
TEST_ARRAY_PLUS("array('a' => array(1))");
MVCR("<?php "
"function test() {"
" $a = array();"
" for ($i = 0; $i < 17; $i++) {"
" $a[] = $i;"
" }"
" unset($a[16]);"
" $b = $a;"
" array_unshift($a, 'foo');"
" var_dump(count($a), count($b));"
"}"
"test();");
return true;
}
bool TestCodeRun::TestArrayOffset() {
MVCR("<?php $a['test_cache_2'] = 10; print $a['test_cache_26'];");
MVCR("<?php $a = array(10); $b = $a[0]; var_dump($b);");
MVCR("<?php $a = array(10); $b = $a[0] + 15; var_dump($b);");
MVCR("<?php $a = 1; $a = array($a); $a = array($a); var_dump($a);");
MVCR("<?php $a['A'] = array(1, 2); foreach ($a['A'] as $item) print $item;");
MVCR("<?php $a['A']['B'] = 1; var_dump($a);");
MVCR("<?php $a['A'] = 10; $a['A']++; var_dump($a);");
MVCR("<?php $a['A'] = 10; ++$a['A']; var_dump($a);");
MVCR("<?php $a['A'] = 10; $a['A'] .= 'test'; var_dump($a);");
MVCR("<?php $a['A'] = 10; $a['A'] += 25; var_dump($a);");
MVCR("<?php $a[null] = 10;"
"var_dump($a[null]);"
"var_dump($a[\"\"]);"
"var_dump($a['']);");
MVCR("<?php "
"$a = array();"
"$a[0] = 1;"
"$a[01] = 2;"
"$a[007] = 3;"
"$a[08] = 4;"
"$a[0xa] = 5;"
"var_dump($a);"
"var_dump(\"$a[0]\");"
"var_dump(\"$a[1]\");"
"var_dump(\"$a[7]\");"
"var_dump(\"$a[10]\");"
"var_dump(\"$a[01]\");"
"var_dump(\"$a[007]\");"
"var_dump(\"$a[08]\");"
"var_dump(\"$a[0xa]\");");
MVCR("<?php "
"class A {"
" const i1= -1;"
" const i2= -2;"
" static $s = -4;"
"};"
"class B {"
" static $s = -5;"
"};"
"$attr=array();"
"$attr[a::i1]='abc';"
"$attr[a::i2]='def';"
"$attr[-3]='ghi';"
"$attr[a::$s]='jkl';"
"$attr[b::$s]='mno';"
"var_dump($attr);");
MVCR("<?php "
"function foo(&$a) {}"
"foo($a[array()]);"
"foo($a[new StdClass]);"
"var_dump($a);");
MVCR("<?php\n"
"function f(&$elem) {\n"
"$elem = 44;\n"
"}\n"
"$arr = array();\n"
"$arr[PHP_INT_MAX-1] = 1;\n"
"$arr[PHP_INT_MAX] = 2;\n"
"var_dump($arr);\n"
"f($arr[]);\n"
"var_dump($arr);\n"
"unset($arr[PHP_INT_MAX]);\n"
"unset($arr[PHP_INT_MAX-1]);\n"
"f($arr[]);\n"
"var_dump($arr);\n");
MVCR("<?php "
"function foo($p) {"
" return $p;"
"}"
"$a = array(1, 2, 3, 4);"
"$a[123] = 5;"
"$a[\"0000\"] = 6;"
"var_dump(foo(__LINE__));"
"var_dump(foo(array()));"
"var_dump(foo(array(1, 2, 3)));"
"var_dump(foo($a[123]));"
"var_dump(foo($a[0000]));"
"var_dump(foo(\"$a[123]\"));"
"var_dump(foo(\"$a[0000]\"));");
return true;
}
bool TestCodeRun::TestArrayAccess() {
MVCR("<?php\n"
"class A implements ArrayAccess {"
" public $a;"
" public function offsetExists($offset) {"
" echo \"offsetExist\";"
" return false;"
" }"
" public function offsetGet($offset) {"
" echo \"offsetGet\";"
" return $this->$offset.'get';"
" }"
" public function offsetSet($offset, $value) {"
" $this->$offset = $value.'set';"
" }"
" public function offsetUnset($offset) {"
" $this->$offset = 'unset';"
" }"
"}"
"function f() { var_dump('f()'); return 1; }\n"
"function test($a) {\n"
"$a['foo'] .= f();\n"
"$a['bar'] += f();\n"
"$a['bar'] -= f();\n"
"$a['bar'] *= f();\n"
"$a['bar'] /= f();\n"
"$a['bar'] %= f();\n"
"$a['bar'] &= f();\n"
"$a['bar'] |= f();\n"
"$a['bar'] ^= f();\n"
"$a['bar'] <<= f();\n"
"$a['bar'] >>= f();\n"
"}\n"
"test(new A);\n"
);
MVCR("<?php "
"class A implements ArrayAccess {"
" public $a;"
" public function offsetExists($offset) {"
" echo \"offsetExist\";"
" return false;"
" }"
" public function offsetGet($offset) {"
" echo \"offsetGet\";"
" return $this->$offset.'get';"
" }"
" public function offsetSet($offset, $value) {"
" $this->$offset = $value.'set';"
" }"
" public function offsetUnset($offset) {"
" $this->$offset = 'unset';"
" }"
"}"
"$obj = new A();"
"if (!isset($obj['a'])) {"
" $obj['a'] = 'test';"
"}"
"if (!empty($obj['a'])) {"
" $obj['a'] = 'test2';"
"}"
"var_dump($obj['a']);"
"unset($obj['a']);"
"var_dump($obj['a']);"
);
MVCR("<?php "
"function offsetGet($index) {"
" echo (\"GET0: $index\\n\");"
"}"
"class ArrayAccessImpl implements ArrayAccess {"
" public $data = array();"
" public function offsetUnset($index) { echo \"UNSET: $index\\n\"; }"
" public function offsetSet($index, $value) {"
" echo (\"SET: $index\\n\");"
" if(isset($data[$index])) {"
" unset($data[$index]);"
" }"
" $u = &$this->data[$index];"
" if(is_array($value)) {"
" $u = new ArrayAccessImpl();"
" foreach($value as $idx=>$e)"
" $u[$idx]=$e;"
" } else"
" $u=$value;"
" }"
" public function offsetGet($index) {"
" echo (\"GET: $index\\n\");"
" if(!isset($this->data[$index]))"
" $this->data[$index]=new ArrayAccessImpl();"
" return $this->data[$index];"
" }"
" public function offsetExists($index) {"
" echo (\"EXISTS: $index\\n\");"
" if(isset($this->data[$index])) {"
" if($this->data[$index] instanceof ArrayAccessImpl) {"
" if(count($this->data[$index]->data)>0)"
" return true;"
" else"
" return false;"
" } else"
" return true;"
" } else"
" return false;"
" }"
"}"
""
"class ArrayAccessImpl2 extends ArrayAccessImpl {"
" public function offsetUnset($index) { echo \"UNSET2: $index\\n\"; }"
" public function offsetSet($index, $value) {"
" echo (\"SET2: $index\\n\");"
" if(isset($data[$index])) {"
" unset($data[$index]);"
" }"
" $u = &$this->data[$index];"
" if(is_array($value)) {"
" $u = new ArrayAccessImpl();"
" foreach($value as $idx=>$e)"
" $u[$idx]=$e;"
" } else"
" $u=$value;"
" }"
" public function offsetGet($index) {"
" echo (\"GET2: $index\\n\");"
" if(!isset($this->data[$index]))"
" $this->data[$index]=new ArrayAccessImpl();"
" return $this->data[$index];"
" }"
" public function offsetExists($index) {"
" echo (\"EXISTS2: $index\\n\");"
" if(isset($this->data[$index])) {"
" if($this->data[$index] instanceof ArrayAccessImpl) {"
" if(count($this->data[$index]->data)>0)"
" return true;"
" else"
" return false;"
" } else"
" return true;"
" } else"
" return false;"
" }"
"}"
"offsetGet('foo');"
"$data = new ArrayAccessImpl();"
"$data['string']=\"Just a simple string\";"
"$data['number']=33;"
"$data['array']['another_string']=\"Alpha\";"
"$data['array']['some_object']=new stdClass();"
"$data['array']['another_array']['x']['y']=\"Beta\";"
"$data['blank_array']=array();"
"print_r(isset($data['array']));"
"print_r($data['array']['non_existent']);"
"print_r(isset($data['array']['non_existent']));"
"print_r($data['blank_array']);"
"print_r(isset($data['blank_array']));"
"unset($data['blank_array']);"
"print_r($data);"
"$data2 = new ArrayAccessImpl2();"
"$data2['string']=\"Just a simple string\";"
"$data2['number']=33;"
"$data2['array']['another_string']=\"Alpha\";"
"$data2['array']['some_object']=new stdClass();"
"$data2['array']['another_array']['x']['y']=\"Beta\";"
"$data2['blank_array']=array();"
"print_r(isset($data2['array']));"
"print_r($data2['array']['non_existent']);"
"print_r(isset($data2['array']['non_existent']));"
"print_r($data2['blank_array']);"
"print_r(isset($data2['blank_array']));"
"unset($data2['blank_array']);"
"print_r($data2);");
MVCR("<?php "
"class X implements ArrayAccess {"
" function offsetGet($f) { return $f; }"
" function offsetSet($f, $v) {}"
" function offsetUnset($f) {}"
" function offsetExists($f) { return false; }"
" }"
"function test() {"
" $x = new X;"
" unset($x['a']);"
" return isset($x['b']);"
"}"
"var_dump(test());");
MVCR("<?php "
"function test($x) {"
" $a = $x;"
" $b = $a;"
" $a[0]->foo = 1;"
" var_dump($a, $b);"
" $a = $x;"
" $b = $a;"
" $a[0][1] = 1;"
" var_dump($a, $b);"
" $a = $x;"
" $c = &$a[0];"
" $b = $a;"
" $a[0][1] = 1;"
" var_dump($a, $b);"
" }"
"test(array(false));"
"var_dump(array(false));");
return true;
}
bool TestCodeRun::TestArrayIterator() {
HipHopSyntax w(this);
MVCR("<?php "
"class MyIterator implements Iterator"
"{"
" private $var = array();"
" public function __construct($array)"
" {"
" echo \"constructing\n\";"
" if (is_array($array)) {"
" $this->var = $array;"
" }"
" }"
" public function rewind() {"
" echo \"rewinding\n\";"
" reset($this->var);"
" }"
" public function current() {"
" $var = current($this->var);"
" echo \"current: $var\n\";"
" return $var;"
" }"
" public function key() {"
" $var = key($this->var);"
" echo \"key: $var\n\";"
" return $var;"
" }"
" public function next() {"
" $var = next($this->var);"
" echo \"next: $var\n\";"
" return $var;"
" }"
" public function valid() {"
" $var = $this->current() !== false;"
" echo \"valid: {$var}\n\";"
" return $var;"
" }"
"}"
"$values = array(1,2,3);"
"$it = new MyIterator($values);"
"foreach ($it as $a => $b) {"
" print \"$a: $b\n\";"
"}"
"$itp = \"it\";"
"foreach ($$itp as $a => $b) {"
" print \"$a: $b\n\";"
"}"
"function getIter() {"
" $values = array(1,2,3);"
" $it = new MyIterator($values);"
" return $it;"
"}"
"foreach (getIter() as $a => $b) {"
" print \"$a: $b\n\";"
"}"
"class MyIteratorAggregate implements IteratorAggregate {"
" public function getIterator() {"
" return getIter();"
" }"
"}"
"$obj = new MyIteratorAggregate();"
"foreach ($obj as $a => $b) {"
" print \"$a: $b\n\";"
"}"
);
MVCR("<?php\n"
"$a = array(1, 2, 3, 4, 5, 6);\n"
"while ($v = each($a)) { if ($v[1] < 4) $a[] = $v[1] + $v[1]; }\n"
"var_dump($a);\n"
"$a = array(1, 2, 3, 4, 5, 6);\n"
"foreach ($a as $k => $v) { if ($v >= 4) $a = $v + $v; }\n"
"var_dump($a);\n");
MVCR("<?php\n"
"$arr = array('bar', 'bar', 'bar', 'bar', 'bar', 'bar', 'foo');\n"
"function foo() {\n"
" var_dump(__FUNCTION__); global $arr; $arr[] = 'bar';\n"
"}\n"
"function bar() { var_dump(__FUNCTION__); }\n"
"reset($arr);\n"
"while ($func = each($arr)) { $f = $func[1]; $f(); }\n");
MVCR("<?php "
"function test($a) {"
" $it = new ArrayIterator($a);"
" while ($it->valid()) {"
" var_dump($it->key());"
" var_dump($it->current());"
" $it->next();"
" }"
"}"
"test(array('a' => 'x',"
" false => 'y',"
" '1' => false,"
" null => 'z',"
" 'c' => 'w'));");
MVCR("<?php\n"
"$a = array(1, 2, 3);\n"
"$o = new ArrayIterator($a);\n"
"var_dump($o->next());\n"
"var_dump($o->rewind());\n"
"var_dump($o->seek());\n"
"var_dump($o->asort());\n"
"var_dump($o->ksort());\n"
"var_dump($o->natsort());\n"
"var_dump($o->natcasesort());\n");
// MutableArrayIterator
MVCRO("<?php\n"
"$a = array(1, 2, 3);\n"
"foreach ($a as $k1 => &$v1) { $v1 += $k1; }\n"
"var_dump($a);\n"
"$a = array(1, 2, 3);\n"
"for ($o = new MutableArrayIterator($a); $o->valid(); $o->next()) {\n"
" $k2 = $o->key();\n"
" $v2 = &$o->currentRef();\n"
" $v2 += $k2;\n"
"}\n"
"var_dump($a);\n"
,
"array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(3)\n"
" [2]=>\n"
" &int(5)\n"
"}\n"
"array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(3)\n"
" [2]=>\n"
" &int(5)\n"
"}\n");
MVCRO("<?php\n"
"function gen() {\n"
" $a = array(1, 2, 3);\n"
" foreach ($a as $k1 => &$v1) { $v1 += $k1; }\n"
" var_dump($a);\n"
" $a = array(1, 2, 3);\n"
" for ($o = new MutableArrayIterator($a); $o->valid(); $o->next()) {\n"
" $k2 = $o->key();\n"
" $v2 = &$o->currentRef();\n"
" $v2 += $k2;\n"
" }\n"
" var_dump($a);\n"
" yield null;\n"
"}\n"
"foreach (gen() as $_) {}\n"
,
"array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(3)\n"
" [2]=>\n"
" &int(5)\n"
"}\n"
"array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(3)\n"
" [2]=>\n"
" &int(5)\n"
"}\n");
MVCR("<?php"
"function ex($m) {"
" var_dump('Throwing: '.$m);"
" throw new Exception($m);"
"}"
"class A {"
" public function __construct() {"
" var_dump(__METHOD__);"
" }"
" public function __destruct() {"
" var_dump(__METHOD__);"
" }"
"}"
"class B {"
" public $a;"
" public function gen() {"
" ex('die!');"
" yield(2);"
" }"
" function __destruct() {"
" var_dump(__METHOD__);"
" }"
"}"
"class II {"
" private $tn, $tv;"
" function __construct($tn, $tv) { $this->tn = $tn; $this->tv = $tv; }"
" function __destruct() {"
" var_dump(__METHOD__);"
" }"
" public function gen() { return new I($this->tn, $this->tv); }"
"}"
"class JJ {"
" private $tn, $tv;"
" function __construct($tn, $tv) { $this->tn = $tn; $this->tv = $tv; }"
" function __destruct() {"
" var_dump(__METHOD__);"
" }"
" public function gen() { return new J($this->tn, $this->tv); }"
"}"
"class KK {"
" private $tn, $tv;"
" function __construct($tn, $tv) { $this->tn = $tn; $this->tv = $tv; }"
" function __destruct() {"
" var_dump(__METHOD__);"
" }"
" public function gen() { return new K($this->tn, $this->tv); }"
"}"
"class LL {"
" private $tn, $tv;"
" function __construct($tn, $tv) { $this->tn = $tn; $this->tv = $tv; }"
" function __destruct() {"
" var_dump(__METHOD__);"
" }"
" public function gen() { return new L($this->tn, $this->tv); }"
"}"
"class I implements Iterator"
"{"
" private $tn, $tv, $i = 0;"
" public function gen() { return $this; }"
" public function __construct($tn, $tv) {"
" $this->tn = $tn;"
" $this->tv = $tv;"
" }"
" public function __destruct() {"
" var_dump(__METHOD__);"
" }"
" public function rewind() {"
" var_dump(__METHOD__);"
" if ($this->tn == 0) ex(__METHOD__);"
" $this->i = 1;"
" }"
" public function current() {"
" var_dump(__METHOD__);"
" return $this->i;"
" }"
" public function key() {"
" var_dump(__METHOD__);"
" return $this->i;"
" }"
" public function next() {"
" var_dump(__METHOD__);"
" if ($this->tn == $this->i) ex(__METHOD__);"
" return ++$this->i;"
" }"
" public function valid() {"
" var_dump(__METHOD__);"
" if ($this->tv == $this->i) ex(__METHOD__);"
" return $this->i < 10;"
" }"
"}"
"class J implements IteratorAggregate {"
" private $i;"
" public function __construct($tn, $tv) {"
" $this->i = new I($tn, $tv);"
" }"
" public function __destruct() {"
" var_dump(__METHOD__);"
" }"
" public function getIterator() { return $this->i; }"
" public function gen() { return $this; }"
"}"
"class K implements IteratorAggregate {"
" private $tn, $tv;"
" public function __construct($tn, $tv) {"
" $this->tn = $tn;"
" $this->tv = $tv;"
" }"
" public function __destruct() {"
" var_dump(__METHOD__);"
" }"
" public function getIterator() { return new I($this->tn, $this->tv); }"
" public function gen() { return $this; }"
"}"
"class L implements IteratorAggregate {"
" public function getIterator() { ex(__METHOD__); }"
" public function gen() { return $this; }"
"}"
"function run($n, $tn, $tv) {"
" var_dump('>>>main');"
" $a = new A();"
" $b = new $n($tn, $tv);"
" $b->a = $a;"
" try {"
" foreach ($b->gen() as $k) {"
" var_dump('got '.$k);"
" }"
" } catch(Exception $e) {"
" var_dump('Exception: ' . $e->getMessage());"
" unset($e);"
" }"
" unset($b);"
" var_dump('<<<main');"
"}"
"function test($n, $tn, $tv) {"
" run($n, $tn, $tv);"
" var_dump('Done: '.$n);"
"}"
"function triple($n) {"
" test($n, 0, 0);"
" test($n, -1, 1);"
" test($n, 2,-1);"
"}"
"function main() {"
" triple('I');"
" triple('J');"
" triple('K');"
" triple('L');"
" triple('II');"
" triple('JJ');"
" triple('KK');"
" triple('LL');"
" test('B', 0, 0);"
"}"
"main();");
return true;
}
bool TestCodeRun::TestArrayForEach() {
HipHopSyntax w(this);
MVCR("<?php\n"
"function f1() {\n"
" $i = 0;\n"
" $foo = array(1,2,3,4);\n"
" foreach ($foo as $key => &$val) {\n"
" echo \"key=$key val=$val\\n\";\n"
" if($val == 2) {\n"
" $foo[$key] = 0;\n"
" } else if($val == 3) {\n"
" unset($foo[$key]);\n"
" } else {\n"
" $val++;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
" var_dump($foo);\n"
"}\n"
"f1();\n");
MVCRO("<?php\n"
"function f1() {\n"
" $i = 0;\n"
" $foo = array(1,2,3,4);\n"
" foreach ($foo as $key => &$val) {\n"
" yield null;\n"
" echo \"key=$key val=$val\\n\";\n"
" if($val == 2) {\n"
" $foo[$key] = 0;\n"
" } else if($val == 3) {\n"
" unset($foo[$key]);\n"
" } else {\n"
" $val++;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
" var_dump($foo);\n"
"}\n"
"foreach (f1() as $_) {}\n"
,
"key=0 val=1\n"
"key=1 val=2\n"
"key=2 val=3\n"
"key=3 val=4\n"
"array(3) {\n"
" [0]=>\n"
" int(2)\n"
" [1]=>\n"
" int(0)\n"
" [3]=>\n"
" &int(5)\n"
"}\n"
);
MVCR("<?php\n"
"function f2() {\n"
" $i = 0;\n"
" $foo = array(1,2,3,4);\n"
" foreach ($foo as $key => &$val) {\n"
" echo \"key=$key val=$val\\n\";\n"
" if($val == 2) {\n"
" $foo[$key] = 0;\n"
" } else if($val == 3) {\n"
" $foo['a'] = 7;\n"
" } else {\n"
" $val++;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
" var_dump($foo);\n"
"}\n"
"f2();\n");
MVCRO("<?php\n"
"function f2() {\n"
" $i = 0;\n"
" $foo = array(1,2,3,4);\n"
" foreach ($foo as $key => &$val) {\n"
" yield null;\n"
" echo \"key=$key val=$val\\n\";\n"
" if($val == 2) {\n"
" $foo[$key] = 0;\n"
" } else if($val == 3) {\n"
" $foo['a'] = 7;\n"
" } else {\n"
" $val++;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
" var_dump($foo);\n"
"}\n"
"foreach (f2() as $_) {}\n"
,
"key=0 val=1\n"
"key=1 val=2\n"
"key=2 val=3\n"
"key=3 val=4\n"
"key=a val=7\n"
"array(5) {\n"
" [0]=>\n"
" int(2)\n"
" [1]=>\n"
" int(0)\n"
" [2]=>\n"
" int(3)\n"
" [3]=>\n"
" int(5)\n"
" [\"a\"]=>\n"
" &int(8)\n"
"}\n"
);
/**
* Zend PHP 5.2 outputs:
* key=a val=1
* key=b val=2
* key=c val=333
* array(6) {
* ["a"]=>
* int(1)
* ["b"]=>
* int(2)
* ["d"]=>
* int(4)
* ["e"]=>
* int(5)
* ["f"]=>
* int(6)
* ["c"]=>
* &int(333)
* }
*
* The difference in behavior is intentional. Under Zend, when the next
* element is unset inside a foreach by reference loop, a heuristic is used
* to figure out which element should be visited next. In this specific
* example, the loop resumes at key 'c', skipping over keys 'd', 'e', and
* 'f'.
*
* Under HPHP, when the next element is unset inside a foreach by loop, the
* loop's iterator is appropriately updated. HPHP successfully upholds the
* invariant that a foreach by refererence loop that exhausts the array will
* visit every element that has not been deleted exactly once.
*/
MVCRO("<?php\n"
"function f3() {\n"
" $i = 0;\n"
" $foo = array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5, 'f'=>6);\n"
" $bar = array();\n"
" $a = 0;\n"
" foreach ($foo as $key => &$val) {\n"
" echo \"key=$key val=$val\\n\";\n"
" if ($key == 'b' && $a == 0) {\n"
" $a = 1;\n"
" unset($foo['c']);\n"
" $foo['c'] = 333;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
" var_dump($foo);\n"
"}\n"
"f3();\n"
,
"key=a val=1\n"
"key=b val=2\n"
"key=d val=4\n"
"key=e val=5\n"
"key=f val=6\n"
"key=c val=333\n"
"array(6) {\n"
" [\"a\"]=>\n"
" int(1)\n"
" [\"b\"]=>\n"
" int(2)\n"
" [\"d\"]=>\n"
" int(4)\n"
" [\"e\"]=>\n"
" int(5)\n"
" [\"f\"]=>\n"
" int(6)\n"
" [\"c\"]=>\n"
" &int(333)\n"
"}\n"
);
MVCRO("<?php\n"
"function f3() {\n"
" $i = 0;\n"
" $foo = array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5, 'f'=>6);\n"
" $bar = array();\n"
" $a = 0;\n"
" foreach ($foo as $key => &$val) {\n"
" yield null;\n"
" echo \"key=$key val=$val\\n\";\n"
" if ($key == 'b' && $a == 0) {\n"
" $a = 1;\n"
" unset($foo['c']);\n"
" $foo['c'] = 333;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
" var_dump($foo);\n"
"}\n"
"foreach (f3() as $_) {}\n"
,
"key=a val=1\n"
"key=b val=2\n"
"key=d val=4\n"
"key=e val=5\n"
"key=f val=6\n"
"key=c val=333\n"
"array(6) {\n"
" [\"a\"]=>\n"
" int(1)\n"
" [\"b\"]=>\n"
" int(2)\n"
" [\"d\"]=>\n"
" int(4)\n"
" [\"e\"]=>\n"
" int(5)\n"
" [\"f\"]=>\n"
" int(6)\n"
" [\"c\"]=>\n"
" &int(333)\n"
"}\n"
);
MVCR("<?php\n"
"function f4() {\n"
" $i = 0;\n"
" $foo = array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5, 'f'=>6);\n"
" $bar = array();\n"
" $a = 0;\n"
" foreach ($foo as $key => &$val) {\n"
" echo \"key=$key val=$val\\n\";\n"
" if ($key == 'b' && $a == 0) {\n"
" $a = 1;\n"
" unset($foo['c']);\n"
" $bar['b'] = 888;\n"
" $foo['c'] = 333;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
" var_dump($foo);\n"
"}\n"
"f4();\n");
MVCRO("<?php\n"
"function f4() {\n"
" $i = 0;\n"
" $foo = array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5, 'f'=>6);\n"
" $bar = array();\n"
" $a = 0;\n"
" foreach ($foo as $key => &$val) {\n"
" yield null;\n"
" echo \"key=$key val=$val\\n\";\n"
" if ($key == 'b' && $a == 0) {\n"
" $a = 1;\n"
" unset($foo['c']);\n"
" $bar['b'] = 888;\n"
" $foo['c'] = 333;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
" var_dump($foo);\n"
"}\n"
"foreach (f4() as $_) {}\n"
,
"key=a val=1\n"
"key=b val=2\n"
"key=d val=4\n"
"key=e val=5\n"
"key=f val=6\n"
"key=c val=333\n"
"array(6) {\n"
" [\"a\"]=>\n"
" int(1)\n"
" [\"b\"]=>\n"
" int(2)\n"
" [\"d\"]=>\n"
" int(4)\n"
" [\"e\"]=>\n"
" int(5)\n"
" [\"f\"]=>\n"
" int(6)\n"
" [\"c\"]=>\n"
" &int(333)\n"
"}\n"
);
/**
* Zend PHP 5.2 outputs:
* key=f val=3
* key()=e current()=1
* key=e val=1
* key()=d current()=5
* key=d val=9
* key()=0s0 current()=0
* key=0s0 val=0
* key()=1s1 current()=1
* key=1s1 val=1
* key()=2s2 current()=2
* key=2s2 val=2
* key()=3s3 current()=3
* key=3s3 val=3
* key()=4s4 current()=4
* ...
*
* The difference in behavior is intentional. For more info, see testcase h3.
*/
MVCRO("<?php\n"
"function f5() {\n"
" $i = 0;\n"
" $foo = array('f'=>3, 'e'=>1, 'd'=>5, 'a'=>6, 'b'=>2, 'c'=>4);\n"
" $a = 0;\n"
" foreach ($foo as $key => &$val) {\n"
" echo \"key=$key val=$val\\n\";\n"
" if ($key == 'e' && $a == 0) {\n"
" $a = 1;\n"
" unset($foo['e']);\n"
" unset($foo['d']);\n"
" $foo['d'] = 9;\n"
" for ($j = 0; $j < 10000; ++$j)\n"
" $foo[$j . 's' . $j] = $j;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"f5();\n"
,
"key=f val=3\n"
"key=e val=1\n"
"key=a val=6\n"
"key=b val=2\n"
"key=c val=4\n"
"key=d val=9\n"
"key=0s0 val=0\n"
"key=1s1 val=1\n"
"key=2s2 val=2\n"
"key=3s3 val=3\n"
"key=4s4 val=4\n"
"key=5s5 val=5\n"
"key=6s6 val=6\n"
"key=7s7 val=7\n"
"key=8s8 val=8\n"
"key=9s9 val=9\n"
"key=10s10 val=10\n"
"key=11s11 val=11\n"
"key=12s12 val=12\n"
"key=13s13 val=13\n"
);
MVCRO("<?php\n"
"function f5() {\n"
" $i = 0;\n"
" $foo = array('f'=>3, 'e'=>1, 'd'=>5, 'a'=>6, 'b'=>2, 'c'=>4);\n"
" $a = 0;\n"
" foreach ($foo as $key => &$val) {\n"
" yield null;\n"
" echo \"key=$key val=$val\\n\";\n"
" if ($key == 'e' && $a == 0) {\n"
" $a = 1;\n"
" unset($foo['e']);\n"
" unset($foo['d']);\n"
" $foo['d'] = 9;\n"
" for ($j = 0; $j < 10000; ++$j)\n"
" $foo[$j . 's' . $j] = $j;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"foreach (f5() as $_) {}\n"
,
"key=f val=3\n"
"key=e val=1\n"
"key=a val=6\n"
"key=b val=2\n"
"key=c val=4\n"
"key=d val=9\n"
"key=0s0 val=0\n"
"key=1s1 val=1\n"
"key=2s2 val=2\n"
"key=3s3 val=3\n"
"key=4s4 val=4\n"
"key=5s5 val=5\n"
"key=6s6 val=6\n"
"key=7s7 val=7\n"
"key=8s8 val=8\n"
"key=9s9 val=9\n"
"key=10s10 val=10\n"
"key=11s11 val=11\n"
"key=12s12 val=12\n"
"key=13s13 val=13\n"
);
MVCR("<?php\n"
"function f6() {\n"
" $i = 0;\n"
" $foo = array('f'=>3, 'e'=>1, 'd'=>5, 'a'=>6, 'b'=>2, 'c'=>4);\n"
" $a = 0;\n"
" foreach ($foo as $key => &$val) {\n"
" echo \"key=$key val=$val\\n\";\n"
" if ($key == 'e' && $a == 0) {\n"
" $a = 1;\n"
" unset($foo['e']);\n"
" unset($foo['d']);\n"
" $bar['e'] = 8;\n"
" $foo['d'] = 9;\n"
" for ($j = 0; $j < 10000; ++$j)\n"
" $foo[$j . 's' . $j] = $j;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"f6();\n");
MVCRO("<?php\n"
"function f6() {\n"
" $i = 0;\n"
" $foo = array('f'=>3, 'e'=>1, 'd'=>5, 'a'=>6, 'b'=>2, 'c'=>4);\n"
" $a = 0;\n"
" foreach ($foo as $key => &$val) {\n"
" yield null;\n"
" echo \"key=$key val=$val\\n\";\n"
" if ($key == 'e' && $a == 0) {\n"
" $a = 1;\n"
" unset($foo['e']);\n"
" unset($foo['d']);\n"
" $bar['e'] = 8;\n"
" $foo['d'] = 9;\n"
" for ($j = 0; $j < 10000; ++$j)\n"
" $foo[$j . 's' . $j] = $j;\n"
" }\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"foreach (f6() as $_) {}\n"
,
"key=f val=3\n"
"key=e val=1\n"
"key=a val=6\n"
"key=b val=2\n"
"key=c val=4\n"
"key=d val=9\n"
"key=0s0 val=0\n"
"key=1s1 val=1\n"
"key=2s2 val=2\n"
"key=3s3 val=3\n"
"key=4s4 val=4\n"
"key=5s5 val=5\n"
"key=6s6 val=6\n"
"key=7s7 val=7\n"
"key=8s8 val=8\n"
"key=9s9 val=9\n"
"key=10s10 val=10\n"
"key=11s11 val=11\n"
"key=12s12 val=12\n"
"key=13s13 val=13\n"
);
/**
* Zend PHP 5.2 outputs:
* key=0 value=0
* key=1 value=1
* key=2 value=0
* key=3 value=1
*
* The difference in behavior is intentional. Under PHP, a foreach by
* reference loop will not visit an element that is appended to the array
* during the iteration for the last element in the array.
*
* Under HPHP, a foreach by reference loop will always visit an element that
* is appended to the array during any iteration, provided that the element
* is not deleted and the loop does not exit early.
*/
MVCRO("<?php\n"
"function f7() {\n"
" $i = 0;\n"
" $bar = array();\n"
" $arr = array(0,1,0,1);\n"
" foreach ($arr as $k => &$v) {\n"
" echo \"key=$k value=$v\\n\";\n"
" if ($k == 0)\n"
" $val = 1;\n"
" else\n"
" $val = $arr[$k-1];\n"
" $arr[$k+1] = $val;\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"f7();\n"
,
"key=0 value=0\n"
"key=1 value=1\n"
"key=2 value=0\n"
"key=3 value=1\n"
"key=4 value=0\n"
"key=5 value=1\n"
"key=6 value=0\n"
"key=7 value=1\n"
"key=8 value=0\n"
"key=9 value=1\n"
"key=10 value=0\n"
"key=11 value=1\n"
"key=12 value=0\n"
"key=13 value=1\n"
"key=14 value=0\n"
"key=15 value=1\n"
"key=16 value=0\n"
"key=17 value=1\n"
"key=18 value=0\n"
"key=19 value=1\n"
);
MVCRO("<?php\n"
"function f7() {\n"
" $i = 0;\n"
" $bar = array();\n"
" $arr = array(0,1,0,1);\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo \"key=$k value=$v\\n\";\n"
" if ($k == 0)\n"
" $val = 1;\n"
" else\n"
" $val = $arr[$k-1];\n"
" $arr[$k+1] = $val;\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"foreach (f7() as $_) {}\n"
,
"key=0 value=0\n"
"key=1 value=1\n"
"key=2 value=0\n"
"key=3 value=1\n"
"key=4 value=0\n"
"key=5 value=1\n"
"key=6 value=0\n"
"key=7 value=1\n"
"key=8 value=0\n"
"key=9 value=1\n"
"key=10 value=0\n"
"key=11 value=1\n"
"key=12 value=0\n"
"key=13 value=1\n"
"key=14 value=0\n"
"key=15 value=1\n"
"key=16 value=0\n"
"key=17 value=1\n"
"key=18 value=0\n"
"key=19 value=1\n"
);
MVCR("<?php\n"
"function f8() {\n"
" $i = 0;\n"
" $bar = array();\n"
" $arr = array(0,1,0,1);\n"
" foreach ($arr as $k => &$v) {\n"
" echo \"key=$k value=$v\\n\";\n"
" if ($k == 0)\n"
" $val = 1;\n"
" else\n"
" $val = $arr[$k-1];\n"
" unset($arr[$k+1]);\n"
" $bar[] = 0;\n"
" $arr[$k+1] = $val;\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"f8();\n");
MVCRO("<?php\n"
"function f8() {\n"
" $i = 0;\n"
" $bar = array();\n"
" $arr = array(0,1,0,1);\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo \"key=$k value=$v\\n\";\n"
" if ($k == 0)\n"
" $val = 1;\n"
" else\n"
" $val = $arr[$k-1];\n"
" unset($arr[$k+1]);\n"
" $bar[] = 0;\n"
" $arr[$k+1] = $val;\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"foreach (f8() as $_) {}\n"
,
"key=0 value=0\n"
"key=2 value=0\n"
"key=1 value=1\n"
"key=3 value=1\n"
"key=2 value=0\n"
"key=4 value=0\n"
"key=3 value=1\n"
"key=5 value=1\n"
"key=4 value=0\n"
"key=6 value=0\n"
"key=5 value=1\n"
"key=7 value=1\n"
"key=6 value=0\n"
"key=8 value=0\n"
"key=7 value=1\n"
"key=9 value=1\n"
"key=8 value=0\n"
"key=10 value=0\n"
"key=9 value=1\n"
"key=11 value=1\n"
);
MVCR("<?php\n"
"function f9() {\n"
" $i = 0;\n"
" $arr = array(1,1,1);\n"
" $bar = array();\n"
" $first = true;\n"
" foreach ($arr as $k => &$v) {\n"
" echo \"k=$k v=$v\\n\";\n"
" if (!$first) {\n"
" $prev_k = ($k+2)%3;\n"
" unset($arr[$prev_k]);\n"
" if (count($bar) > 100)\n"
" $bar = array();\n"
" $bar[] = 1;\n"
" $arr[$prev_k] = 1;\n"
" }\n"
" $first = false;\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"f9();\n");
MVCRO("<?php\n"
"function f9() {\n"
" $i = 0;\n"
" $arr = array(1,1,1);\n"
" $bar = array();\n"
" $first = true;\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo \"k=$k v=$v\\n\";\n"
" if (!$first) {\n"
" $prev_k = ($k+2)%3;\n"
" unset($arr[$prev_k]);\n"
" if (count($bar) > 100)\n"
" $bar = array();\n"
" $bar[] = 1;\n"
" $arr[$prev_k] = 1;\n"
" }\n"
" $first = false;\n"
" ++$i;\n"
" if ($i >= 20)\n"
" break;\n"
" }\n"
"}\n"
"foreach (f9() as $_) {}\n"
,
"k=0 v=1\n"
"k=1 v=1\n"
"k=2 v=1\n"
"k=0 v=1\n"
"k=1 v=1\n"
"k=2 v=1\n"
"k=0 v=1\n"
"k=1 v=1\n"
"k=2 v=1\n"
"k=0 v=1\n"
"k=1 v=1\n"
"k=2 v=1\n"
"k=0 v=1\n"
"k=1 v=1\n"
"k=2 v=1\n"
"k=0 v=1\n"
"k=1 v=1\n"
"k=2 v=1\n"
"k=0 v=1\n"
"k=1 v=1\n"
);
MVCR("<?php function g1() {\n"
" $arr = array(0,1,2,3);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" $arr = array(4,5,6,7);\n"
" }\n"
" }\n"
"}\n"
"g1();\n");
MVCRO("<?php function g1() {\n"
" $arr = array(0,1,2,3);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" yield null;\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" $arr = array(4,5,6,7);\n"
" }\n"
" }\n"
"}\n"
"foreach (g1() as $_) {}\n"
,
"val=0\n"
"val=1\n"
"val=4\n"
"val=5\n"
"val=6\n"
"val=7\n"
);
MVCR("<?php function g2() {\n"
" $arr = array(0,1,2,3);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" $old = $arr;\n"
" $arr = array(4,5,6,7);\n"
" } else if ($v == 6) {\n"
" $arr = $old;\n"
" unset($old);\n"
" }\n"
" }\n"
"}\n"
"g2();\n");
MVCRO("<?php function g2() {\n"
" $arr = array(0,1,2,3);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" yield null;\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" $old = $arr;\n"
" $arr = array(4,5,6,7);\n"
" } else if ($v == 6) {\n"
" $arr = $old;\n"
" unset($old);\n"
" }\n"
" }\n"
"}\n"
"foreach (g2() as $_) {}\n"
,
"val=0\n"
"val=1\n"
"val=4\n"
"val=5\n"
"val=6\n"
"val=2\n"
"val=3\n"
);
MVCR("<?php function g3() {\n"
" $arr2 = array(0,1,2,3);\n"
" $arr = $arr2;\n"
" $b = true;\n"
" $b2 = true;\n"
" foreach ($arr as &$v) {\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" $arr = array(4,5,6,7);\n"
" } else if ($b2 && $v == 6) {\n"
" $b2 = false;\n"
" $arr = $arr2;\n"
" }\n"
" }\n"
"}\n"
"g3();\n");
MVCRO("<?php function g3() {\n"
" $arr2 = array(0,1,2,3);\n"
" $arr = $arr2;\n"
" $b = true;\n"
" $b2 = true;\n"
" foreach ($arr as &$v) {\n"
" yield null;\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" $arr = array(4,5,6,7);\n"
" } else if ($b2 && $v == 6) {\n"
" $b2 = false;\n"
" $arr = $arr2;\n"
" }\n"
" }\n"
"}\n"
"foreach (g3() as $_) {}\n"
,
"val=0\n"
"val=1\n"
"val=4\n"
"val=5\n"
"val=6\n"
"val=0\n"
"val=1\n"
"val=2\n"
"val=3\n"
);
MVCR("<?php function g4() {\n"
" $arr = array(0,1,2,3);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_push($arr, 4);\n"
" }\n"
" }\n"
"}\n"
"g4();\n");
MVCRO("<?php function g4() {\n"
" $arr = array(0,1,2,3);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" yield null;\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_push($arr, 4);\n"
" }\n"
" }\n"
"}\n"
"foreach (g4() as $_) {}\n"
,
"val=0\n"
"val=1\n"
"val=2\n"
"val=3\n"
"val=4\n"
);
MVCR("<?php function g5() {\n"
" $arr = array(0,1,2,3);\n"
" $arr2 = $arr;\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_push($arr, 4);\n"
" }\n"
" }\n"
"}\n"
"g5();\n");
MVCRO("<?php function g5() {\n"
" $arr = array(0,1,2,3);\n"
" $arr2 = $arr;\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" yield null;\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_push($arr, 4);\n"
" }\n"
" }\n"
"}\n"
"foreach (g5() as $_) {}\n"
,
"val=0\n"
"val=1\n"
"val=2\n"
"val=3\n"
"val=4\n"
);
MVCR("<?php function g6() {\n"
" $arr = array(0,'a'=>1,2,'b'=>3,4);\n"
" $b = true;\n"
" foreach ($arr as $k => &$v) {\n"
" echo \"key=$k val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_pop($arr);\n"
" }\n"
" }\n"
"}\n"
"g6();\n");
MVCRO("<?php function g6() {\n"
" $arr = array(0,'a'=>1,2,'b'=>3,4);\n"
" $b = true;\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo \"key=$k val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_pop($arr);\n"
" }\n"
" }\n"
"}\n"
"foreach (g6() as $_) {}\n"
,
"key=0 val=0\n"
"key=a val=1\n"
"key=1 val=2\n"
"key=b val=3\n"
);
MVCR("<?php function g7() {\n"
" $arr = array(0,'a'=>1,2,'b'=>3,4);\n"
" $b = true;\n"
" foreach ($arr as $k => &$v) {\n"
" echo \"key=$k val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" unset($arr[1]); \n"
" }\n"
" }\n"
"}\n"
"g7();\n");
MVCRO("<?php function g7() {\n"
" $arr = array(0,'a'=>1,2,'b'=>3,4);\n"
" $b = true;\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo \"key=$k val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" unset($arr[1]); \n"
" }\n"
" }\n"
"}\n"
"foreach (g7() as $_) {}\n"
,
"key=0 val=0\n"
"key=a val=1\n"
"key=b val=3\n"
"key=2 val=4\n"
);
/**
* Zend PHP 5.2 outputs:
* key=0 val=0
* key=a val=1
* key=0 val=0
* key=a val=1
* key=b val=3
*
* The difference in behavior is intentional. Under PHP, after the next
* element is unset inside the foreach by reference loop and the array_pop
* operation is performed, a heuristic is used to determine which element
* should be visited next. If this specific example, the loop chooses to
* resume at key '0'.
*
* Under HPHP, when the next element is unset inside a foreach by loop, the
* loop's iterator is appropriately updated. Likewise, the loop's iterator
* remains intact after the array_pop operation. Thus, after the unset and
* the pop operation, HPHP resumes the loop at key 'b'.
*/
MVCRO("<?php function g8() {\n"
" $arr = array(0,'a'=>1,2,'b'=>3,4);\n"
" $b = true;\n"
" foreach ($arr as $k => &$v) {\n"
" echo \"key=$k val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" unset($arr[1]); \n"
" array_pop($arr);\n"
" }\n"
" }\n"
"}\n"
"g8();\n"
,
"key=0 val=0\n"
"key=a val=1\n"
"key=b val=3\n"
);
MVCRO("<?php function g8() {\n"
" $arr = array(0,'a'=>1,2,'b'=>3,4);\n"
" $b = true;\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo \"key=$k val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" unset($arr[1]); \n"
" array_pop($arr);\n"
" }\n"
" }\n"
"}\n"
"foreach (g8() as $_) {}\n"
,
"key=0 val=0\n"
"key=a val=1\n"
"key=b val=3\n"
);
MVCR("<?php function g9() {\n"
" $arr = array(0,1,2,3,4);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_shift($arr);\n"
" }\n"
" }\n"
"}\n"
"g9();\n");
MVCRO("<?php function g9() {\n"
" $arr = array(0,1,2,3,4);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" yield null;\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_shift($arr);\n"
" }\n"
" }\n"
"}\n"
"foreach (g9() as $_) {}\n"
,
"val=0\n"
"val=1\n"
"val=1\n"
"val=2\n"
"val=3\n"
"val=4\n"
);
MVCR("<?php function g10() {\n"
" $arr = array(0,1,2,3);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_unshift($arr, 4);\n"
" }\n"
" }\n"
"}\n"
"g10();\n");
MVCRO("<?php function g10() {\n"
" $arr = array(0,1,2,3);\n"
" $b = true;\n"
" foreach ($arr as &$v) {\n"
" yield null;\n"
" echo \"val=$v\\n\";\n"
" if ($b && $v == 1) {\n"
" $b = false;\n"
" array_unshift($arr, 4);\n"
" }\n"
" }\n"
"}\n"
"foreach (g10() as $_) {}\n"
,
"val=0\n"
"val=1\n"
"val=4\n"
"val=0\n"
"val=1\n"
"val=2\n"
"val=3\n"
);
MVCR("<?php function g11() {\n"
" $arr = array(0,1,2,3);\n"
" reset($arr);\n"
" var_dump(current($arr));\n"
" foreach ($arr as &$v) {\n"
" var_dump(current($arr));\n"
" }\n"
" var_dump(current($arr));\n"
"}\n"
"g11();\n");
MVCRO("<?php function g11() {\n"
" $arr = array(0,1,2,3);\n"
" reset($arr);\n"
" var_dump(current($arr));\n"
" foreach ($arr as &$v) {\n"
" yield null;\n"
" var_dump(current($arr));\n"
" }\n"
" var_dump(current($arr));\n"
"}\n"
"foreach (g11() as $_) {}\n"
,
"int(0)\n"
"int(1)\n"
"int(2)\n"
"int(3)\n"
"bool(false)\n"
"bool(false)\n"
);
MVCR("<?php "
"function g12($a) {"
" var_dump($a);"
" $arr = array(0,1,2,3);"
" $b = true;"
" foreach ($arr as &$v) {"
" if ($b && $v == 1) {"
" $b = false;"
" $arr = $a;"
" } else {"
" $v = 5;"
" }"
" }"
" var_dump($a);"
"}"
"g12(array(0, 0, 0, 0));");
MVCRO("<?php "
"function g12($a) {"
" var_dump($a);"
" $arr = array(0,1,2,3);"
" $b = true;"
" foreach ($arr as &$v) {"
" yield null;"
" if ($b && $v == 1) {"
" $b = false;"
" $arr = $a;"
" } else {"
" $v = 5;"
" }"
" }"
" var_dump($a);"
"}"
"foreach (g12(array(0, 0, 0, 0)) as $_) {}"
,
"array(4) {\n"
" [0]=>\n"
" int(0)\n"
" [1]=>\n"
" int(0)\n"
" [2]=>\n"
" int(0)\n"
" [3]=>\n"
" int(0)\n"
"}\n"
"array(4) {\n"
" [0]=>\n"
" int(0)\n"
" [1]=>\n"
" int(0)\n"
" [2]=>\n"
" int(0)\n"
" [3]=>\n"
" int(0)\n"
"}\n"
);
MVCR("<?php\n"
"function h1(&$arr, $i) {\n"
" foreach ($arr as $k => &$v) {\n"
" echo \"i=$i key=$k\\n\";\n"
" if ($k == 0) {\n"
" if ($i > 0) {\n"
" h1($arr, $i-1);\n"
" } else if ($i == 0) {\n"
" echo \"Unsetting key 1\\n\";\n"
" unset($arr[1]);\n"
" }\n"
" }\n"
" }\n"
" end($arr);\n"
"}\n"
"$arr = array('a','b','c');\n"
"h1($arr, 10);\n"
"var_dump($arr);\n");
MVCRO("<?php\n"
"function h1(&$arr, $i) {\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo \"i=$i key=$k\\n\";\n"
" if ($k == 0) {\n"
" if ($i > 0) {\n"
" foreach (h1($arr, $i-1) as $_) {}\n"
" } else if ($i == 0) {\n"
" echo \"Unsetting key 1\\n\";\n"
" unset($arr[1]);\n"
" }\n"
" }\n"
" }\n"
" end($arr);\n"
"}\n"
"$arr = array('a','b','c');\n"
"foreach (h1($arr, 10) as $_) {}\n"
"var_dump($arr);\n"
,
"i=10 key=0\n"
"i=9 key=0\n"
"i=8 key=0\n"
"i=7 key=0\n"
"i=6 key=0\n"
"i=5 key=0\n"
"i=4 key=0\n"
"i=3 key=0\n"
"i=2 key=0\n"
"i=1 key=0\n"
"i=0 key=0\n"
"Unsetting key 1\n"
"i=0 key=2\n"
"i=1 key=2\n"
"i=2 key=2\n"
"i=3 key=2\n"
"i=4 key=2\n"
"i=5 key=2\n"
"i=6 key=2\n"
"i=7 key=2\n"
"i=8 key=2\n"
"i=9 key=2\n"
"i=10 key=2\n"
"array(2) {\n"
" [0]=>\n"
" string(1) \"a\"\n"
" [2]=>\n"
" string(1) \"c\"\n"
"}\n"
);
MVCR("<?php\n"
"function foo() {\n"
" $arr = array(10,20,30,40,50);\n"
" foreach ($arr as $k => &$v) {\n"
" echo $k . \"\\n\";\n"
" if ($k == 2 && !isset($arr2)) {\n"
" $arr2 = $arr;\n"
" }\n"
" $v += 100;\n"
" }\n"
" var_dump($arr);\n"
" var_dump($arr2);\n"
"}\n"
"foo();\n");
MVCRO("<?php\n"
"function foo() {\n"
" $arr = array(10,20,30,40,50);\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo $k . \"\\n\";\n"
" if ($k == 2 && !isset($arr2)) {\n"
" $arr2 = $arr;\n"
" }\n"
" $v += 100;\n"
" }\n"
" var_dump($arr);\n"
" var_dump($arr2);\n"
"}\n"
"foreach (foo() as $_) {}\n"
,
"0\n"
"1\n"
"2\n"
"3\n"
"4\n"
"array(5) {\n"
" [0]=>\n"
" int(110)\n"
" [1]=>\n"
" int(120)\n"
" [2]=>\n"
" &int(130)\n"
" [3]=>\n"
" int(140)\n"
" [4]=>\n"
" &int(150)\n"
"}\n"
"array(5) {\n"
" [0]=>\n"
" int(110)\n"
" [1]=>\n"
" int(120)\n"
" [2]=>\n"
" &int(130)\n"
" [3]=>\n"
" int(40)\n"
" [4]=>\n"
" int(50)\n"
"}\n"
);
MVCR("<?php\n"
"function foo() {\n"
" $arr = array(10,20,30,40,50);\n"
" foreach ($arr as $k => &$v) {\n"
" echo $k . \"\\n\";\n"
" if ($k == 2 && !isset($arr2)) {\n"
" $arr2 = $arr;\n"
" $arr[] = 60;\n"
" }\n"
" $v += 100;\n"
" }\n"
" var_dump($arr);\n"
" var_dump($arr2);\n"
"}\n"
"foo();\n");
MVCRO("<?php\n"
"function foo() {\n"
" $arr = array(10,20,30,40,50);\n"
" foreach ($arr as $k => &$v) {\n"
" yield null;\n"
" echo $k . \"\\n\";\n"
" if ($k == 2 && !isset($arr2)) {\n"
" $arr2 = $arr;\n"
" $arr[] = 60;\n"
" }\n"
" $v += 100;\n"
" }\n"
" var_dump($arr);\n"
" var_dump($arr2);\n"
"}\n"
"foreach (foo() as $_) {}\n"
,
"0\n"
"1\n"
"2\n"
"3\n"
"4\n"
"5\n"
"array(6) {\n"
" [0]=>\n"
" int(110)\n"
" [1]=>\n"
" int(120)\n"
" [2]=>\n"
" &int(130)\n"
" [3]=>\n"
" int(140)\n"
" [4]=>\n"
" int(150)\n"
" [5]=>\n"
" &int(160)\n"
"}\n"
"array(5) {\n"
" [0]=>\n"
" int(110)\n"
" [1]=>\n"
" int(120)\n"
" [2]=>\n"
" &int(130)\n"
" [3]=>\n"
" int(40)\n"
" [4]=>\n"
" int(50)\n"
"}\n"
);
/**
* Zend PHP 5.2 outputs:
* val=0
* val=1
* val=2
* val=3
* val=4
* bool(false)
*
* The difference in behavior is intentional. Under PHP, foreach by value can
* in some cases modify the array's internal iterator without triggering an
* array copy. This can potentially expose information to user code about
* when array copies are triggered.
*
* Under HPHP, foreach by value will never modify the array's internal
* iterator. The advantage here is that we do not expose information about
* when array copies are triggered to user code.
*
* The PHP manual states the following:
* foreach has some side effects on the array pointer. Don't rely on the
* array pointer during or after the foreach without resetting it.
*/
MVCRO("<?php function k1() {\n"
" $arr = array(0,1,2,3,4);\n"
" reset($arr);\n"
" foreach ($arr as $v) {\n"
" echo \"val=$v\\n\";\n"
" }\n"
" var_dump(current($arr));\n"
"}\n"
"k1();\n"
,
"val=0\n"
"val=1\n"
"val=2\n"
"val=3\n"
"val=4\n"
"int(0)\n"
);
MVCR("<?php function k2() {\n"
" $arr = array(0,1,2,3,4);\n"
" reset($arr);\n"
" $arr2 = $arr;\n"
" foreach ($arr as $v) {\n"
" echo \"val=$v\\n\";\n"
" }\n"
" var_dump(current($arr));\n"
" var_dump(current($arr2));\n"
"}\n"
"k2();\n");
/**
* Zend PHP 5.2 outputs:
* val=0
* val=1
* val=2
* val=3
* val=4
* int(0)
* bool(false)
*
* The difference in behavior is intentional. For more info see testcase k1.
*/
MVCRO("<?php function k3() {\n"
" $arr = array(0,1,2,3,4);\n"
" reset($arr);\n"
" $b = true;\n"
" foreach ($arr as $v) {\n"
" if ($b) {\n"
" $b = false;\n"
" $arr2 = $arr;\n"
" }\n"
" echo \"val=$v\\n\";\n"
" }\n"
" var_dump(current($arr));\n"
" var_dump(current($arr2));\n"
"}\n"
"k3();\n"
,
"val=0\n"
"val=1\n"
"val=2\n"
"val=3\n"
"val=4\n"
"int(0)\n"
"int(0)\n"
);
/**
* Zend PHP 5.2 outputs:
* val=0
* val=1
* val=2
* val=3
* val=4
* int(0)
* bool(false)
*
* This behavior is intentional. For more info see testcase k1.
*/
MVCRO("<?php function k4() {\n"
" $arr = array(0,1,2,3,4);\n"
" reset($arr);\n"
" $b = true;\n"
" foreach ($arr as $v) {\n"
" if ($b) {\n"
" $b = false;\n"
" $arr2 = $arr;\n"
" }\n"
" echo \"val=$v\\n\";\n"
" }\n"
" var_dump(current($arr2));\n"
" var_dump(current($arr));\n"
"}\n"
"k4();\n"
,
"val=0\n"
"val=1\n"
"val=2\n"
"val=3\n"
"val=4\n"
"int(0)\n"
"int(0)\n"
);
MVCR("<?php "
"$a = array(1,2,3,4,5);"
"function foo($a, $b, $c) {"
" var_dump('foo');"
" return 1;"
"}"
"function bar($a, $b, $c) {"
" var_dump('bar');"
" return 2;"
"}"
"function buz($x,$y) { if ($y) return $x; return 1; }"
"$s = buz('hello',1);"
"foreach ($a as $s[3]) {"
" var_dump($s);"
"}"
"$i = 0;"
"foreach ($a as "
" $a[bar($i++, $i++, $i++)] => &$a[foo($i++, $i++, $i++)]) {"
" var_dump($a[1],$a[2]);"
"}"
"foreach ($a as "
" $a[bar($i++, $i++, $i++)] => $a[foo($i++, $i++, $i++)]) {"
" var_dump($a[1],$a[2]);"
"}");
MVCR("<?php "
"class X {"
" function __destruct() { var_dump(__METHOD__); }"
"}"
"function test() {"
" $a = array(new X, 0);"
" foreach ($a as $v) {"
" var_dump($v);"
" }"
" $a = null;"
" var_dump('done');"
"}"
"test();"
"var_dump('exit');");
MVCR("<?php\n"
"function main() {\n"
" echo \"Entering main\\n\";\n"
" foreach (array(1 => 1) as $k => $v) {\n"
" break;\n"
" }\n"
" echo \"Leaving main\\n\";\n"
"}\n"
"main();\n");
return true;
}
bool TestCodeRun::TestArrayAssignment() {
MVCR("<?php "
"$a = array(1, 2, 3);"
"$b = $a;"
"$b[4] = 4;"
"var_dump($a);"
"var_dump($b);"
"$b = 3;"
"var_dump($a);"
"var_dump($b);");
MVCR("<?php "
"$a = array('1', '2', '3');"
"$b = $a;"
"$b[4] = '4';"
"var_dump($a);"
"var_dump($b);"
"$b = '3';"
"var_dump($a);"
"var_dump($b);");
MVCR("<?php "
"$a = array(1.5, 2.5, 3.5);"
"$b = $a;"
"$b[4] = 4.5;"
"var_dump($a);"
"var_dump($b);"
"$b = 3.5;"
"var_dump($a);"
"var_dump($b);");
MVCR("<?php "
"$a = array(1, 'hello', 3.5);"
"$b = $a;"
"$b[4] = 'world';"
"var_dump($a);"
"var_dump($b);");
MVCR("<?php "
"$a = array(1, 'hello', 3.5);"
"$b = $a;"
"$b[4] = 'world';"
"var_dump($a);"
"var_dump($b);"
"$b = 3;"
"var_dump($a);"
"var_dump($b);");
MVCR("<?php "
"$a = array('a' => '1', 2 => 2, 'c' => '3');"
"var_dump($a);"
"$a = array('a' => '1', 2 => 2, 'c' => '3',"
" 'd' => array('a' => '1', 2 => 2, 'c' => '3'));"
"var_dump($a);");
MVCR("<?php "
"$a = array(1=>'main', 2=>'sub');"
"$b = $a;"
"var_dump(array_pop($b));"
"print_r($a);"
"var_dump(array_shift($b));"
"print_r($a);");
MVCR("<?php "
"$a = array(1, 2, 3);"
"var_dump($a);"
"array_pop($a);"
"var_dump($a);"
"array_shift($a);"
"var_dump($a);");
MVCR("<?php "
"function foo() {"
" $p = 1;"
" $q = 2;"
" $r = 3;"
" $s = 4;"
" $a = array('1'=>$p, '2'=>&$q);"
" $b = array('3'=>$r, '4'=>&$s);"
" var_dump($a);"
" $a += $b;"
" var_dump($a);"
" var_dump($b);"
"}"
"foo();");
MVCR("<?php $a = false; $a['a'] = 10;");
MVCR("<?php $a = false; $a['a']['b'] = 10;");
// invalid offset type
MVCR("<?php\n"
"class c { function f(&$a, $b) { $a = $b; } }\n"
"function setNullVariantHelper($f, $value) {\n"
" $a = array();\n"
" $obj = new c;\n"
" $obj->$f($a[$obj] = 1, $value);\n"
" var_dump($a[$obj] = 1);\n"
"}\n"
"function setNullVariant($value) {\n"
" setNullVariantHelper('f', $value);\n"
"}\n"
"setNullVariant('Surprise!');\n"
"$b = null;\n"
"var_dump($b[1]);\n");
// empty string to array conversion
MVCR("<?php\n"
"$s = '';\n"
"$s[0] += 10;\n"
"var_dump($s);\n");
return true;
}
bool TestCodeRun::TestArrayFunctions() {
MVCR("<?php "
"class A implements Countable { public function count() { return 1;}} "
"$obj = new A(); var_dump(count($obj));");
MVCR("<?php\n"
"$a = array(\n"
" array('a' => 'a'),\n"
" array('b' => 'bb'),\n"
" array('c' => 'cc'),\n"
");\n"
"\n"
"$refs = array();\n"
"foreach ($a as &$arr) {\n"
" $refs[] = &$arr;\n"
"}\n"
"array_splice($a, 1, 1);\n"
"var_dump($a);\n"
);
MVCR("<?php\n"
"$x = array('x' => 'y');\n"
"$a = array('a1' => $x, 'a2' => $x);\n"
"$b = array('a1' => array(1,2,3), 'a2' => array(1,2,3));\n"
"var_dump(array_merge_recursive($a, $b));");
MVCR("<?php\n"
"$x = array('x' => 'y');\n"
"$a = array('a1' => &$x, 'a2' => &$x);\n"
"$b = array('a1' => array(), 'a2' => array(1,2));\n"
"var_dump(array_merge_recursive($a, $b));");
MVCR("<?php\n"
"$x = array('x' => 'y');\n"
"$a = array('a1' => &$x, 'a2' => &$x);\n"
"$b = array('a1' => array(1,2), 'a2' => array(3,4));\n"
"var_dump(array_merge_recursive($a, $b));");
MVCR("<?php $a = array(1 => 1, 3 => 3); "
"var_dump(array_merge($a, array(2)));");
MVCR("<?php $a = array(1 => 1, 3 => 3); "
"var_dump(array_merge($a, array()));");
MVCR("<?php $a = array('a' => 1, 3 => 3); "
"var_dump(array_merge($a, array(2)));");
MVCR("<?php $a = array('a' => 1, 'b' => 3); "
"var_dump(array_merge($a, array(2)));");
MVCR("<?php $a = array('a' => 1, 3 => 3); "
"var_dump(array_merge($a, array('a' => 2)));");
MVCR("<?php $a = array('a' => 1, 3 => 3); "
"var_dump(array_merge($a, array('b' => 2)));");
MVCR("<?php $a = array('a' => 1, 'b' => 3); "
"var_dump(array_merge($a, array('c' => 2)));");
MVCR("<?php "
"var_dump(array_unique(array(array(1,2), array(1,2), array(3,4),)));");
MVCR("<?php "
"$input = array(\"a\" => \"green\","
" \"red\", \"b\" => \"green\", \"blue\", \"red\");"
"$result = array_unique($input);"
"print_r($result);");
MVCR("<?php "
"$input = array(4, \"4\", \"3\", 4, 3, \"3\");"
"$result = array_unique($input);"
"var_dump($result);");
// Preservation of keys and references in original arrays.
MVCR("<?php\n"
"class A { }\n"
"$o = new A;\n"
"$f = '10';\n"
"$o->$f = 100;\n"
"$a = (array)$o;\n"
"$v = 1;\n"
"$a[10] = &$v;\n"
"$a[11] = array(&$v);\n"
"var_dump($a);\n"
// array_diff
"$b = array(10 => 10);\n"
"var_dump(array_diff_key($a, $b));\n"
// array_merge and array_merge_recursive
"var_dump(array_merge($a, $b));\n"
"var_dump(array_merge_recursive($a, $b));\n"
// array_reverse
"var_dump(array_reverse($a));\n"
// array_chunk
"var_dump(array_chunk($a, 2));\n"
);
// Test array_reduce
MVCR("<?php\n"
"function f($x, $y) {\n"
" var_dump($x, $y);\n"
" return $x + $x + $y + 1;\n"
"}\n"
"var_dump(array_reduce(array(), 'f'));\n"
"var_dump(array_reduce(array(), 'f', null));\n"
"var_dump(array_reduce(array(), 'f', 0));\n"
"var_dump(array_reduce(array(), 'f', 23));\n"
"var_dump(array_reduce(array(4), 'f'));\n"
"var_dump(array_reduce(array(4), 'f', null));\n"
"var_dump(array_reduce(array(4), 'f', 0));\n"
"var_dump(array_reduce(array(4), 'f', 23));\n"
"var_dump(array_reduce(array(1,2,3,4), 'f'));\n"
"var_dump(array_reduce(array(1,2,3,4), 'f', null));\n"
"var_dump(array_reduce(array(1,2,3,4), 'f', 0));\n"
"var_dump(array_reduce(array(1,2,3,4), 'f', 23)); \n");
MVCR("<?php "
"var_dump(array_filter(array(4294967295 => 22)));");
return true;
}
bool TestCodeRun::TestArrayCSE() {
HipHopSyntax w0(this);
OptionSetter w1(this, OptionSetter::CompileTime, "-vArrayAccessIdempotent=1");
MVCR("<?php\n"
"function f($x, $y) {\n"
" var_dump($x[$y]);\n"
" if ($x[$y]) print 'HI';\n"
"}\n"
"function g(&$x, $y) {\n"
" var_dump($x[$y]);\n"
" if ($x[$y]) print 'HI';\n"
"}\n"
"f(null, 0);\n"
"f(array(0), 0);\n"
"f(array(0), 'noidx');\n"
"f('abc', 0);\n"
"f('abc', 'noidx');\n"
"g($x = null, 0);\n"
"g($x = array(0), 0);\n"
"g($x = array(0), 'noidx');\n"
"g($x = 'abc', 0);\n"
"g($x = 'abc', 'noidx');\n");
MVCR("<?php\n"
"function f(array $a = null, $e) {\n"
" $a[$e]['foo'] = 30;\n"
" $x = $a[$e]['baz'];\n"
" $a[$e]['bar'] = 50;\n"
" var_dump($a, $x);\n"
"}\n"
"function g($x, $y) {\n"
" $x[$y]['foo'] = 30;\n"
" $x[$y]['bar'] = 30;\n"
" $z = $x[$y]['bar'];\n"
" $x[$y]['baz'] = 30;\n"
" if ($z) {\n"
" $x[$y]['baz'] = 30;\n"
" }\n"
" return $x;\n"
"}\n"
"function h($x, $y) {\n"
" if ($x) {\n"
" $x[$y]['foo'] = 30;\n"
" $x[$y]['bar'] = 30;\n"
" }\n"
" var_dump($x[$y]['foo']);\n"
"}\n"
"f(null, 'e');\n"
"f(array(), 'e');\n"
"f(array('e' => array('baz' => 40)), 'e');\n"
"var_dump(f(array('y' => array()), 'y'));\n"
"var_dump(f(array(), 'y'));\n"
"var_dump(f(array(), array()));\n"
"h(array(), 0);\n"
"h(array(array()), 0);\n");
MVCRO("<?php\n"
"function f(array $a, $e) {\n"
" $a[$e][$e] = 30;\n"
" $x = new stdClass();\n"
" $x = $a[$e];\n"
" var_dump($a, $x);\n"
"}\n"
"function g(string $x) {\n"
" var_dump($x[0]);\n"
" var_dump($x[1]);\n"
" var_dump($x[0]);\n"
"}\n"
"f(array(), 0);\n"
"g('bar');\n"
"g('');\n"
"g('b');\n",
"array(1) {\n"
" [0]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(30)\n"
" }\n"
"}\n"
"array(1) {\n"
" [0]=>\n"
" int(30)\n"
"}\n"
"string(1) \"b\"\n"
"string(1) \"a\"\n"
"string(1) \"b\"\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"string(1) \"b\"\n"
"string(0) \"\"\n"
"string(1) \"b\"\n");
MVCR("<?php\n"
"function f($x) {\n"
" var_dump($x[0]);\n"
" $x =& $x[0];\n"
" $x[0] = 30;\n"
" var_dump($x[0]);\n"
"}\n"
"function g($x) {\n"
" $x[0][1] = 10;\n"
" var_dump($x[0][2]);\n"
"}\n"
"f(array(0));\n"
"g(array());\n"
"g(array(0));\n");
MVCR("class ArrayWrap implements arrayaccess {\n"
" private $x;\n"
" public function __construct($x) {\n"
" $this->x = $x;\n"
" }\n"
" public function offsetSet($offset, $value) {\n"
" $this->x[$offset] = $value;\n"
" }\n"
" public function offsetExists($offset) {\n"
" return isset($this->x[$offset]);\n"
" }\n"
" public function offsetUnset($offset) {\n"
" unset($this->x[$offset]);\n"
" }\n"
" public function offsetGet($offset) {\n"
" return $this->x[$offset];\n"
" }\n"
"}\n"
"$o = new ArrayWrap(array(0, 1, 2));\n"
"\n"
"function f1($x) {\n"
" return isset($x[0]) && $x[0];\n"
"}\n"
"var_dump(f1(null));\n"
"var_dump(f1(array()));\n"
"var_dump(f1(array(0)));\n"
"var_dump(f1(''));\n"
"var_dump(f1('a'));\n"
"var_dump(f1($o));\n"
"\n"
"function f2($x) {\n"
" if (!is_null($x[0])) var_dump($x[0]);\n"
" var_dump($x[0]);\n"
"}\n"
"f2(array(0 => array()));\n"
"f2(array());\n"
"f2('');\n"
"f2($o);\n"
"f2(null);\n"
"\n"
"function f3($x) {\n"
" foreach ($x['foo'] as $k => $v) {\n"
" if ($v) unset($x['foo'][$k]);\n"
" }\n"
" var_dump($x);\n"
"}\n"
"f3(array('foo' => array(0,1,2,3)));\n"
"\n"
"function f4($x) {\n"
" var_dump($x[0][1]);\n"
" unset($x[0][1]);\n"
" var_dump($x[0][1]);\n"
"}\n"
"f4(array(array(1 => new stdClass())));\n"
"\n"
"function f5($x) {\n"
" var_dump(md5($x[0]), $x[0]);\n"
"}\n"
"f5('foobar');\n");
MVCR("function f1($x) {\n"
" if (count($x) > 0) { \n"
" var_dump($x); \n"
" } else if (count($x[0]) > 0) {\n"
" var_dump($x[0]);\n"
" }\n"
"}\n"
"f1(array(array(0, 1, 2)));\n"
"f1('abc');\n"
"\n"
"function id($x) { return $x; }\n"
"function f2($x) {\n"
" if ($x[0]) var_dump(id($x), $x[0]);\n"
"}\n"
"f2(null);\n"
"f2(array());\n"
"f2(array(10));\n"
"\n"
"function f3($x) {\n"
" var_dump($x[0].'/'. $x[1]);\n"
" var_dump($x[0].'/'. $x[1]);\n"
"}\n"
"f3(array('first', 'second'));\n"
"f3('AB');\n"
"\n"
"function f4($x) {\n"
" $z = @id($x[0]);\n"
" var_dump($z);\n"
" var_dump($x[0]);\n"
"}\n"
"f4(array('e1', 'e2'));\n"
"\n"
"function f5($x) {\n"
" if ($x[0][id($x[0])-1]) var_dump($x);\n"
"}\n"
"f5(array(0, 1, 2));\n");
MVCR("function id($x) { return $x; }\n"
"function f1($x) {\n"
" $z = id($x[0]);\n"
" foreach ($x[0] as $a) {\n"
" $z[] = array(id($z), count($x[0]));\n"
" }\n"
"}\n"
"f1(array(array(0, 1, 2, 3)));\n"
"\n"
"function f2($x) {\n"
" var_dump($x[0]);\n"
" $y = 'foo' . $x[0] . 'bar';\n"
"}\n"
"f2('foobar');\n"
"\n"
"function f3($x) {\n"
" $x = is_string($x[0]) ? $x[0] : get_class($x[0]);\n"
" return $x;\n"
"}\n"
"var_dump(f3('abc'));\n"
"var_dump(f3(array(new stdClass)));\n");
MVCR("<?php\n"
"function foo($a, $b, $c, $d) {\n"
" var_dump($a, $b, $c, $d);\n"
"}\n"
"function bar(&$a, $b, $c, $d) {\n"
" var_dump($a, $b, $c, $d);\n"
"}\n"
"function f($a) {\n"
" foo($a[0], $a[0], $a[0], $a[0]++);\n"
" foo($a[0], $a[0], $a[0], $a[0]);\n"
"}\n"
"function g($a) {\n"
" bar($a[0], $a[0], $a[0], $a[0]++);\n"
" bar($a[0], $a[0], $a[0], $a[0]);\n"
"}\n"
"f(array(0));\n"
"g(array(0));\n");
MVCR("<?php\n"
"$GLOBALS['foo'] = 10;\n"
"$GLOBALS['bar'] = \n"
" array(\n"
" 10 => array($GLOBALS['foo']),\n"
" 20 => array($GLOBALS['foo']));\n"
"var_dump($GLOBALS['bar']);\n");
MVCR("<?php\n"
"function blocker() { print 'block'; }\n"
"function f($x) {\n"
" $x = (string) $x;\n"
" blocker();\n"
" var_dump($x[0]);\n"
" var_dump($x[0]);\n"
"}\n"
"var_dump('foo');\n");
MVCR("<?php\n"
"function f1($x) {\n"
" if ($x[1]) goto x_t;\n"
" var_dump($x[0]);\n"
" var_dump($x[0]);\n"
" x_t:\n"
" var_dump($x[0]);\n"
"}\n"
"function f2($x) {\n"
" $i = 3;\n"
" while ($x[0] && $i--) {\n"
" var_dump($x[0]);\n"
" }\n"
"}\n"
"function f3($x, $y) {\n"
" do {\n"
" var_dump($x[0]);\n"
" } while ($x[0] && $y);\n"
" var_dump($x[0]);\n"
"}\n"
"function f4($x) {\n"
" foreach ($x[0] as $k => $v) {\n"
" var_dump($x[0]);\n"
" var_dump($k, $v);\n"
" }\n"
"}\n"
"function f5($x) {\n"
" switch ($x[0]) {\n"
" case 0:\n"
" var_dump($x[0]);\n"
" }\n"
"}\n"
"function f6($x, $y, $z) {\n"
" if ($z) goto my_clause;\n"
" if ($y) { var_dump($y); }\n"
" else if ($x[0]) {\n"
" var_dump($x[0]);\n"
" my_clause:\n"
" var_dump($x);\n"
" }\n"
"}\n"
"f1(array(0, 0));\n"
"f2(array(10));\n"
"f3(array(10), false);\n"
"f4(array(array(1, 2, 3)));\n"
"f5(array(false, false));\n"
"f6(array(true), false, false);\n");
MVCR("<?php\n"
"function blocker() { print 'block'; }\n"
"function id($x) { return $x; }\n"
"function f($x, $y) {\n"
" $y = $x[$y[0]] ? $x[$y[0]] : id($x[$y[0]]);\n"
" blocker();\n"
" var_dump($y);\n"
"}\n");
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool TestCodeRun::TestVariant() {
MVCR("<?php $a = 1; $a = 'test'; print $a;");
MVCR("<?php $a = 1; $a = 'test'; $a .= 'b'; print $a;");
MVCR("<?php $a = array(); $a[] = 3; $a = 'test'; var_dump($a);");
MVCR("<?php $a = array(); $a['test'] = 3; var_dump($a);");
MVCR("<?php $a['test'] = 3; var_dump($a);");
MVCR("<?php $a = 1; $a = 'test'; print $a{0};");
MVCR("<?php $a=1;$a='t'; $a[0] = 'AB'; var_dump($a);");
MVCR("<?php $a=1;$a=''; $a[0] = 'AB'; var_dump($a);");
MVCR("<?php $a=1;$a='t'; $a[10] = 'AB'; var_dump($a);");
MVCR("<?php $a=1;$a='t'; $b = $a; $a[0] = 'AB'; var_dump($a); var_dump($b);");
MVCR("<?php $a=1;$a='t'; $b = $a; $a[10]= 'AB'; var_dump($a); var_dump($b);");
MVCR("<?php $a=1;$a='t'; $b = $a; $b[0] = 'AB'; var_dump($a); var_dump($b);");
MVCR("<?php $a=1;$a='t'; $b = $a; $b[10]= 'AB'; var_dump($a); var_dump($b);");
MVCR("<?php $a = 't'; $a = 1; print $a + 2;");
MVCR("<?php $a = 't'; $a = 1; print 2 + $a;");
MVCR("<?php $a = 't'; $a = 1; $b = 'a'; $b = 2; print $a + $b;");
MVCR("<?php $a = 't'; $a = 1; $a += 2; print $a;");
MVCR("<?php $a = 't'; $a = 1; $a += 'n'; print $a;");
MVCR("<?php $a = 't'; $a = 1; $a += '5'; print $a;");
MVCR("<?php $b = 'test'; $b = 1; $a += $b; print $a;");
MVCR("<?php $a = 't'; $a = 1; print -$a;");
MVCR("<?php $a = 't'; $a = -$a; print $a;");
MVCR("<?php $a = 't'; $a = 1; print $a - 2;");
MVCR("<?php $a = 't'; $a = 1; print 2 - $a;");
MVCR("<?php $a = 't'; $a = 1; $b = 'a'; $b = 2; print $a - $b;");
MVCR("<?php $a = 't'; $a = 1; $a -= 2; print $a;");
MVCR("<?php $a = 't'; $a = 1; $a -= 'n'; print $a;");
MVCR("<?php $a = 't'; $a = 1; $a -= '5'; print $a;");
MVCR("<?php $a = 't'; $a = 10; print $a * 2;");
MVCR("<?php $a = 't'; $a = 10; print 2 * $a;");
MVCR("<?php $a = 't'; $a = 10; $b = 'a'; $b = 2; print $a * $b;");
MVCR("<?php $a = 't'; $a = 10; $a *= 2; print $a;");
MVCR("<?php $a = 't'; $a = 10; $a *= 'n'; print $a;");
MVCR("<?php $a = 't'; $a = 10; $a *= '5'; print $a;");
MVCR("<?php $a = 't'; $a = 10; print $a / 2;");
MVCR("<?php $a = 't'; $a = 10; print 2 / $a;");
MVCR("<?php $a = 't'; $a = 10; $b = 'a'; $b = 2; print $a / $b;");
MVCR("<?php $a = 't'; $a = 10; $a /= 2; print $a;");
MVCR("<?php $a = 't'; $a = 10; $a /= '5'; print $a;");
MVCR("<?php $a = 't'; $a = 10; print $a % 2;");
MVCR("<?php $a = 't'; $a = 10; print 2 % $a;");
MVCR("<?php $a = 't'; $a = 10; $b = 'a'; $b = 2; print $a % $b;");
MVCR("<?php $a = 't'; $a = 10; $a %= 2; print $a;");
MVCR("<?php $a = 't'; $a = 10; $a %= '5'; print $a;");
MVCR("<?php $a = 't'; $a = 10; var_dump(~$a);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; var_dump($a & $b);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; var_dump($a | $b);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; var_dump($a ^ $b);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; var_dump($a << 2);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; var_dump($a >> 2);");
MVCR("<?php $b = 't'; $a = 10; $b = 9; var_dump($a & $b);");
MVCR("<?php $b = 't'; $a = 10; $b = 9; var_dump($a | $b);");
MVCR("<?php $b = 't'; $a = 10; $b = 9; var_dump($a ^ $b);");
MVCR("<?php $b = 't'; $a = 10; $b = 2; var_dump($a << $b);");
MVCR("<?php $b = 't'; $a = 10; $b = 2; var_dump($a >> $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump($a & $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump($a | $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump($a ^ $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 2; var_dump($a << $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 2; var_dump($a >> $b);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; $a &= $b; var_dump($a);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; $a |= $b; var_dump($a);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; $a ^= $b; var_dump($a);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; $a <<= 2; var_dump($a);");
MVCR("<?php $a = 't'; $a = 10; $b = 9; $a >>= 2; var_dump($a);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump($a and $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump($a or $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump($a xor $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump(!$a);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump($a && $b);");
MVCR("<?php $a = 't'; $b = 't'; $a = 10; $b = 9; var_dump($a || $b);");
MVCR("<?php $a = 10; ++$a; var_dump($a);");
MVCR("<?php $a = 10; $a++; var_dump($a);");
MVCR("<?php $a = 10; --$a; var_dump($a);");
MVCR("<?php $a = 10; $a--; var_dump($a);");
MVCR("<?php $a = 't'; $a = 10; ++$a; var_dump($a);");
MVCR("<?php $a = 't'; $a = 10; $a++; var_dump($a);");
MVCR("<?php $a = 't'; $a = 10; --$a; var_dump($a);");
MVCR("<?php $a = 't'; $a = 10; $a--; var_dump($a);");
MVCR("<?php $a = 'test'; ++$a; var_dump($a);");
MVCR("<?php $a = 'test'; $a++; var_dump($a);");
MVCR("<?php $a = 'test'; --$a; var_dump($a);");
MVCR("<?php $a = 'test'; $a--; var_dump($a);");
MVCR("<?php $a = 1; $a = 'test'; var_dump(~$a);");
MVCR("<?php $a = 1; $a = 'test'; $b = 'zzz'; var_dump($a & $b);");
MVCR("<?php $a = 1; $a = 'test'; $b = 'zzz'; var_dump($a | $b);");
MVCR("<?php $a = 1; $a = 'test'; $b = 'zzz'; var_dump($a ^ $b);");
MVCR("<?php $a = 1; $a = 'test'; $b = 'zzz'; $a &= $b; var_dump($a);");
MVCR("<?php $a = 1; $a = 'test'; $b = 'zzz'; $a |= $b; var_dump($a);");
MVCR("<?php $a = 1; $a = 'test'; $b = 'zzz'; $a ^= $b; var_dump($a);");
MVCR("<?php class a { public $var2 = 1; public $var1; }"
"class b extends a { public $var2; }"
"function f() { $obj1 = new b(); var_dump($obj1); $obj1->var1 = 1; }"
"f();"); //#147156
return true;
}
bool TestCodeRun::TestObject() {
HipHopSyntax w(this);
MVCR("<?php "
"var_dump((object)NULL);"
"var_dump((object)true);"
"var_dump((object)10);"
"var_dump((object)'test');"
"var_dump((object)array(10, 20));"
);
MVCR("<?php class A {} $obj = new A(); "
"var_dump($obj);"
"var_dump((bool)$obj);"
"var_dump((int)$obj);"
"var_dump((array)$obj);"
"var_dump((object)$obj);"
);
MVCR("<?php class A { public $test = 'ok';} $obj = new A(); "
"var_dump($obj);"
"var_dump((bool)$obj);"
"var_dump((int)$obj);"
"var_dump((array)$obj);"
"var_dump((object)$obj);"
);
MVCR("<?php "
"var_dump((object)NULL);"
"var_dump((object)true);"
"var_dump((object)10);"
"var_dump((object)'test');"
"var_dump((object)array(10, 20));"
);
MVCR("<?php class A { public $a = 0;} class B extends A {}"
"$obj1 = new A(); $obj2 = new A(); $obj2->a++; "
"$obj3 = new B(); $obj3->a = 10;"
"var_dump($obj1->a);"
"var_dump($obj1);"
"var_dump($obj2->a);"
"var_dump($obj2);"
"var_dump($obj3);"
"var_dump($obj1 instanceof A);"
"var_dump($obj3 instanceof A);"
"var_dump($obj1 instanceof B);"
"var_dump($obj3 instanceof B);"
);
MVCR("<?php "
"class A {"
" public $a = 3;"
" public function __construct($a) {"
" $this->a = $a + 1;"
" }"
" public function __destruct() {"
" $this->a += 2;"
" var_dump($this->a);"
" }"
"}"
"class B extends A {"
" public function __construct($a) {"
" }"
"}"
"class C extends A {"
" public function __construct($a) {"
" parent::__construct($a);"
" }"
"}"
"$obj = new A(1); var_dump($obj->a);"
"$obj = new B(1); var_dump($obj->a);"
"$obj = new C(1); var_dump($obj->a);"
"unset($obj);"
);
MVCR("<?php "
"class A {"
" public $b = 3;"
" public $a = 2;"
"}"
"$obj = new A(); var_dump($obj); var_dump($obj->c);"
);
MVCR("<?php "
"class A {"
" public $a = 2;"
"}"
"class B {"
" public $b = 3;"
"}"
"$obj = new A(); var_dump($obj); /*var_dump($obj->b);*/" // undeclared
"$obj = new B(); var_dump($obj); var_dump($obj->b);"
);
MVCR("<?php "
"class A {"
" public $a = 2;"
"}"
"class B {"
" public $b = 3;"
"}"
"$obj = new A(); var_dump($obj); var_dump($obj->a);"
"$obj = new B(); var_dump($obj); var_dump($obj->b);"
);
MVCR("<?php "
"class A {"
" public $a = 2;"
"}"
"class B extends A {"
" public $b = 3;"
"}"
"$obj = new A(); var_dump($obj); var_dump($obj->b);"
"$obj = new B(); var_dump($obj); var_dump($obj->b);"
);
MVCR("<?php "
"class A {"
" public $a = 2;"
" public $b = 1;"
"}"
"class B extends A {"
" public $b = 3;"
"}"
"$obj = new A(); var_dump($obj); var_dump($obj->b);"
"$obj = new B(); var_dump($obj); var_dump($obj->b);"
);
MVCR("<?php "
"interface I { public function test($a);}"
"class A implements I { public function test($a) { print $a;}}"
"$obj = new A(); var_dump($obj instanceof I); $obj->test('cool');"
);
MVCR("<?php "
"interface I { public function test($a);} "
"class A { public function test($a) { print 'A';}} "
"class B extends A implements I { "
" public function test($a) { print 'B';} "
"}"
"$obj = new A(); $obj->test(1);"
"$obj = new B(); $obj->test(1);"
);
// circular references
MVCR("<?php class A { public $a;} "
"$obj1 = new A(); $obj2 = new A(); $obj1->a = $obj2; $obj2->a = $obj1;"
"var_dump($obj1);");
MVCR("<?php $a = 1; class A { public function t() { global $a; $b = 'a'; var_dump($$b);}} $obj = new A(); $obj->t();");
MVCR("<?php "
"class g {"
" public $v;"
" function set($v) {"
" $this->v = $v;"
" return $this;"
" }"
"}"
"function foo() {"
" $z = 1;"
" $qd = array('x' => $z);"
" $a = G()->set($qd);"
" var_dump($a);"
" $qd['e'] = true;"
" $b = G()->set($qd);"
" var_dump($a);"
""
"}"
"function G() {"
" return new g;"
"}"
"foo();");
MVCR("<?php "
"class EE extends Exception {"
"}"
"class E extends EE {"
" function foo() {}"
" function __construct() {"
" echo 'MAKING E';"
" parent::__construct();"
" }"
"}"
"new E;");
MVCR("<?php "
"class A {"
" var $a;"
" var $b;"
"};"
"$obj = new A();"
"var_dump($obj);"
"foreach ($obj as &$value) {"
" $value = 1;"
"}"
"var_dump($obj);"
"$obj->c = 3;"
"var_dump($obj);"
"foreach ($obj as &$value) {"
" $value = 2;"
"}"
"var_dump($obj);");
MVCRO("<?php "
"class A {"
" var $a;"
" var $b;"
"};"
"function gen() {"
" $obj = new A();"
" var_dump($obj);"
" foreach ($obj as &$value) {"
" yield null;"
" $value = 1;"
" }"
" var_dump($obj);"
" $obj->c = 3;"
" var_dump($obj);"
" foreach ($obj as &$value) {"
" yield null;"
" $value = 2;"
" }"
" var_dump($obj);"
"}"
"foreach (gen() as $_) {}"
,
"object(A)#2 (2) {\n"
" [\"a\"]=>\n"
" NULL\n"
" [\"b\"]=>\n"
" NULL\n"
"}\n"
"object(A)#2 (2) {\n"
" [\"a\"]=>\n"
" int(1)\n"
" [\"b\"]=>\n"
" &int(1)\n"
"}\n"
"object(A)#2 (3) {\n"
" [\"a\"]=>\n"
" int(1)\n"
" [\"b\"]=>\n"
" &int(1)\n"
" [\"c\"]=>\n"
" int(3)\n"
"}\n"
"object(A)#2 (3) {\n"
" [\"a\"]=>\n"
" int(2)\n"
" [\"b\"]=>\n"
" int(2)\n"
" [\"c\"]=>\n"
" &int(2)\n"
"}\n"
);
MVCR("<?php "
"class A {"
" var $a;"
" var $b;"
"};"
"$obj = new A();"
"$obj2 = $obj;"
"foreach ($obj2 as $k => &$value) {"
" $value = 'ok';"
"}"
"var_dump($obj);"
"var_dump($obj2);");
MVCRO("<?php "
"class A {"
" var $a;"
" var $b;"
"};"
"function gen() {"
" $obj = new A();"
" $obj2 = $obj;"
" foreach ($obj2 as $k => &$value) {"
" yield null;"
" $value = 'ok';"
" }"
" var_dump($obj);"
" var_dump($obj2);"
"}"
"foreach (gen() as $_) {}"
,
"object(A)#2 (2) {\n"
" [\"a\"]=>\n"
" string(2) \"ok\"\n"
" [\"b\"]=>\n"
" &string(2) \"ok\"\n"
"}\n"
"object(A)#2 (2) {\n"
" [\"a\"]=>\n"
" string(2) \"ok\"\n"
" [\"b\"]=>\n"
" &string(2) \"ok\"\n"
"}\n"
);
MVCR("<?php "
"class A {"
" var $a;"
" var $b;"
" var $c;"
" var $d;"
" public function __construct($p1, $p2, $p3, $p4) {"
" $this->a = $p1;"
" $this->b = $p2;"
" $this->c = $p3;"
" $this->d = $p4;"
" }"
"};"
"$obj = new A(1, 2, 3, 4);"
"foreach ($obj as $key => &$val) {"
" if($val == 2) {"
" $obj->$key = 0;"
" } else if($val == 3) {"
" var_dump($key);"
" unset($obj->$key);"
" } else {"
" $val++;"
" }"
"}"
"var_dump($obj);");
MVCRO("<?php "
"class A {"
" var $a;"
" var $b;"
" var $c;"
" var $d;"
" public function __construct($p1, $p2, $p3, $p4) {"
" $this->a = $p1;"
" $this->b = $p2;"
" $this->c = $p3;"
" $this->d = $p4;"
" }"
"};"
"function gen() {"
" $obj = new A(1, 2, 3, 4);"
" foreach ($obj as $key => &$val) {"
" yield null;"
" if($val == 2) {"
" $obj->$key = 0;"
" } else if($val == 3) {"
" var_dump($key);"
" unset($obj->$key);"
" } else {"
" $val++;"
" }"
" }"
" var_dump($obj);"
"}"
"foreach (gen() as $_) {}"
,
"string(1) \"c\"\n"
"object(A)#2 (3) {\n"
" [\"a\"]=>\n"
" int(2)\n"
" [\"b\"]=>\n"
" int(0)\n"
" [\"d\"]=>\n"
" &int(5)\n"
"}\n"
);
MVCR("<?php "
"class A {"
" var $a = 1;"
" var $b = 2;"
" var $c = 3;"
" var $d = 4;"
" public function __construct() {"
" $this->a = 1;"
" $this->b = 2;"
" $this->c = 3;"
" $this->d = 4;"
" }"
"};"
"function f() {"
" $obj = new A();"
" foreach ($obj as $key => &$val) {"
" $val = 5;"
" }"
" var_dump($obj);"
"}"
"f();");
MVCRO("<?php "
"class A {"
" var $a = 1;"
" var $b = 2;"
" var $c = 3;"
" var $d = 4;"
" public function __construct() {"
" $this->a = 1;"
" $this->b = 2;"
" $this->c = 3;"
" $this->d = 4;"
" }"
"};"
"function f() {"
" $obj = new A();"
" foreach ($obj as $key => &$val) {"
" yield null;"
" $val = 5;"
" }"
" var_dump($obj);"
"}"
"foreach (f() as $_) {}"
,
"object(A)#2 (4) {\n"
" [\"a\"]=>\n"
" int(5)\n"
" [\"b\"]=>\n"
" int(5)\n"
" [\"c\"]=>\n"
" int(5)\n"
" [\"d\"]=>\n"
" &int(5)\n"
"}\n"
);
MVCR("<?php function test() {"
"$abc = 'abc'; var_dump($abc instanceof Nothing); }"
"test();");
MVCR("<?php "
"class X {"
" public $x = 1;"
" }"
"class Y {"
" public $x = array();"
"}"
"function test() {"
" $x = (object)new Y;"
" var_dump($x->x);"
" $x = new X;"
" var_dump($x->x);"
"}"
"test();");
MVCR("<?php\n"
"class A { }\n"
"class B extends A {\n"
" static function check1($a) { return $a instanceof self; }\n"
" static function check2($a) { return $a instanceof parent; }\n"
"}\n"
"$a = new B;\n"
"var_dump(B::check1($a), B::check2($a));\n"
"$b = (object)array(1, 2, 3);\n"
"var_dump(B::check1($b), B::check2($b));\n");
MVCR("<php\n"
"class X { static function f($o, $s) { return $o instanceof $s; } }\n"
"$x = new X;\n"
"var_dump(X::f($x, 'self'));\n"
"var_dump(X::f($x, 'X'));\n");
MVCR("<php\n"
"class X {\n"
" static function f($o) {\n"
" $s = 'self'; return $o instanceof $s;\n"
" }\n"
"}\n"
"X::f(new X);\n");
MVCR("<?php\n"
"$x = null;\n"
"$y = 0;\n"
"class C {\n"
" public $p = \"C::\\$p\";\n"
" function __destruct() {\n"
" global $x, $y;\n"
" print \"In C::__destruct(): $y\n\";\n"
" $this->p = \"changed\";\n"
" $x = $this;\n"
" }\n"
"}\n"
"$c = new C();\n"
"var_dump($c);\n"
"$c = null;\n"
"$y = 140;\n"
"var_dump($x);\n"
"$x = null;\n");
MVCR("<?php "
"class X {"
" function foo() { var_dump(__METHOD__); }"
" }"
"function foo($a) {"
" $x = null;"
" if ($a) $x = new X;"
" return $x;"
"}"
"function test($x, $a) {"
" $x = foo($a);"
" if ($x) {"
" $x->foo();"
" }"
"}"
"test(45, 0);"
"test(77, 1);");
MVCR("<?php\n"
"class FOo {\n"
" public function exclAIM() { echo \"FOo::exclAIM\\n\"; }\n"
" public function teST() { echo \"FOo::teST\\n\"; }\n"
" public function __CaLL($name, $args) {\n"
" echo \"FOo::\" . $name . \"\\n\";\n"
" }\n"
"}\n"
"class TesT {\n"
" public static function ExclAim() {\n"
" $obj = new fOO();\n"
" $obj->{__fUNCTION__} = 1;\n"
" $obj->{__cLASS__} = 2;\n"
" $obj->__FuNCTION__ = 3;\n"
" $obj->__ClASS__ = 4;\n"
" $obj->{__FUnCTION__}();\n"
" $obj->{__CLaSS__}();\n"
" $obj->__FUNcTION__();\n"
" $obj->__CLAsS__();\n"
" $arr = array();\n"
" foreach ($obj as $k => $v) {\n"
" $arr[$k] = $v;\n"
" }\n"
" ksort($arr);\n"
" var_dump($arr);\n"
" }\n"
"}\n"
"tEst::eXclaiM();\n");
return true;
}
bool TestCodeRun::TestObjectProperty() {
MVCR("<?php "
"class A { static protected $foo = 11; "
" function foo() { var_dump(A::$foo);}} "
"class B extends A { static public $foo;} "
"var_dump(B::$foo); B::$foo = 123; A::foo();");
MVCR("<?php "
"class A { static protected $foo = 11; } "
"class B extends A {} "
"class C extends B { static public $foo;} "
"var_dump(C::$foo); ");
MVCR("<?php "
"class A { static private $foo = 11; } "
"class B extends A {} "
"class C extends B { static public $foo;} "
"var_dump(C::$foo); ");
MVCR("<?php\n"
"class A {\n"
" public $a = 'apple';\n"
" public $b = 'banana';\n"
"}\n"
"\n"
"$old = new A;\n"
"unset($old->a);\n"
"var_dump($old);\n"
"\n"
"$new = new A;\n"
"unset($new->b);\n"
"var_dump($new);\n"
"\n"
"foreach ($new as $property => $value) {\n"
" $old->$property = $value;\n"
"}\n"
"var_dump($old->a);\n"
"var_dump($old->b);\n"
// We can't really maintain the same order as PHP does, even though we
// can move unset and reset properties to the back of the list, but
// then we can't really tell who's added back first if there are two :-(
//"var_dump($old);\n"
);
MVCR("<?php\n"
"class A {\n"
" public $a = 'apple';\n"
"}\n"
"$obj = new A;\n"
"var_dump(isset($obj->a), property_exists($obj, 'a'));\n"
"$obj->a = null;\n"
"var_dump(isset($obj->a), property_exists($obj, 'a'));\n"
"unset($obj->a);\n"
"var_dump(isset($obj->a), property_exists($obj, 'a'));\n"
"$obj->a = 123;\n"
"var_dump(isset($obj->a), property_exists($obj, 'a'));\n"
"$obj->a = null;\n"
"var_dump(isset($obj->a), property_exists($obj, 'a'));\n"
);
MVCR("<?php\n"
"class A {\n"
" private $prop = 'test';\n"
"\n"
" function __get($name) {\n"
" return $this->$name;\n"
" }}\n"
"\n"
"$obj = new A();\n"
"var_dump($obj->prop);\n"
);
MVCR("<?php "
"class A { public $a = 10; public function foo() { $this->a = 20;} } "
"class B extends A { public $a = 'test';} "
"$obj = new B(); $obj->foo(); var_dump($obj->a);");
MVCR("<?php "
"class A { public $a = null; }"
"class B extends A { public function foo() { var_dump($this->a);} } "
"class C extends B { public $a = 'test';} "
"$obj = new C(); $obj->foo();");
MVCR("<?php "
"$y = true;"
"define('foo', $y ? 1 : 0);"
"if (false) {"
" class redecClass {"
" }"
"} else {"
" final class redecClass {"
" const redecConst = foo;"
" const redecConst2 = 456;"
" public static $fx = foo;"
" }"
"}"
"class T {"
" const c = foo;"
" const c2 = redecClass::redecConst;"
" const c3 = redecClass::redecConst2;"
" public static $q = foo;"
" public static $n = 123;"
"}"
"class T2 {"
" const c = foo;"
" public static $q = foo;"
"}"
"class T3 {"
" const c = foo;"
"}"
"class normal {"
" const C = 1;"
" public static $xx = 123;"
"}"
"function test() {"
" var_dump(T::c);"
" var_dump(T::c2);"
" var_dump(T::c3);"
" var_dump(T::$q);"
" var_dump(T::$n);"
" var_dump(T2::c);"
" var_dump(T2::$q);"
" var_dump(T3::c);"
" var_dump(normal::C);"
" var_dump(normal::$xx);"
"}"
"test();");
MVCR("<?php "
"class c {"
" public $d = 'd';"
" private $e = 'e';"
" protected $f = 'f';"
" function t1($y) {"
" foreach ($y as $k => $v) {"
" var_dump($v);"
" }"
" }"
"}"
"class d extends c {"
" public $a = 'a';"
" private $b = 'b';"
" protected $c = 'c';"
" function t2($y) {"
" foreach ($this as $k => $v) {"
" var_dump($v);"
" }"
" foreach ($y as $k => $v) {"
" var_dump($v);"
" }"
" foreach ($y as $k => $v) {"
" var_dump($v);"
" }"
" }"
"}"
"$x = new d;"
"$x->surprise = 1;"
"$y = new d;"
"$y->shock = 2;"
"echo \"t2\n\";"
"$x->t2($y);"
"echo \"t1\n\";"
"$x->t1($y);"
"$z = new c;"
"echo \"t12\n\";"
"$z->t1($x);"
"foreach ($x as $k => $v) {"
" var_dump($v);"
"}");
MVCR("<?php "
"$one = array('cluster'=> 1, 'version'=>2);"
"var_dump(isset($one->cluster));"
"var_dump(empty($one->cluster));"
"$two = 'hello';"
"var_dump(isset($two->scalar));");
MVCR("<?php "
"function f() { return false; }"
"if (f()) { class A { } }"
"else { class A { static $a = 100; var $b = 1000; } }"
"class B { var $a = 1; static $b = array(1, 2, 3); }"
"$vars = get_class_vars('A'); asort($vars); var_dump($vars);"
"A::$a = 1;"
"$vars = get_class_vars('A'); asort($vars); var_dump($vars);"
"$vars = get_class_vars('B'); asort($vars); var_dump($vars);");
MVCR("<?php "
"if (true) {"
" class A {"
" var $a0;"
" static $a1 = 1;"
" static $a2 = 2;"
" }"
" class X {"
" var $x0;"
" static $x1 = 1;"
" static $x2 = 2;"
" }"
"} else {"
" class A {"
" var $a3;"
" static $a4 = 4;"
" static $a5 = 5;"
" }"
" class X {"
" var $y3;"
" static $y4 = 4;"
" static $y5 = 5;"
" }"
"}"
"class B extends A {"
" var $b0 = 3;"
" static $b1 = 4;"
" static $b2 = 5;"
"}"
"class Y extends X {"
" var $y0 = 3;"
" static $y1 = 4;"
" static $y2 = 5;"
"}"
"class C {"
" var $c0;"
" static $c1 = 1;"
" static $c2 = 2;"
"}"
"class Z {"
" var $z0;"
" static $z1 = 1;"
" static $z2 = 2;"
"}"
"$vars = get_class_vars('A'); asort($vars); var_dump($vars);"
"$vars = get_class_vars('B'); asort($vars); var_dump($vars);"
"$vars = get_class_vars('C'); asort($vars); var_dump($vars);"
"$vars = get_class_vars('X'); asort($vars); var_dump($vars);"
"$vars = get_class_vars('Y'); asort($vars); var_dump($vars);"
"$vars = get_class_vars('Z'); asort($vars); var_dump($vars);");
MVCR("<?php "
"class A {"
" private $pri = 'a-pri';"
" protected $pro = 'a-pro';"
" function bar() {"
" var_dump($this->pri);"
" $pri = $q ? 'zz' : 'p'.'ri';"
" var_dump($this->$pri);"
" }"
" function bar2() {"
" var_dump($this->pro);"
" }"
"}"
"class B extends A {"
" private $pri = 'b-pri';"
" function bar() {"
" parent::bar();"
" var_dump($this->pri);"
" }"
"}"
"$obj = new B(); $obj->bar();"
"class C extends B {"
" public $pri = 'c-pri';"
" public $pro = 'c-pro';"
" function bar2() {"
" parent::bar2();"
" var_dump($this->pro);"
" }"
"}"
"$obj = new C; $obj->bar(); $obj->bar2();"
"var_dump(serialize($obj));"
"class Base {"
" protected $pro = 1;"
" private $pri = 'base-pri';"
" function q0() {"
" var_dump($this->pri);"
" }"
"}"
""
"class R extends Base {"
" public $rpub = 1;"
" protected $pro = 2;"
" private $pri = 'r-pri';"
" function q() {"
" var_dump($this->pri);"
" }"
"}"
""
"class D extends R {"
" public $dpub = 'd';"
" protected $pro = 'pro';"
" private $pri = 'd-pri';"
" function qq() {"
" var_dump($this->pri);"
" }"
"}"
""
"class DD extends D {"
" private $pri = 'dd-pri';"
" function qqq() {"
" var_dump($this->pri);"
" }"
"}"
""
"if (false) {"
" class R{}"
"}"
"$d = new D;"
"$d->qq();"
"$d->q();"
"$d->q0();"
"$d = new DD;"
"$d->qqq();"
"$d->qq();"
"$d->q();"
"$d->q0();"
);
MVCR("<?php\n"
"class A { }\n"
"$a = new A();\n"
"$f = 20;\n"
"$a->$f = 100;\n"
"var_dump($a);\n"
"unset($a->$f);\n"
"var_dump($a);\n");
MVCR("<?php "
"class X {"
" public $x = 0;"
" function y($u,&$a) {"
" $a++;"
" }"
"};"
"if (0) { class X{} }"
"function f() {}"
"function test() {"
" $x = new X;"
" $x->y(f(),$x->x);"
" var_dump($x);"
" $x->y(0,$x->x);"
" var_dump($x);"
"}"
"test();");
MVCR("<?php "
"class A {"
" private $a = array('apple');"
" private $b = 'banana';"
" function foo() {"
" $b = new A();"
" unset($b->b);"
" var_dump($b);"
" foreach ($b as $prop => $value) {"
" var_dump($prop);"
" }"
" }"
"}"
"A::foo();");
MVCR("<?php "
"class X {"
" public $pub_var = null;"
" public $pub_set = array();"
" private $priv_var = 2;"
" function __get($name) {"
" echo 'get: '; var_dump($name); return $name == 'buz' ? 1 : array();"
" }"
" function __isset($name) {"
" echo 'isset: '; var_dump($name);"
" return $name == 'baz' || $name == 'buz';"
" }"
"}"
"$x = new X;"
"var_dump(isset($x->foo));"
"var_dump(isset($x->baz));"
"var_dump(isset($x->buz));"
"var_dump(isset($x->pub_var));"
"var_dump(isset($x->pub_set));"
"var_dump(isset($x->priv_var));"
"var_dump(empty($x->foo));"
"var_dump(empty($x->baz));"
"var_dump(empty($x->buz));"
"var_dump(empty($x->pub_var));"
"var_dump(empty($x->pub_set));"
"var_dump(empty($x->priv_var));"
"unset($x->pub_var);"
"var_dump(isset($x->pub_var));"
"var_dump(empty($x->pub_var));");
MVCR("<?php "
"define('FOO', 'foo');"
"class X {"
" const UNKNOWN = 1;"
" public $foo = -1;"
" static public $bar = FOO;"
" public $baz = self::UNKNOWN;"
"}"
"$vars = get_class_vars('X'); asort($vars); var_dump($vars);");
// Mutable object foreach needs to respect the context.
MVCR("<?php\n"
"class A { public $a = 1; protected $b = 2; private $c = 3; }\n"
"class B extends A {\n"
" function f() {\n"
" foreach ($this as $k => &$v) { var_dump($k); $v = 100; }\n"
" var_dump($this);\n"
" }\n"
"}\n"
"$b = new B();\n"
"$b->f();\n"
"function f() {\n"
" $o = new B();\n"
" foreach ($o as $k => &$v) { var_dump($k); $v = 100; }\n"
" var_dump($o);\n"
"}\n"
"f();\n");
// empty property name shouldn't crash
MVCR("<?php\n"
"$a = array(); $a[""] = 1;\n"
"$o = (object)$a;\n"
"var_dump($o);\n"
"$s = serialize($o);\n"
"$o2 = unserialize($s);\n");
MVCR("<?php "
"class Test"
"{"
" protected static $color = array('gray' => 30);"
" public static function foo($type, $key) {"
" return isset( self::${$type}[$key] );"
" }"
"}"
"var_dump(Test::foo('color', 'gray'));");
MVCR("<?php "
"function foo() {"
" $x = new stdClass;"
" $x->v = array(1, 2);"
" return $x;"
"}"
"foo()->v[0] += 5;"
"var_dump(shuffle(foo()->v));");
MVCR("<?php "
"class A {}"
"class B {"
" public $data;"
" public function setData(A $result = null) {"
" $this->data = $result;"
" }"
"}"
"function foo($obj) {"
" $obj->data = new A;"
" $a = $obj->data;"
" var_dump($a);"
" $obj->setData(null);"
" $a = $obj->data;"
" var_dump($a);"
"}"
"foo(new B);");
MVCR("<?php "
"class X {"
" function __destruct() { var_dump(__METHOD__); }"
" protected $prot_over_prot = 1;"
" public $pub_over_pub = 2;"
" protected $pub_over_prot = 3;"
"}"
"class Y extends X {"
" function __destruct() { var_dump(__METHOD__,$this); }"
" protected $prot_over_prot = 4;"
" public $pub_over_pub = 5;"
" public $pub_over_prot = 6;"
" protected $prot_base = 7;"
" public $pub_base = 8;"
"}"
"class Z extends Y {"
" function __destruct() { var_dump(__METHOD__); }"
" public $prot_over_prot = 9;"
" public $pub_over_pub = 10;"
" public $pub_over_prot = 11;"
" public $prot_base = 12;"
" public $pub_base = 13;"
"}"
"function foo($x) {"
" $s = serialize($x);"
" var_dump($s);"
" $y = unserialize($s);"
" var_dump($y);"
" var_dump((array)$y);"
" if (function_exists('apc_store')) {"
" apc_store('foo', $y);"
" $z = apc_fetch('foo');"
" } else {"
" $z = clone $y;"
" }"
" var_dump($z);"
" unset($z, $y);"
" var_dump($x);"
"}"
"$y = new y;"
"foo($y);"
"$z = new z;"
"foo($z);"
"unset($z, $y);");
MVCR("<?php "
"class X {"
" private $b = false;"
" private $i = 0;"
" private $a = array();"
" private $s = 'hello';"
" function set() {"
" $this->b = true;"
" $this->i = 5;"
" $this->a = array(1,2,3);"
" $this->s = 'goodbye';"
" }"
" function foo() {"
" var_dump($this->b, $this->i, $this->a, $this->s);"
" }"
"}"
"function test() {"
" $x = new X;"
" $x->set();"
" $s = serialize($x);"
" $y = unserialize($s);"
" $y->foo();"
" var_dump($y);"
"}"
"test();");
MVCR("<?php "
"define('INIT1', 1000);"
"class d { static public $x = INIT1; }"
"class e extends d {}"
"var_dump(d::$x++);"
"var_dump(e::$x++);");
MVCR("<?php "
"function test($x, $v) { var_dump(isset($x->$v)); }"
"test(false, \"\");"
"test(false, \"\\0foo\");"
"test(true, \"\");"
"test(true, \"\\0foo\");"
"test(new stdclass, \"\");"
"test(new stdclass, \"\\0foo\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v); }"
"test(false, \"\");"
"test(false, \"\\0foo\");"
"test(true, \"\");"
"test(true, \"\\0foo\");"
"test(new stdclass, \"\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v); }"
"test(new stdclass, \"\\0foo\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v = 1); }"
"test(true, \"\");"
"test(true, \"\\0foo\");"
"test(false, \"\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v = 1); }"
"test(false, \"\\0foo\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v = 1); }"
"test(new stdclass, \"\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v = 1); }"
"test(new stdclass, \"\\0foo\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v++); }"
"test(true, \"\");"
"test(true, \"\\0foo\");"
"test(false, \"\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v++); }"
"test(false, \"\\0foo\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v++); }"
"test(new stdclass, \"\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v++); }"
"test(new stdclass, \"\\0foo\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v += 1); }"
"test(true, \"\");"
"test(true, \"\\0foo\");"
"test(false, \"\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v += 1); }"
"test(false, \"\\0foo\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v += 1); }"
"test(new stdclass, \"\");");
MVCRNW("<?php "
"function test($x, $v) { var_dump($x->$v += 1); }"
"test(new stdclass, \"\\0foo\");");
MVCRNW("<?php "
"function test($x, $v) { unset($x->$v); var_dump($x); }"
"test(false, \"\");"
"test(false, \"\\0foo\");"
"test(true, \"\");"
"test(true, \"\\0foo\");"
"test(new stdclass, \"\");");
MVCRNW("<?php "
"function test($x, $v) { unset($x->$v); var_dump($x); }"
"test(new stdclass, \"\\0foo\");");
MVCRNW("<?php "
"$x = new stdclass;"
"var_dump($z =& $x->$y);");
MVCRNW("<?php "
"$x = new stdclass;"
"var_dump($x->$y =& $z);");
MVCR("<?php "
"class X {"
" public $bar = 5;"
" function &foo() { static $v; if (!$v) $v = $this; return $v; }"
"}"
"function &foo() {"
" static $v;"
" if (!$v) $v = new X;"
" return $v;"
"}"
"function &bar() {"
" static $v;"
" return $v;"
"}"
"function test() {"
" $x = new X;"
" var_dump($x->foo()->bar);"
" var_dump($x->foo()->bar);"
" var_dump($x->foo()->bar);"
" var_dump(foo()->bar);"
" foo()->bar = 6;"
" var_dump(foo()->bar);"
" foo()->bar = 7;"
" var_dump(foo()->bar);"
" foo()->bar = 8;"
" var_dump(foo()->bar);"
" bar()->bar = 6;"
" var_dump(bar()->bar);"
" bar()->bar = 7;"
" var_dump(bar()->bar);"
" bar()->bar = 8;"
" var_dump(bar()->bar);"
"}"
"test();");
return true;
}
bool TestCodeRun::TestObjectMethod() {
MVCR("<?php class A { function test() {}} "
"$obj = new A(); $obj->test(); $obj = 1;");
// calling a function that's implemented in a derived class
MVCR("<?php abstract class T { function foo() { $this->test();} }"
"class R extends T { function test() { var_dump('test'); }} "
"$obj = new R(); $obj->test(); $obj->foo();");
MVCR("<?php class A { function test() { print 'A';} "
"function foo() { $this->test();}} "
"class B extends A { function test() { print 'B';}} "
"$obj = new A(); $obj = new B(); $obj->foo();");
MVCR("<?php "
"class A {} "
"class AA extends A { function test() { print 'AA ok';} }"
"class B { function foo(A $obj) { $obj->test();}}"
"$obj = new AA(); $b = new B(); $b->foo($obj);"
);
// calling a virtual function
MVCR("<?php abstract class T { abstract function test(); "
"function foo() { $this->test();} }"
"class R extends T { function test() { var_dump('test'); }} "
"$obj = new R(); $obj->test(); $obj->foo();");
// calling a virtual function
MVCR("<?php abstract class T { abstract function test(); } "
"class R extends T { function test() { var_dump('test'); }} "
"$obj = 1; $obj = new R(); $obj->test();");
MVCR("<?php "
"class foo {"
" public function test1() {"
" echo 'in test1';"
" }"
" public function test2() {"
" self::test1();"
" foo::test1();"
" echo 'in test2';"
" }"
" public function test3() {"
" echo 'in test3';"
" }"
" public static function test4() {"
" echo 'in test4';"
" }"
"}"
"$obj = new foo();"
"$obj->test2();"
"foo::test1();"
"foo::test2();"
"foo::test3();"
"$obj->test3();"
"$obj->test4();");
// calling instance method statically
MVCR("<?php "
"class A1 {"
" function a1f($a) {"
" var_dump('a1f:0');"
" }"
" static function a1b($a) {"
" var_dump('a1b:0');"
" }"
"}"
"class B1 extends A1 {"
" function b1f($a) {"
" var_dump('b1f:0');"
" }"
" static function b1b($a) {"
" var_dump('b1b:0');"
" }"
"}"
"$f = 'a1f';"
"$b = 'a1b';"
"A1::$f(1);"
"A1::$b(1);"
"B1::$f(1);"
"B1::$b(1);"
"$f = 'b1f';"
"$b = 'b1b';"
"B1::$f(1);"
"B1::$b(1);"
"$f = 'b2f';"
"$b = 'b2b';"
"call_user_func(array('B1', 'b1f'), 1);");
// calling instance method through self
MVCR("<?php "
"class A {"
" var $a;"
" function f() {"
" var_dump($this->a);"
" }"
" function g() {"
" $this->a = 100;"
" call_user_func(array('self', 'f'));"
" }"
"}");
MVCR("<?php "
"class c {"
"function foo() { echo \"called\n\"; }"
"}"
"function meh() {}"
"function z() {"
" $p = new c;"
" $p->foo(meh());"
" $p = null;"
"}"
"z();");
MVCR("<?php "
"interface intf {"
" function meth();"
"}"
"class m {"
" function meth() {"
" return 1;"
" }"
"}"
"class m2 extends m implements intf {"
"}"
"class m3 extends m2 {"
" function f() {"
" var_dump(parent::meth());"
" }"
"}"
"$y = new m3;"
"$y->f();"
"function g() {"
" $y = new m3;"
" var_dump($y->meth());"
"}"
"g();");
MVCR("<?php "
"class c {"
" function x() {"
" var_dump($this);"
" $t = 'this';"
" var_dump($$t);"
" }"
"}"
"$x = new c;"
"$x->x();");
MVCR("<?php "
"class RootBase {}"
"class Base extends RootBase {"
" private $privateData;"
"}"
"class Test extends Base {"
" protected function f1() {"
" $this->privateData = 1;"
" var_dump('ok');"
" }"
" public function f2() {"
" $this->f1();"
" }"
"}"
"function foo() {"
" $obj = new Test();"
" $obj->f2();"
" $obj->privateData = 2;"
" $obj = new Base();"
"}"
"foo();");
#define TEST_BODY_FOR_IS_CALLABLE \
"var_dump(is_callable('A::a_spub'));" \
"var_dump(is_callable('A::a_spro'));" \
"var_dump(is_callable('A::a_spri'));" \
"var_dump(is_callable('A::a_pro'));" \
"var_dump(is_callable('A::a_pri'));" \
"var_dump(is_callable('a_spub'));" \
"var_dump(is_callable('a_spro'));" \
"var_dump(is_callable('a_spri'));" \
"var_dump(is_callable('a_pub'));" \
"var_dump(is_callable('a_pro'));" \
"var_dump(is_callable('a_pri'));" \
"var_dump(is_callable('B::b_spub'));" \
"var_dump(is_callable('B::b_spro'));" \
"var_dump(is_callable('B::b_spri'));" \
"var_dump(is_callable('B::b_pro'));" \
"var_dump(is_callable('B::b_pri'));" \
"var_dump(is_callable('b_spub'));" \
"var_dump(is_callable('b_spro'));" \
"var_dump(is_callable('b_spri'));" \
"var_dump(is_callable('b_pub'));" \
"var_dump(is_callable('b_pro'));" \
"var_dump(is_callable('b_pri'));" \
"var_dump(is_callable(array('A', 'a_spub')));" \
"var_dump(is_callable(array('A', 'a_spro')));" \
"var_dump(is_callable(array('A', 'a_spri')));" \
"var_dump(is_callable(array('A', 'a_pub')));" \
"var_dump(is_callable(array('A', 'a_pro')));" \
"var_dump(is_callable(array('A', 'a_pri')));" \
"var_dump(is_callable(array('A', 'A::a_spub')));" \
"var_dump(is_callable(array('A', 'A::a_spro')));" \
"var_dump(is_callable(array('A', 'A::a_spri')));" \
"var_dump(is_callable(array('A', 'A::a_pro')));" \
"var_dump(is_callable(array('A', 'A::a_pri')));" \
"var_dump(is_callable(array('A', 'A::A::a_spub')));" \
"var_dump(is_callable(array('A', 'A::A::a_spro')));" \
"var_dump(is_callable(array('A', 'A::A::a_spri')));" \
"var_dump(is_callable(array('A', 'A::A::a_pro')));" \
"var_dump(is_callable(array('A', 'A::A::a_pri')));" \
"var_dump(is_callable(array('A', 'C::a_spub')));" \
"var_dump(is_callable(array('A', 'C::a_spro')));" \
"var_dump(is_callable(array('A', 'C::a_spri')));" \
"var_dump(is_callable(array('A', 'C::a_pub')));" \
"var_dump(is_callable(array('A', 'C::a_pro')));" \
"var_dump(is_callable(array('A', 'C::a_pri')));" \
"var_dump(is_callable(array('A', 'A::C::a_spub')));" \
"var_dump(is_callable(array('A', 'A::C::a_spro')));" \
"var_dump(is_callable(array('A', 'A::C::a_spri')));" \
"var_dump(is_callable(array('A', 'A::C::a_pub')));" \
"var_dump(is_callable(array('A', 'A::C::a_pro')));" \
"var_dump(is_callable(array('A', 'A::C::a_pri')));" \
"var_dump(is_callable(array('A', 'b_spub')));" \
"var_dump(is_callable(array('A', 'b_spro')));" \
"var_dump(is_callable(array('A', 'b_spri')));" \
"var_dump(is_callable(array('A', 'b_pub')));" \
"var_dump(is_callable(array('A', 'b_pro')));" \
"var_dump(is_callable(array('A', 'b_pri')));" \
"var_dump(is_callable(array('A', 'B::a_spub')));" \
"var_dump(is_callable(array('A', 'B::a_spro')));" \
"var_dump(is_callable(array('A', 'B::a_spri')));" \
"var_dump(is_callable(array('A', 'B::a_pub')));" \
"var_dump(is_callable(array('A', 'B::a_pro')));" \
"var_dump(is_callable(array('A', 'B::a_pri')));" \
"var_dump(is_callable(array('A', 'B::B::a_spub')));" \
"var_dump(is_callable(array('A', 'B::B::a_spro')));" \
"var_dump(is_callable(array('A', 'B::B::a_spri')));" \
"var_dump(is_callable(array('A', 'B::B::a_pub')));" \
"var_dump(is_callable(array('A', 'B::B::a_pro')));" \
"var_dump(is_callable(array('A', 'B::B::a_pri')));" \
"var_dump(is_callable(array('B', 'a_spub')));" \
"var_dump(is_callable(array('B', 'a_spro')));" \
"var_dump(is_callable(array('B', 'a_spri')));" \
"var_dump(is_callable(array('B', 'a_pub')));" \
"var_dump(is_callable(array('B', 'a_pro')));" \
"var_dump(is_callable(array('B', 'a_pri')));" \
"var_dump(is_callable(array('B', 'A::a_spub')));" \
"var_dump(is_callable(array('B', 'A::a_spro')));" \
"var_dump(is_callable(array('B', 'A::a_spri')));" \
"var_dump(is_callable(array('B', 'A::a_pro')));" \
"var_dump(is_callable(array('B', 'A::a_pri')));" \
"var_dump(is_callable(array('B', 'A::A::a_spub')));" \
"var_dump(is_callable(array('B', 'A::A::a_spro')));" \
"var_dump(is_callable(array('B', 'A::A::a_spri')));" \
"var_dump(is_callable(array('B', 'A::A::a_pro')));" \
"var_dump(is_callable(array('B', 'A::A::a_pri')));" \
"var_dump(is_callable(array('B', 'C::a_spub')));" \
"var_dump(is_callable(array('B', 'C::a_spro')));" \
"var_dump(is_callable(array('B', 'C::a_spri')));" \
"var_dump(is_callable(array('B', 'C::a_pub')));" \
"var_dump(is_callable(array('B', 'C::a_pro')));" \
"var_dump(is_callable(array('B', 'C::a_pri')));" \
"var_dump(is_callable(array('B', 'B::C::a_spub')));" \
"var_dump(is_callable(array('B', 'B::C::a_spro')));" \
"var_dump(is_callable(array('B', 'B::C::a_spri')));" \
"var_dump(is_callable(array('B', 'B::C::a_pub')));" \
"var_dump(is_callable(array('B', 'B::C::a_pro')));" \
"var_dump(is_callable(array('B', 'B::C::a_pri')));" \
"var_dump(is_callable(array('B', 'b_spub')));" \
"var_dump(is_callable(array('B', 'b_spro')));" \
"var_dump(is_callable(array('B', 'b_spri')));" \
"var_dump(is_callable(array('B', 'b_pub')));" \
"var_dump(is_callable(array('B', 'b_pro')));" \
"var_dump(is_callable(array('B', 'b_pri')));" \
"var_dump(is_callable(array('B', 'B::a_spub')));" \
"var_dump(is_callable(array('B', 'B::a_spro')));" \
"var_dump(is_callable(array('B', 'B::a_spri')));" \
"var_dump(is_callable(array('B', 'B::a_pub')));" \
"var_dump(is_callable(array('B', 'B::a_pro')));" \
"var_dump(is_callable(array('B', 'B::a_pri')));" \
"var_dump(is_callable(array('B', 'B::A::a_spub')));" \
"var_dump(is_callable(array('B', 'B::A::a_spro')));" \
"var_dump(is_callable(array('B', 'B::A::a_spri')));" \
"var_dump(is_callable(array('B', 'B::A::a_pro')));" \
"var_dump(is_callable(array('B', 'B::A::a_pri')));" \
"var_dump(is_callable(array('B', 'B::B::a_spub')));" \
"var_dump(is_callable(array('B', 'B::B::a_spro')));" \
"var_dump(is_callable(array('B', 'B::B::a_spri')));" \
"var_dump(is_callable(array('B', 'B::B::a_pub')));" \
"var_dump(is_callable(array('B', 'B::B::a_pro')));" \
"var_dump(is_callable(array('B', 'B::B::a_pri')));" \
"var_dump(is_callable(array(new A(), 'a_spub')));" \
"var_dump(is_callable(array(new A(), 'a_spro')));" \
"var_dump(is_callable(array(new A(), 'a_spri')));" \
"var_dump(is_callable(array(new A(), 'a_pub')));" \
"var_dump(is_callable(array(new A(), 'a_pro')));" \
"var_dump(is_callable(array(new A(), 'a_pri')));" \
"var_dump(is_callable(array(new A(), 'A::a_spub')));" \
"var_dump(is_callable(array(new A(), 'A::a_spro')));" \
"var_dump(is_callable(array(new A(), 'A::a_spri')));" \
"var_dump(is_callable(array(new A(), 'A::a_pro')));" \
"var_dump(is_callable(array(new A(), 'A::a_pri')));" \
"var_dump(is_callable(array(new A(), 'A::A::a_spub')));" \
"var_dump(is_callable(array(new A(), 'A::A::a_spro')));" \
"var_dump(is_callable(array(new A(), 'A::A::a_spri')));" \
"var_dump(is_callable(array(new A(), 'A::A::a_pro')));" \
"var_dump(is_callable(array(new A(), 'A::A::a_pri')));" \
"var_dump(is_callable(array(new A(), 'C::a_spub')));" \
"var_dump(is_callable(array(new A(), 'C::a_spro')));" \
"var_dump(is_callable(array(new A(), 'C::a_spri')));" \
"var_dump(is_callable(array(new A(), 'C::a_pub')));" \
"var_dump(is_callable(array(new A(), 'C::a_pro')));" \
"var_dump(is_callable(array(new A(), 'C::a_pri')));" \
"var_dump(is_callable(array(new A(), 'A::C::a_spub')));" \
"var_dump(is_callable(array(new A(), 'A::C::a_spro')));" \
"var_dump(is_callable(array(new A(), 'A::C::a_spri')));" \
"var_dump(is_callable(array(new A(), 'A::C::a_pub')));" \
"var_dump(is_callable(array(new A(), 'A::C::a_pro')));" \
"var_dump(is_callable(array(new A(), 'A::C::a_pri')));" \
"var_dump(is_callable(array(new A(), 'b_spub')));" \
"var_dump(is_callable(array(new A(), 'b_spro')));" \
"var_dump(is_callable(array(new A(), 'b_spri')));" \
"var_dump(is_callable(array(new A(), 'b_pub')));" \
"var_dump(is_callable(array(new A(), 'b_pro')));" \
"var_dump(is_callable(array(new A(), 'b_pri')));" \
"var_dump(is_callable(array(new A(), 'B::a_spub')));" \
"var_dump(is_callable(array(new A(), 'B::a_spro')));" \
"var_dump(is_callable(array(new A(), 'B::a_spri')));" \
"var_dump(is_callable(array(new A(), 'B::a_pub')));" \
"var_dump(is_callable(array(new A(), 'B::a_pro')));" \
"var_dump(is_callable(array(new A(), 'B::a_pri')));" \
"var_dump(is_callable(array(new A(), 'B::A::a_spub')));" \
"var_dump(is_callable(array(new A(), 'B::A::a_spro')));" \
"var_dump(is_callable(array(new A(), 'B::A::a_spri')));" \
"var_dump(is_callable(array(new A(), 'B::A::a_pro')));" \
"var_dump(is_callable(array(new A(), 'B::A::a_pri')));" \
"var_dump(is_callable(array(new B(), 'b_spub')));" \
"var_dump(is_callable(array(new B(), 'b_spro')));" \
"var_dump(is_callable(array(new B(), 'b_spri')));" \
"var_dump(is_callable(array(new B(), 'b_pub')));" \
"var_dump(is_callable(array(new B(), 'b_pro')));" \
"var_dump(is_callable(array(new B(), 'b_pri')));" \
"var_dump(is_callable(array(new B(), 'B::b_spub')));" \
"var_dump(is_callable(array(new B(), 'B::b_spro')));" \
"var_dump(is_callable(array(new B(), 'B::b_spri')));" \
"var_dump(is_callable(array(new B(), 'B::b_pro')));" \
"var_dump(is_callable(array(new B(), 'B::b_pri')));" \
"var_dump(is_callable(array(new B(), 'B::B::b_spub')));" \
"var_dump(is_callable(array(new B(), 'B::B::b_spro')));" \
"var_dump(is_callable(array(new B(), 'B::B::b_spri')));" \
"var_dump(is_callable(array(new B(), 'B::B::b_pro')));" \
"var_dump(is_callable(array(new B(), 'B::B::b_pri')));" \
"var_dump(is_callable(array(new B(), 'C::b_spub')));" \
"var_dump(is_callable(array(new B(), 'C::b_spro')));" \
"var_dump(is_callable(array(new B(), 'C::b_spri')));" \
"var_dump(is_callable(array(new B(), 'C::b_pub')));" \
"var_dump(is_callable(array(new B(), 'C::b_pro')));" \
"var_dump(is_callable(array(new B(), 'C::b_pri')));" \
"var_dump(is_callable(array(new B(), 'B::C::b_spub')));" \
"var_dump(is_callable(array(new B(), 'B::C::b_spro')));" \
"var_dump(is_callable(array(new B(), 'B::C::b_spri')));" \
"var_dump(is_callable(array(new B(), 'B::C::b_pub')));" \
"var_dump(is_callable(array(new B(), 'B::C::b_pro')));" \
"var_dump(is_callable(array(new B(), 'B::C::b_pri')));" \
"var_dump(is_callable(array(new B(), 'a_spub')));" \
"var_dump(is_callable(array(new B(), 'a_spro')));" \
"var_dump(is_callable(array(new B(), 'a_spri')));" \
"var_dump(is_callable(array(new B(), 'a_pub')));" \
"var_dump(is_callable(array(new B(), 'a_pro')));" \
"var_dump(is_callable(array(new B(), 'a_pri')));" \
"var_dump(is_callable(array(new B(), 'A::B::b_spub')));" \
"var_dump(is_callable(array(new B(), 'A::B::b_spro')));" \
"var_dump(is_callable(array(new B(), 'A::B::b_spri')));" \
"var_dump(is_callable(array(new B(), 'A::B::b_pro')));" \
"var_dump(is_callable(array(new B(), 'A::B::b_pri')));" \
MVCRNW("<?php "
"function test() {"
TEST_BODY_FOR_IS_CALLABLE
"}"
"class EXT {"
" static public function ext_spub() {"
" test();"
TEST_BODY_FOR_IS_CALLABLE
" }"
"}"
"class A {"
" static public function a_spub() {"
" test();"
" }"
" static protected function a_spro() {"
" test();"
" }"
" static private function a_spri() {"
" test();"
" }"
" public function a_pub() {"
" test();"
" }"
" protected function a_pro() {"
" test();"
" }"
" private function a_pri() {"
" test();"
" }"
" public static function a_sf() {"
" test();"
" self::a_spub();"
" self::a_spro();"
" self::a_spri();"
" self::a_pub();"
" self::a_pro();"
" self::a_pri();"
" }"
" public function a_f() {"
" test();"
" self::a_spub();"
" self::a_spro();"
" self::a_spri();"
" self::a_pub();"
" self::a_pro();"
" self::a_pri();"
" }"
"};"
"class B extends A {"
" static public function b_spub() {"
" test();"
" }"
" static protected function b_spro() {"
" test();"
" }"
" static private function b_spri() {"
" test();"
" }"
" public function b_pub() {"
" test();"
" }"
" protected function b_pro() {"
" test();"
" }"
" private function b_pri() {"
" test();"
" }"
" public static function b_sf() {"
" test();"
" self::b_spub();"
" self::b_spro();"
" self::b_spri();"
" self::b_pub();"
" self::b_pro();"
" self::b_pri();"
" }"
" public function b_f() {"
" test();"
" self::b_spub();"
" self::b_spro();"
" self::b_spri();"
" self::b_pub();"
" self::b_pro();"
" self::b_pri();"
" }"
"}"
"EXT::ext_spub();"
"test();"
TEST_BODY_FOR_IS_CALLABLE
"var_dump(is_callable('A::b_spub'));"
"var_dump(is_callable('A::b_spro'));"
"var_dump(is_callable('A::b_spri'));"
"var_dump(is_callable('A::b_pub'));"
"var_dump(is_callable('A::b_pro'));"
"var_dump(is_callable('A::b_pri'));"
"B::a_sf();"
"B::b_sf();"
"$obj = new B;"
"$obj->a_sf();"
"$obj->b_sf();"
"$obj->a_f();"
"$obj->b_f();");
MVCR("<?php "
"function foo() { echo 'Caught'; exit; }"
"set_error_handler('foo', E_ALL);"
"class X { function foo() { var_dump($this); } }"
"class Y {"
" function bar(X $a) { $a->foo(); }"
"}"
"function test($y,$z) {"
" $y->$z($y);"
"}"
"test(new Y, 'bar');");
MVCR("<?php\n"
"/*\n"
" some random tests used for debugging fast method call and various "
" invoke paths\n"
" // php53 means this feature cannot be tested under php 5.2\n"
"*/\n"
"\n"
"$fix249639=0; // when this task is fixed or o_id on static calls\n"
"\n"
"global $trace;\n"
"function f2 ($a) { return $a+200; }\n"
"function f4 ($a) { return $a+400; }\n"
"class B {\n"
" public $id;\n"
" public $x;\n"
" function __call($name, $arguments) {\n"
" // keep f4bogus from fatalling\n"
" echo \"Calling B object method '$name' \" . implode(', ', "
"$arguments). \"\\n\";\n"
" }\n"
"\n"
" function f1($a) { return $x=$a+11; }\n"
" function f2($a) { return $x=$a+12; }\n"
" function f4($a) { return $x=$a+12; }\n"
" function trace($s) { global $trace; $trace = \"<$s(\"."
"$this->id.\")>\"; }\n"
" private function f4helper($a) { return $x=$a+12; }\n"
"}\n"
"class G extends B {\n"
" public $pointless;\n"
" function __call($name, $arguments) {\n"
" // keep f4bogus from fatalling\n"
" echo \"Calling G object method '$name' \" . "
"implode(', ', $arguments). \"\\n\";\n"
" }\n"
" function __construct($i) { $this->id=$i; }\n"
" function f($a) { $this->trace(\"G::f\"); return $a; }\n"
" function f1($a) { return $a; } // override\n"
" function flongerthan8($a,$b,$c) { return $a+$b+$c+1; }\n"
" function f4($a) { return B::f4($a); } \n"
" // check SimpleFunctionCall::outputCPPParamOrderControlled\n"
" /// !m_valid, !m_className.empty() case\n"
" // called method must not exist anywhere even though it\n"
" // looks like it might\n"
" function f4missing($a) { \n"
" // check SimpleFunctionCall::outputCPPParamOrderControlled\n"
" // !m_valid, !m_className.empty() cases\n"
"\n"
" // m_validClass \n"
" echo \"Calling G object 'f4missing' 3 == \"; \n"
" //php53 echo parent::f4missing(3),\"\\n\"; // fatals in PHP\n"
"\n"
" // !m_validClass, m_class\n"
" $b=\"B\"; // $b::f4(4); // task 217171\n"
" echo \"static parent method B::f4, 16 == \", B::f4(4),\"\\n\"; "
" // should work\n"
" \n"
" // call an non-existant method on the one object via dynamic "
"class name\n"
" //php53 if($fix249639) echo \"Calling G object method 'f4bogus' "
"5 == \", $b::f4bogus(5); __call, \n"
" // call existing method on the one object via dynamic class name\n"
" //php53 if($fix249639) echo \"Calling G object method 'f4missing' "
"5 == \", $b::f4missing(5); \n"
" // $b=\"Bbogus\"; $b::f4bogus(6); // report error\n"
" // !m_validClass, !m_class // DDD need this test yet \n"
" //echo \"missing 3 \", Bbogus::f4bogus(6),\"\\n\"; "
"// fatals in PHP\n"
"\n"
" } \n"
" function f5($a) { return H::f4($a); } // static call\n"
"}\n"
"class H {\n"
" function f($a) { global $trace; $trace=\"H::f,\"; return \"\"; }\n"
" function f3($a) { return \"\"; }\n"
" function f4($a) { return $a+12; }\n"
" function f7($a) { return \"\"; }\n"
"}\n"
"\n"
"class J {\n"
" function __call($name, $arguments) {\n"
" echo \"Calling object method '$name' \" . implode(', ', "
"$arguments). \"\\n\";\n"
" }\n"
" function f6($a) { return \"\"; }\n"
"}\n"
"\n"
"function error_handler ($errnor, $errstr, $errfile, $errline) {\n"
" // Should catch these undefined methods here, but task 333319\n"
" // is blocking their being caught. For now, suppress the PHP error\n"
" // so as to match the missing HPHP one.\n"
" //echo \"error handler<<<\\n\";\n"
" //var_dump($errnor, $errstr, $errfile, $errline) ;\n"
" //echo \">>>\\n\";\n"
" return true;\n"
"}\n"
"// test invoke_builtin_static_method\n"
"//echo \"bar == \", \n"
" // call_user_func_array(array('Normalizer','normalize'),"
"array(\"bar\")), \"\\n\";\n"
"\n"
"$g = new G(5);\n"
"// test simple function case\n"
"echo \"600 == \",\n"
" call_user_func_array('f2',array(call_user_func_array('f4',array(0))))"
", "
"\"\\n\";\n"
"\n"
"// test C::o_invoke, C::o_invoke_few_args, lookup in call_user_func\n"
"// static method call (in G::f4).\n"
"echo \"1 1 13 34 12 == \",$g->f(1),\" \", $g->f1(1),\" \", \n"
" $g->f2(1),\" \",$g->flongerthan8(10,11,12,13,14,15,16),\n"
" \" \",$g->f4(0),\"\\n\";\n"
"// check case insensitive\n"
"echo \"1 1 13 34 12 == \",$g->F(1),\" \", $g->F1(1),\" \", \n"
" $g->F2(1),\" \",$g->Flongerthan8(10,11,12,13,14,15,16),\n"
" \" \",$g->F4(0),\"\\n\";\n"
"\n"
"// check SimpleFunctionCall::outputCPPParamOrderControlled\n"
"$prev_handler=set_error_handler(\"error_handler\");\n"
"$g->f4missing(3);\n"
"// $b=\"G\"; $b::f4(4); \n"
"\n"
"// For those dynamic cases, check:\n"
"// 1) A call to an existing method\n"
"// 2) A call to a method which exists, but not in this class (exists "
"in methodMap)\n"
"// 3) A call to a method which does not exist anywhere\n"
"\n"
"// $func=\"f3\"; echo \"{G::f3}(3) = \",$g->$func(3),\"\\n\";\n"
"// $func=\"missing\"; echo \"{G::missing}(3) = \",$g->$func(3),\"\\n\";"
"\n"
"// tests direct dynamic call \n"
"$f='f'; $f1='f1';\n"
"echo \"1 1 == \",$g->{$f}(1),\" \", $g->{$f1}(1),\"\\n\"; \n"
"echo \"1 1 == \",$g->{'F'}(1),\" \", $g->{$f1}(1),\"\\n\"; \n"
"\n"
"$res = call_user_func_array(\"H::f\",array(2)); // ok\n"
"\n"
"// tests methodIndexLookup and this variety of dynamic calls\n"
"// trying to exhause f_call_user_func_array cases\n"
"$res = call_user_func_array(array($g,'f'),array(20)); // ok\n"
"echo \"dynamic call \\$g->'f' $trace, 20 == $res\\n\"; \n"
"$res= call_user_func_array(array($g,'G::f'),array(21)); // G::G::f a "
"bit wierd\n"
"echo \"dynamic call \\$g->'G::f' $trace, 21 == $res\\n\";\n"
"//echo \"dynamic call \\$g->'H::f' $trace, FAIL = \",\n"
"// call_user_func_array(array($g,'H::f'),array(22)),\"\\n\"; "
"// G::H::f better break\n"
"\n"
"// Test on static class, dynamic method name, static call\n"
"$f = 'f1';\n"
"echo \"31 == \",G::$f(31),\"\\n\"; // G::f exists\n"
"$f = 'f3';\n"
"if ($fix249639) echo \"<method not found>(32) == \",G::$f(32),\"\\n\"; "
"// H::f3 exists, but not G::f3\n"
"$f = 'missing';\n"
"if ($fix249639) echo \"<method not found>(33) == \",G::$f(33),\"\\n\"; "
"// missing does not exist \n"
"\n"
"// Test dynamic class, dynamic method name, static call\n"
"$cls='G';\n"
"$f = 'f1';\n"
"\n"
"//php53 echo \"31 == \",$cls::$f(31),\"\\n\"; // G::f1 exists\n"
"$f = 'f3';\n"
"//php53 if ($fix249639) echo \"<method not found>(32) == \","
"$cls::$f(32),\"\\n\"; // H::f3 exists, but not G::f3\n"
"$f = 'missing';\n"
"//php53 if ($fix249639) echo \"<method not found>(33) == \","
"$cls::$f(33),\"\\n\"; // missing does not exist \n"
"\n"
"\n"
"// test methodIndexLookupReverse\n"
"echo \"dynamic call \\$g->'missing' $trace, Calling G object method "
"'missing' 2 = \", call_user_func_array(array($g,'missing'),"
"array(2)),\"\\n\";\n"
"echo \"dynamic call 'missing(2)' $trace, FAIL =\", "
"call_user_func_array('missing',array(2)),\"\\n\";\n"
"\n"
"// more __call testing\n"
"$j = new J();\n"
"echo \"Calling object method 'missing' 3 = \";\n"
"call_user_func_array(array($j,'missing'),array(3)); \n"
"\n"
"// test mapping for system function names\n"
"$ourFileName = \"testFile.txt\";\n"
"$ourFileHandle = fopen($ourFileName, 'w') or die(\"can't open file\");\n"
"fclose($ourFileHandle);\n"
"unlink($ourFileName);\n"
"\n"
"echo \"done\\n\";");
MVCR("<?php "
"class B {"
" public function foo() {"
" $this->bar();"
" }"
" private function bar() {"
" var_dump('in B::bar...');"
" }"
"}"
"class C extends B {"
" private function bar() {"
" var_dump('in C::bar!');"
" }"
"}"
"$obj = new C;"
"$obj->foo();");
return true;
}
bool TestCodeRun::TestClassMethod() {
MVCR(
"<?php\n"
"class Foo {\n"
" static function Bar() {\n"
" if (isset($this) && isset($this->bar)) {\n"
" echo \"isset\\n\";\n"
" }\n"
" var_dump($this);\n"
" }\n"
"} Foo::Bar(); $obj = new Foo(); $obj->Bar();\n"
);
MVCR(
"<?php\n"
"class Example {\n"
" function whatever() {\n"
" if (isset($this)) {\n"
" var_dump('static method call');\n"
" } else {\n"
" var_dump('non-static method call');\n"
" }\n"
" }\n"
"}\n"
"Example::whatever();\n"
"$inst = new Example();\n"
"$inst->whatever();\n"
);
MVCR("<?php\n"
"if (true) {\n"
" class c extends AppendIterator {}\n"
"} else {\n"
" class c {}\n"
"}\n"
"class d extends c {\n"
" public function rewind() {\n"
" var_dump('rewinding');\n"
" }\n"
"}\n"
"$obj = new d;\n"
"foreach ($obj as $k => $v) {}\n");
MVCR("<?php "
"$error = 'fatal error';"
"echo AdsConsoleRenderer::getInstance()->writeMsg('error', $error);"
"class AdsConsoleRenderer {"
" public static function getInstance() {"
" return new AdsConsoleRenderer();"
" }"
""
" function writeMsg($classname = '', $s = '') {"
" echo $classname . \"::\" . $s;"
" }"
"}");
MVCR("<?php class A { "
" function f() { return \"hello\" ;}"
"}; "
"$g = new A(); echo $g->{'f'}();");
MVCR("<?php "
"$a = 'self';"
"class A {"
" public static function f($value) {"
" $filter = 'g';"
" return call_user_func(array($GLOBALS['a'], $filter), $value);"
" }"
" public static function g($value) {"
" return $value;"
" }"
"}"
"var_dump(A::f('test'));");
MVCRO("<?php "
"interface I {"
" public function foo($x);"
"}"
"abstract class B implements I {"
" abstract public function foo($x);"
"}"
"class C extends B {"
" public function foo($x){ echo \"$x \\n\";}"
"}"
"$obj = new C;"
"$obj->foo(1);",
"1 \n");
MVCR("<?php"
"class AB {"
" static function foo() {"
" var_dump('foo');"
" }"
"}"
"function f($x) {"
" $a = $x.'B';"
" $a::foo();"
"}"
"f('A');");
return true;
}
bool TestCodeRun::TestObjectMagicMethod() {
MVCR("<?php\n"
"class Test {\n"
" public function __call($name, $args) {\n"
" var_dump($args);\n"
" }\n"
"}\n"
"$test = new Test();\n"
"$test->test();\n"
);
MVCR("<?php class A {"
" private $foo, $bar; "
" function __construct() { $this->foo = 1; $this->bar = 2;} "
" public function __sleep() { $this->foo = 3; return array('foo');} "
"}"
" $a = new A(); var_dump(serialize($a));");
MVCR("<?php class A { "
" public $a = array(); "
" function __set($name, $value) { $this->a[$name] = $value.'set';} "
" function __get($name) { return $this->a[$name].'get';} "
"} "
"$obj = new A(); $obj->test = 'test'; var_dump($obj->test);");
MVCR("<?php "
"class A {"
" public $a = 'aaa';"
" public function __get($name) { return 'getA';}"
"}"
"class B extends A {"
" public function __get($name) { return 'getB';}"
"}"
"$obj = new A();"
"var_dump($obj->a);"
"var_dump($obj->b);"
"$obj = new B();"
"var_dump($obj->a);"
"var_dump($obj->b);");
MVCR("<?php class A { "
" public $a = array(); "
" function __set($name, $value) { $this->a[$name] = $value;} "
" function __get($name) { return $this->a[$name];} "
"} "
"$obj = new A(); $obj->test = 'test'; var_dump($obj->test);");
MVCR("<?php class A {} "
"$obj = new A(); $obj->test = 'test'; var_dump($obj->test);");
MVCR("<?php class A { "
"function __call($a, $b) { var_dump($a, $b[0], $b[1]);}} "
"$obj = new A(); $a = 1; $obj->test($a, 'ss');");
/*
MVCR("<?php class A { "
" function __set($name, $value) { $this->a[$name] = $value;} "
" function __get($name) { return $this->a[$name];} "
"} "
"$obj = new A(); $obj->test = 'test'; var_dump($obj->test);");
*/
MVCR("<?php "
"class foo"
"{"
" public $public = 'public';"
" public function __sleep()"
" { return array('public'); }"
"}"
"$foo = new foo();"
"$data = serialize($foo);"
"var_dump($data);");
MVCR("<?php "
"class MemberTest {"
" private $data = array();"
" public function __set($name, $value) {"
" echo \"Setting '$name' to '$value'\n\";"
" $this->data[$name] = $value;"
" }"
" public function __get($name) {"
" echo \"Getting '$name'\n\";"
" if (array_key_exists($name, $this->data)) {"
" return $this->data[$name];"
" }"
" return null;"
" }"
" public function __unset($name) {"
" echo \"Unsetting '$name'\n\";"
" unset($this->data[$name]);"
" return 1;"
" }"
"}"
"$obj = new MemberTest;"
"$obj->a = 1;"
"var_dump($obj->a);"
"var_dump(isset($obj->a));"
"unset($obj->a);");
MVCR("<?php\n"
"class C {\n"
" public $foo = 123;\n"
" public function __unset($k) { echo \"__unset $k\\n\"; }\n"
"}\n"
"$obj = new C;\n"
"unset($obj->foo);\n");
MVCR("<?php "
"class foo"
"{"
" public $public = 'public';"
" public function __wakeup()"
" { echo \"__wakeup called\\n\"; return 1; }"
"}"
"$foo = unserialize(\"O:3:\\\"foo\\\":1:{s:6:\\\"public\\\";s:6:\\\"public\\\";}\");"
"var_dump($foo);");
MVCR("<?php "
"class b {"
" private $f2 = 10;"
" function t2() {"
" var_dump($this->f2);"
" }"
"}"
"class c extends b{"
" private $f = 10;"
" private static $sf = 10;"
" function __get($n) {"
" echo 'got';"
" return 1;"
" }"
" function t() {"
" var_dump($this->f2);"
" }"
"}"
"$x = new c;"
"var_dump($x->f);"
"$x->t();"
"$x->t2();");
MVCR("<?php "
"class X implements arrayaccess {"
"function offsetGet($n) { return $n; }"
"function offsetSet($n, $v) { var_dump($n); }"
"function offsetExists($n) { var_dump($n); return true; }"
"function offsetUnset($n) { var_dump($n); }"
"function __toString() { return 'baz'; }"
"}"
""
"$a = new X;"
"echo \"sets\\n\";"
"$a[true] = 5;"
"$a[NULL] = 57;"
"$a[3.2] = 25;"
"$a[array(3)] = 30;"
"$a[$a] = 32;"
"$a['57'] = 5;"
"$a['6.5'] = 7;"
""
"echo \"gets\\n\";"
"var_dump($a[true]);"
"var_dump($a[NULL]);"
"var_dump($a[3.2]);"
"var_dump($a[array(3)]);"
"var_dump($a[$a]);"
"var_dump($a['57']);"
"var_dump($a['6.5']);"
""
"echo \"unsets\\n\";"
"unset($a[true]);"
"unset($a[NULL]);"
"unset($a[3.2]);"
"unset($a[array(3)]);"
"unset($a[$a]);"
"unset($a['57']);"
"unset($a['6.5']);"
""
"echo \"issets\\n\";"
"isset($a[true]);"
"isset($a[NULL]);"
"isset($a[3.2]);"
"isset($a[array(3)]);"
"isset($a[$a]);"
"isset($a['57']);"
"isset($a['6.5']);");
MVCR("<?php "
"class foo"
"{"
" public function __get($n) { return 'foo'; }"
" public function __set($n,$v) { }"
"}"
"$foo = new foo; $a = $foo->x = 'baz'; $b = $foo->x .= 'bar';"
"var_dump($a,$b);");
MVCR("<?php\n"
"class A {\n"
" var $a;\n"
" function __set($n, $v) { $this->a[$n] = $v; }\n"
" function __get($n) { return $this->a[$n]; }\n"
" function f() { $this->f = 100; $this->f += 100; }\n"
"}\n"
"function test() {\n"
" $a = new A();\n"
" $a->f();\n"
" var_dump($a);\n"
"}\n"
"test();\n");
MVCR("<?php "
"class X {"
" public $real = 1;"
" function __get($name) { echo 'get:'; var_dump($name); return 'abc'; }"
" function __set($name, $val) { echo 'set:'; var_dump($name,$val); }"
"}"
"function test($x) {"
" ++$x->foo;"
" var_dump($x->bar++);"
" $x->real++;"
" var_dump($x);"
"}"
"test(new X);");
MVCR("<?php "
"class Foo {"
" public static $bar;"
" public function __call($fun, $args) {"
" self::$bar = array($fun);"
" }"
"}"
"function getName($part) {"
" return 'funny_'.$part;"
"}"
"function scoped($foo, $name) {"
" call_user_func(array($foo, getName($name)));"
"}"
"scoped(new Foo, 'a');"
"var_dump(Foo::$bar);");
MVCR("<?php "
"if (isset($g)) { class X {} }"
"else {"
" class X {"
" function __destruct() {"
" var_dump(__METHOD__);"
" }"
" }"
"}"
"class Y extends X {"
" function __destruct() {"
" var_dump(__METHOD__);"
" parent::__destruct();"
" }"
"}"
"class Z extends X {}"
"function test($t) {"
" var_dump('test:'.$t);"
" new $t(1,2);"
"}"
"test('X');"
"test('Y');"
"test('Z');");
return true;
}
bool TestCodeRun::TestObjectInvokeMethod() {
MVCR("<?php\n"
"// standard execution\n"
"class C1 {\n"
" public function __invoke($a0, $a1) {\n"
" var_dump('C1');\n"
" var_dump($a0, $a1);\n"
" }\n"
"}\n"
"class D1 extends C1 {}\n"
"class E1 extends D1 {\n"
" public function __invoke($a0, $a1) {\n"
" var_dump('D2');\n"
" var_dump($a0, $a1);\n"
" }\n"
"}\n"
"class F1 {\n"
" public function __invoke($a0) {\n"
" return $a0 > 10;\n"
" }\n"
"}\n"
"$c = new C1;\n"
"$d = new D1;\n"
"$e = new E1;\n"
"$c(0, 1);\n"
"$d(0, 1);\n"
"$e(0, 1);\n"
"call_user_func($c, 0, 1);\n"
"call_user_func($d, 0, 1);\n"
"call_user_func($e, 0, 1);\n"
"call_user_func_array($c, array(0, 1));\n"
"call_user_func_array($d, array(0, 1));\n"
"call_user_func_array($e, array(0, 1));\n"
"$c->__invoke(0, 1);\n"
"$d->__invoke(0, 1);\n"
"$e->__invoke(0, 1);\n"
"C1::__invoke(0, 1);\n"
"D1::__invoke(0, 1);\n"
"E1::__invoke(0, 1);\n"
"function mk($n) { return $n . '::__invoke'; }\n"
"call_user_func(mk('C1'), 0, 1);\n"
"call_user_func(mk('D1'), 0, 1);\n"
"call_user_func(mk('E1'), 0, 1);\n"
"var_dump(array_filter(array(0, 1, 11, 13), new F1));\n");
// this differs from regular PHP behavior
MVCR("<?php\n"
"// taking references\n"
"class C2 {\n"
" public function __invoke(&$a0) {\n"
" var_dump($a0);\n"
" return $a0++;\n"
" }\n"
"}\n"
"$x = 0;\n"
"$c = new C2;\n"
"$c($x);\n"
"var_dump($x); // $x = 1\n"
"call_user_func_array($c, array(&$x));\n"
"var_dump($x); // $x = 2\n");
MVCR("<?php\n"
"// taking default args\n"
"class C3 {\n"
" public function __invoke($a0, $a1 = array(), $a2 = false) {\n"
" var_dump($a0, $a1, $a2);\n"
" }\n"
"}\n"
"$c = new C3;\n"
"$c(0);\n"
"$c(0, array(1));\n"
"$c(0, array(1), true);\n"
"call_user_func($c, 0);\n"
"call_user_func($c, 0, array(1));\n"
"call_user_func($c, 0, array(1), true);\n");
MVCR("<?php\n"
"// as a static method\n"
"class C4 {\n"
" public static function __invoke($a0, $a1) {\n"
" var_dump('C4');\n"
" var_dump($a0, $a1);\n"
" }\n"
"}\n"
"class D4 extends C4 {}\n"
"class E4 extends D4 {\n"
" public static function __invoke($a0, $a1) {\n"
" static $x = 0;\n"
" var_dump('E4');\n"
" var_dump($a0, $a1);\n"
" var_dump($x ++);\n"
" }\n"
"}\n"
"class C5 {\n"
" public static function __invoke() {\n"
" static $x = 0;\n"
" var_dump($x ++);\n"
" }\n"
"}\n"
"class D5 extends C5 {}\n"
"$c = new C4;\n"
"$d = new D4;\n"
"$c(0, 1);\n"
"$d(0, 1);\n"
"call_user_func($c, 0, 1);\n"
"call_user_func($d, 0, 1);\n"
"C4::__invoke(0, 1);\n"
"D4::__invoke(0, 1);\n"
"$e = new E4;\n"
"$e(0, 1);\n"
"$e(0, 1);\n"
"call_user_func($e, 0, 1);\n"
"E4::__invoke(0, 1);\n"
"$c = new C5;\n"
"$d = new D5;\n"
"$c(); $d();\n"
"$c(); $d();\n");
MVCR("<?php\n"
"// as a private/protected method\n"
"class C6 {\n"
" private function __invoke($a0) {\n"
" var_dump($a0);\n"
" }\n"
"}\n"
"class C7 {\n"
" protected function __invoke($a0) {\n"
" var_dump($a0);\n"
" }\n"
"}\n"
"$c = new C6;\n"
"$c(10); // still works...\n"
"$c = new C7;\n"
"$c(20); // still works...\n");
MVCR("<?php\n"
"// with type hints\n"
"class C8 {\n"
" public function __invoke(array $a0) {\n"
" var_dump($a0);\n"
" }\n"
"}\n"
"$c = new C8;\n"
"$c(array(1, 2, 3));\n");
MVCR("<?php\n"
"// with var args\n"
"class C9 {\n"
" public function __invoke() {\n"
" var_dump(func_num_args());\n"
" var_dump(func_get_args());\n"
" }\n"
"}\n"
"$c = new C9;\n"
"$c();\n"
"$c(0);\n"
"$c(0, 1);\n");
MVCR("<?php\n"
"class X { \n"
" public function __invoke($x) {\n"
" var_dump($x);\n"
" }\n"
" public function test() {\n"
" $this(10);\n"
" call_user_func($this, 300);\n"
" call_user_func_array($this, array(0, 1));\n"
" }\n"
"}\n"
"class Y { \n"
" public function test($x) {\n"
" $x(10);\n"
" call_user_func($x, 300);\n"
" call_user_func_array($x, array(0, 1));\n"
" }\n"
"}\n"
"$x = new X;\n"
"$x->test();\n"
"$y = new Y;\n"
"$y->test($x);\n");
MVCR("<?php\n"
"class X {}\n"
"class Y {\n"
" public function __invoke() {}\n"
"}\n"
"var_dump(is_callable(new X));\n"
"var_dump(is_callable(new Y));\n");
MVCR("<?php\n"
"abstract class A {\n"
" abstract public function __invoke($x);\n"
"}\n"
"interface IfaceInvoke {\n"
" public function __invoke($x);\n"
"}\n"
"class Test1 extends A {\n"
" public function __invoke($x) {\n"
" var_dump(__CLASS__);\n"
" var_dump($x);\n"
" }\n"
"}\n"
"class Test2 implements IfaceInvoke {\n"
" public function __invoke($x) {\n"
" var_dump(__CLASS__);\n"
" var_dump($x);\n"
" }\n"
"}\n"
"function f1($x, $y) { $x($y); $x->__invoke($y); }\n"
"function f2(A $x, $y) { $x($y); $x->__invoke($y); }\n"
"function f3(IfaceInvoke $x, $y) { $x($y); $x->__invoke($y); }\n"
"$t1 = new Test1;\n"
"$t2 = new Test2;\n"
"f1($t1, 1);\n"
"f1($t2, 2);\n"
"f2($t1, 1);\n"
"f3($t2, 2);\n");
return true;
}
bool TestCodeRun::TestObjectAssignment() {
MVCR("<?php "
"class foo {"
" public function __construct() {"
" $this->val = 1;"
" }"
" function bar() {"
" echo $this->val;"
" $ref = &$this;"
" $ref->val = 2;"
" echo $this->val;"
" $ref2 = $this;"
" $ref2->val = 3;"
" echo $this->val;"
" $x = new foo();"
" echo $x->val;"
" $ref3 = &$x;"
" $ref3->val = 4;"
" echo $x->val;"
" $ref4 = $x;"
" $ref4->val = 5;"
" echo $x->val;"
" }"
" var $val;"
"}"
"$x = new foo();"
"$x->bar();"
"$ref5 = $x;"
"$ref5->val = 6;"
"echo $x->val;"
"$ref6 = &$x;"
"$ref6->val = 7;"
"echo $x->val;");
return true;
}
bool TestCodeRun::TestNewObjectExpression() {
MVCR("<?php "
"class A { var $num; }"
"function foo() { return new A(); }"
"foreach(($a=(object)new A()) as $v);"
"foreach(($a=(object)foo()) as $v);"
"foreach(($a=new A()) as $v);"
"$a->num = 1;"
"print($a->num);");
MVCR("<?php class A {} class B extends A { "
"static function foo() { return new self();} } "
"var_dump(B::foo());");
MVCR("<?php class A {} class B extends A { "
"static function foo() { return new parent();} } "
"var_dump(B::foo());");
MVCR("<?php "
"function g() {}"
"function h() {}"
"class C {}"
"new C(g(), h());");
MVCR("<?php "
"class X {"
" function __construct($a, &$b) {"
" }"
"}"
"function test($a) {"
" $b = 1;"
" return new X($a, $b);"
"}"
"var_dump(test(3));");
MVCR("<?php "
"class A1 {"
" public function A1($id) {"
" $this->id = $id;"
" }"
"}"
"class B1 extends A1 {"
"}"
"class C1 extends B1 {"
" public function __construct($id) {"
" parent::__construct($id);"
" }"
" function zz($id) {"
" parent::__construct($id);"
" }"
"}"
""
"$x = new C1(100);"
"echo $x->id.\"\\n\";"
"$x->zz(1);"
"echo $x->id.\"\\n\";");
MVCRO("<?php\n"
"class A {\n"
" function __construct($a) { echo \"A\\n\"; }\n"
" function __destruct() { var_dump($this); }\n"
"}\n"
"function f() { echo \"f\\n\"; throw new Exception(); }\n"
"function test() { $a = new A(f()); }\n"
"try { test(); } catch (Exception $e) { }\n"
,
"f\n");
MVCR("<?php "
"class foo {"
" static function ioo($y, &$x) {"
" return new self(1);"
" }"
" function __construct($a, $b) {}"
"}"
"function t() {"
" $x = 1;"
" foo::ioo($x, $y);"
"}"
"t();");
MVCR("<?php "
"class X {"
" function __toString() { return 'hello'; }"
"}"
"function f() {"
" return 'bar';"
"}"
"function test($e) {"
" $a = 'foo';"
" for ($i = 0; $i < 10; $i++) {"
" $a .= new X($e['x']) . f();"
" }"
" return $a;"
"}"
"var_dump(test());");
MVCR("<?php "
"class X {}"
"class Y {}"
"function test($x) {"
" return new $x($x = 'y');"
"}"
"var_dump(test('x'));");
return true;
}
bool TestCodeRun::TestObjectPropertyExpression() {
MVCR("<?php "
"class test {"
" function foo() {"
" $var = $this->blah->prop->foo->bar = \"string\";"
" var_dump($this->blah);"
" }"
"}"
"$t = new test;"
"$t->foo();");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"$c = new C1();"
"$c->a = 1;"
"$c->a .= 1;"
"print $c->a;");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C2 {"
" public $p2;"
"}"
"$c2 = new C2();"
"$c2->p = new C1();"
"$c2->p->a = 1;"
"$c2->p->a .= 1;"
"print $c2->p->a;");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C2 {"
" public $p2;"
"}"
"class C3 {"
" public $p3;"
"}"
"$c3 = new C3();"
"$c3->p3 = new C2();"
"$c3->p3->p2 = new C1();"
"$c3->p3->p2->a = 1;"
"$c3->p3->p2->a .= 1;"
"print $c3->p3->p2->a;");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get C1\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C1\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C2 {"
" public function __get( $what ) {"
" echo \"get C2\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C2\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C3 {"
" public function __get( $what) {"
" echo \"get C3\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C3\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"$c3 = new C3();"
"$c3->p3 = new C2();"
"$c3->p3->p2 = new C1();"
"$c3->p3->p2->a = 1;"
"$c3->p3->p2->a .= 1;"
"print $c3->p3->p2->a;");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get C1\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C1\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C2 {"
" public function __get( $what ) {"
" echo \"get C2\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C2\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C3 {"
" public function __get( $what) {"
" echo \"get C3\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C3\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"$c3 = new C3();"
"$c3->p3 = new C2();"
"$c3->p3->p2 = new C1();"
"$c3->p3->p2->a = 1;"
"$c3->p3->p2->a .= 1;"
"print $c3->p3->p2->a;");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get C1\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C1\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C2 {"
" public function __get( $what ) {"
" echo \"get C2\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C2\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C3 {"
" public function __get( $what) {"
" echo \"get C3\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C3\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"$c3 = new C3();"
"$c3->p3 = new C2();"
"$c3->p3->p2 = new C1();"
"$c3->p3->p2->a = 1;"
"$c3->p3->p2->a .= 1;"
"print $c3->p3->p2->a;");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"$c = new C1();"
"$c->a += 1;"
"print $c->a;"
"$c->a += 10;"
"print $c->a;"
"$c->a -= 2;"
"print $c->a;"
"$c->a *= 3;"
"print $c->a;"
"$c->a /= 2;"
"print $c->a;"
"$c->a %= 8;"
"print $c->a;"
"$c->a <<= 3;"
"print $c->a;"
"$c->a >>= 2;"
"print $c->a;"
"$c->a ^= 18;"
"print $c->a;"
"$c->a &= 333;"
"print $c->a;"
"$c->a |= 7;"
"print $c->a;");
MVCR("<?php "
"class C1 {"
"}"
"class C2 {"
" public function __get( $what ) {"
" echo \"get C2\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C2\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C3 {"
" public function __get( $what ) {"
" echo \"get C3\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C3\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"function assign_ref(&$v) {"
" $v = 22;"
"}"
"$c3 = new C3();"
"$c3->p3 = new C2();"
"$c3->p3->p2 = new C1();"
"$c3->p3->p2->a = 1;"
"$c3->p3->p2->a .= 1;"
"print $c3->p3->p2->a;"
"assign_ref($c3->p3->p2->a);"
"print $c3->p3->p2->a;");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get C1\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C1\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C2 {"
" public function __get( $what ) {"
" echo \"get C2\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C2\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"class C3 {"
" public function __get( $what ) {"
" echo \"get C3\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C3\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"function assign_ref(&$v) {"
" $v = 22;"
"}"
"$c3 = new C3();"
"$c3->p3 = new C2();"
"$c3->p3->p2 = new C1();"
"$c3->p3->p2->a = 1;"
"$c3->p3->p2->a .= 1;"
"print $c3->p3->p2->a;"
"assign_ref($c3->p3->p2->a);"
"print $c3->p3->p2->a;");
MVCR("<?php "
"$b = 10;"
"class C1 {"
" public function __get( $what ) {"
" global $b;"
" return $b;"
" }"
"}"
"$c1 = new C1();"
"function assign_ref(&$lv) {"
" $lv = 8;"
"}"
"assign_ref($c1->a);"
"var_dump($b);");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get C1\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C1\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"$c1 = new C1();"
"$c1->a = new C1();"
"$c1->a->b = new C1();"
"$c1->a->b->c = 10;"
"var_dump($c1->a->b->c);"
"$c1->a->b->c .= 10;"
"var_dump($c1->a->b->c);");
MVCR("<?php "
"class C1 {"
" public function __get( $what ) {"
" echo \"get C1\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C1\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"$c1 = new C1();"
"$c1->a = new C1();"
"$c1->a->b = new C1();"
"for ($i = 0; $i < 2048; $i++) {"
" $c1->a->b->c = 10;"
"}"
"var_dump($c1->a->b->c);");
MVCR("<?php "
"class Y {}"
"class X {"
" public $a;"
" function __construct() {"
" $this->a = array('x' => new Y);"
" }"
" function bar() {"
" var_dump('bar');"
" $this->qq = new Y;"
" $this->qq->x = $this->qq->y = 1;"
" return $this->qq;"
" }"
"}"
"function foo() { var_dump('foo'); return 'foo'; }"
"function test($x, $a, $s) {"
" $t = &$s->t;"
" unset($x->bar()->x);"
" unset($x->q->r->s->${foo()});"
" unset($x->y->a->b->c);"
" unset($x->a['x']->y->a->b->c);"
" unset($a['a']['y'][foo()]);"
" unset($a['b']->y->z);"
" unset($a->c->d);"
" var_dump($x, $a, $s);"
"}"
"test(new X, array(), false);");
MVCR("<?php "
"class X {"
"public $a = 3;"
"function foo($t) {"
"$$t = 5;"
"var_dump($this->a);"
"var_dump($this);"
"}"
"}"
"$x = new X;"
"$x->foo('this');");
MVCR("<?php "
"class X {"
" public function foo($q) {"
" $s =& $this;"
" $s->q = $q;"
" }"
"}"
"function test() {"
" $x = new X;"
" $x->foo('hello');"
" var_dump($x);"
"}"
"test();");
if (Option::EnableEval >= Option::FullEval) {
MVCRONW("<?php "
"class X {"
" function ref(&$ref) { $ref = 1; }"
" function bar() {"
" $this->ref($this->priv);"
" }"
"};"
"class Y extends X { private $priv; }"
"class Z extends Y {}"
"$z = new Z;"
"$z->bar();"
"var_dump($z);"
"$y = new Y;"
"$y->bar();"
"var_dump($y);"
,
"object(Z)#1 (2) {\n"
" [\"priv\":\"Y\":private]=>\n"
" NULL\n"
" [\"priv\"]=>\n"
" int(1)\n"
"}\n");
}
return true;
}
bool TestCodeRun::TestCollectionClasses() {
MVCRO("<?php\n"
"$arr = array(null, false, true, 0, 1, 0.0, 1.0, '', '0', '1',\n"
" '0.0', '1.0', '0 ', 'foo');\n"
"$vec = Vector::fromArray($arr);\n"
"foreach ($vec as $k => $v) {\n"
" var_dump($v);\n"
" var_dump($vec[$k]);\n"
" var_dump(isset($v));\n"
" var_dump(isset($vec[$k]));\n"
" var_dump(empty($v));\n"
" var_dump(empty($vec[$k]));\n"
" echo \"\\n\";\n"
"}\n"
"echo \"=====================\\n\\n\";\n"
"$mp = Map::fromArray($arr);\n"
"foreach ($arr as $k => $v) {\n"
" var_dump($mp[$k]);\n"
" var_dump(isset($mp[$k]));\n"
" var_dump(empty($mp[$k])); \n"
" echo \"\\n\";\n"
"}\n"
"$new_arr = array();\n"
"foreach ($mp as $k => $v) {\n"
" $new_arr[$k] = $v;\n"
"}\n"
"ksort($new_arr);\n"
"var_dump($new_arr);\n"
"echo \"=====================\\n\\n\";\n"
"$smp = StableMap::fromArray($arr);\n"
"foreach ($smp as $k => $v) {\n"
" var_dump($v);\n"
" var_dump($smp[$k]);\n"
" var_dump(isset($v));\n"
" var_dump(isset($smp[$k]));\n"
" var_dump(empty($v));\n"
" var_dump(empty($smp[$k]));\n"
" echo \"\\n\";\n"
"}\n"
"echo \"Done\\n\";\n"
,
"NULL\n"
"NULL\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"int(0)\n"
"int(0)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"int(1)\n"
"int(1)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"float(0)\n"
"float(0)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"float(1)\n"
"float(1)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"string(1) \"0\"\n"
"string(1) \"0\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"string(1) \"1\"\n"
"string(1) \"1\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(3) \"0.0\"\n"
"string(3) \"0.0\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(3) \"1.0\"\n"
"string(3) \"1.0\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(2) \"0 \"\n"
"string(2) \"0 \"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"=====================\n"
"\n"
"NULL\n"
"bool(false)\n"
"bool(true)\n"
"\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"\n"
"int(0)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"int(1)\n"
"bool(true)\n"
"bool(false)\n"
"\n"
"float(0)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"float(1)\n"
"bool(true)\n"
"bool(false)\n"
"\n"
"string(0) \"\"\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"string(1) \"0\"\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"string(1) \"1\"\n"
"bool(true)\n"
"bool(false)\n"
"\n"
"string(3) \"0.0\"\n"
"bool(true)\n"
"bool(false)\n"
"\n"
"string(3) \"1.0\"\n"
"bool(true)\n"
"bool(false)\n"
"\n"
"string(2) \"0 \"\n"
"bool(true)\n"
"bool(false)\n"
"\n"
"string(3) \"foo\"\n"
"bool(true)\n"
"bool(false)\n"
"\n"
"array(14) {\n"
" [0]=>\n"
" NULL\n"
" [1]=>\n"
" bool(false)\n"
" [2]=>\n"
" bool(true)\n"
" [3]=>\n"
" int(0)\n"
" [4]=>\n"
" int(1)\n"
" [5]=>\n"
" float(0)\n"
" [6]=>\n"
" float(1)\n"
" [7]=>\n"
" string(0) \"\"\n"
" [8]=>\n"
" string(1) \"0\"\n"
" [9]=>\n"
" string(1) \"1\"\n"
" [10]=>\n"
" string(3) \"0.0\"\n"
" [11]=>\n"
" string(3) \"1.0\"\n"
" [12]=>\n"
" string(2) \"0 \"\n"
" [13]=>\n"
" string(3) \"foo\"\n"
"}\n"
"=====================\n"
"\n"
"NULL\n"
"NULL\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"int(0)\n"
"int(0)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"int(1)\n"
"int(1)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"float(0)\n"
"float(0)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"float(1)\n"
"float(1)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"string(1) \"0\"\n"
"string(1) \"0\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"\n"
"string(1) \"1\"\n"
"string(1) \"1\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(3) \"0.0\"\n"
"string(3) \"0.0\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(3) \"1.0\"\n"
"string(3) \"1.0\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(2) \"0 \"\n"
"string(2) \"0 \"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"\n"
"Done\n"
);
MVCRO("<?php\n"
"$v = new Vector;\n"
"$v[] = 123;\n"
"var_dump($v->toArray());\n"
"var_dump($v->pop());\n"
"var_dump($v->toArray());\n"
,
"array(1) {\n"
" [0]=>\n"
" int(123)\n"
"}\n"
"int(123)\n"
"array(0) {\n"
"}\n"
);
MVCRO("<?php\n"
"try {\n"
" $v = new Vector();\n"
" $v->contains(1);\n"
" try {\n"
" $v->contains('foo');\n"
" } catch (Exception $e) {\n"
" echo 'A';\n"
" }\n"
" try {\n"
" $v->contains(1.0);\n"
" } catch (Exception $e) {\n"
" echo 'B';\n"
" }\n"
" $methods = Vector::fromArray(array('contains','remove',"
"'discard'));\n"
" foreach ($methods as $method) {\n"
" $m = new Map();\n"
" $m->$method(1);\n"
" $m->$method('foo');\n"
" try {\n"
" $m->$method(1.0);\n"
" } catch (Exception $e) {\n"
" echo 'C';\n"
" }\n"
" $s = new StableMap();\n"
" $s->$method(1);\n"
" $s->$method('foo');\n"
" try {\n"
" $s->$method(1.0);\n"
" } catch (Exception $e) {\n"
" echo 'D';\n"
" }\n"
" echo \"\\n\";\n"
" }\n"
"} catch (Exception $e) {\n"
" echo \"Test failed\\n\";\n"
"}\n"
,
"ABCD\n"
"CD\n"
"CD\n"
);
MVCRO("<?php\n"
"$classes = array('Vector','Map','StableMap');\n"
"$i = 0;\n"
"try {\n"
" foreach ($classes as $cls) {\n"
" $obj = new $cls;\n"
" try {\n"
" $x = $obj->foo;\n"
" } catch (RuntimeException $e) {\n"
" echo $i;\n"
" }\n"
" ++$i;\n"
" try {\n"
" $obj->foo = 123;\n"
" } catch (RuntimeException $e) {\n"
" echo $i;\n"
" }\n"
" ++$i;\n"
" }\n"
"} catch (Exception $e) {\n"
" echo \"Fail!\\n\";\n"
"}\n"
"echo \"Done\\n\";\n"
,
"012345Done\n"
);
MVCRO("<?php\n"
"$v = new Vector;\n"
"$v[] = 7;\n"
"$v[] = 'foo';\n"
"var_dump(serialize($v));\n"
"$v2 = unserialize(serialize($v));\n"
"echo \"=========================\\n\";\n"
"var_dump($v);\n"
"print_r($v);\n"
"echo json_encode($v) . \"\\n\";\n"
"var_export($v); echo \"\\n\";\n"
"var_dump($v2);\n"
"print_r($v2);\n"
"echo json_encode($v2) . \"\\n\";\n"
"var_export($v2); echo \"\\n\";\n"
,
"string(31) \"V:6:\"Vector\":2:{i:7;s:3:\"foo\";}\"\n"
"=========================\n"
"object(Vector)#1 (2) {\n"
" [0]=>\n"
" int(7)\n"
" [1]=>\n"
" string(3) \"foo\"\n"
"}\n"
"Vector Object\n"
"(\n"
" [0] => 7\n"
" [1] => foo\n"
")\n"
"[7,\"foo\"]\n"
"Vector::__set_state(array(\n"
" 0 => 7,\n"
" 1 => 'foo',\n"
"))\n"
"object(Vector)#2 (2) {\n"
" [0]=>\n"
" int(7)\n"
" [1]=>\n"
" string(3) \"foo\"\n"
"}\n"
"Vector Object\n"
"(\n"
" [0] => 7\n"
" [1] => foo\n"
")\n"
"[7,\"foo\"]\n"
"Vector::__set_state(array(\n"
" 0 => 7,\n"
" 1 => 'foo',\n"
"))\n"
);
MVCRO("<?php\n"
"$m = new Map;\n"
"$m[3] = 'foo';\n"
"var_dump(serialize($m));\n"
"$m2 = unserialize(serialize($m));\n"
"echo \"=========================\\n\";\n"
"var_dump($m);\n"
"print_r($m);\n"
"echo json_encode($m) . \"\\n\";\n"
"var_export($m); echo \"\\n\";\n"
"var_dump($m2);\n"
"print_r($m2);\n"
"echo json_encode($m2) . \"\\n\";\n"
"var_export($m2); echo \"\\n\";\n"
"echo \"=========================\\n\";\n"
"$m = new Map;\n"
"$m['bar'] = 7;\n"
"var_dump(serialize($m));\n"
"$m2 = unserialize(serialize($m));\n"
"echo \"=========================\\n\";\n"
"var_dump($m);\n"
"print_r($m);\n"
"echo json_encode($m) . \"\\n\";\n"
"var_export($m); echo \"\\n\";\n"
"var_dump($m2);\n"
"print_r($m2);\n"
"echo json_encode($m2) . \"\\n\";\n"
"var_export($m2); echo \"\\n\";\n"
,
"string(28) \"K:3:\"Map\":1:{i:3;s:3:\"foo\";}\"\n"
"=========================\n"
"object(Map)#1 (1) {\n"
" [3]=>\n"
" string(3) \"foo\"\n"
"}\n"
"Map Object\n"
"(\n"
" [3] => foo\n"
")\n"
"{\"3\":\"foo\"}\n"
"Map::__set_state(array(\n"
" 3 => 'foo',\n"
"))\n"
"object(Map)#2 (1) {\n"
" [3]=>\n"
" string(3) \"foo\"\n"
"}\n"
"Map Object\n"
"(\n"
" [3] => foo\n"
")\n"
"{\"3\":\"foo\"}\n"
"Map::__set_state(array(\n"
" 3 => 'foo',\n"
"))\n"
"=========================\n"
"string(28) \"K:3:\"Map\":1:{s:3:\"bar\";i:7;}\"\n"
"=========================\n"
"object(Map)#3 (1) {\n"
" [\"bar\"]=>\n"
" int(7)\n"
"}\n"
"Map Object\n"
"(\n"
" [bar] => 7\n"
")\n"
"{\"bar\":7}\n"
"Map::__set_state(array(\n"
" 'bar' => 7,\n"
"))\n"
"object(Map)#4 (1) {\n"
" [\"bar\"]=>\n"
" int(7)\n"
"}\n"
"Map Object\n"
"(\n"
" [bar] => 7\n"
")\n"
"{\"bar\":7}\n"
"Map::__set_state(array(\n"
" 'bar' => 7,\n"
"))\n"
);
MVCRO("<?php\n"
"$m = new StableMap;\n"
"$m[3] = 'foo';\n"
"$m['bar'] = 7;\n"
"var_dump(serialize($m));\n"
"$m2 = unserialize(serialize($m));\n"
"echo \"=========================\\n\";\n"
"var_dump($m);\n"
"print_r($m);\n"
"echo json_encode($m) . \"\\n\";\n"
"var_export($m); echo \"\\n\";\n"
"var_dump($m2);\n"
"print_r($m2);\n"
"echo json_encode($m2) . \"\\n\";\n"
"var_export($m2); echo \"\\n\";\n"
"echo \"=========================\\n\";\n"
"$m = new StableMap;\n"
"$m['bar'] = 7;\n"
"$m[3] = 'foo';\n"
"var_dump(serialize($m));\n"
"$m2 = unserialize(serialize($m));\n"
"echo \"=========================\\n\";\n"
"var_dump($m);\n"
"print_r($m);\n"
"echo json_encode($m) . \"\\n\";\n"
"var_export($m); echo \"\\n\";\n"
"var_dump($m2);\n"
"print_r($m2);\n"
"echo json_encode($m2) . \"\\n\";\n"
"var_export($m2); echo \"\\n\";\n"
,
"string(48) \"K:9:\"StableMap\":2:{i:3;s:3:\"foo\";s:3:\"bar\";"
"i:7;}\"\n"
"=========================\n"
"object(StableMap)#1 (2) {\n"
" [3]=>\n"
" string(3) \"foo\"\n"
" [\"bar\"]=>\n"
" int(7)\n"
"}\n"
"StableMap Object\n"
"(\n"
" [3] => foo\n"
" [bar] => 7\n"
")\n"
"{\"3\":\"foo\",\"bar\":7}\n"
"StableMap::__set_state(array(\n"
" 3 => 'foo',\n"
" 'bar' => 7,\n"
"))\n"
"object(StableMap)#2 (2) {\n"
" [3]=>\n"
" string(3) \"foo\"\n"
" [\"bar\"]=>\n"
" int(7)\n"
"}\n"
"StableMap Object\n"
"(\n"
" [3] => foo\n"
" [bar] => 7\n"
")\n"
"{\"3\":\"foo\",\"bar\":7}\n"
"StableMap::__set_state(array(\n"
" 3 => 'foo',\n"
" 'bar' => 7,\n"
"))\n"
"=========================\n"
"string(48) \"K:9:\"StableMap\":2:{s:3:\"bar\";i:7;i:3;"
"s:3:\"foo\";}\"\n"
"=========================\n"
"object(StableMap)#3 (2) {\n"
" [\"bar\"]=>\n"
" int(7)\n"
" [3]=>\n"
" string(3) \"foo\"\n"
"}\n"
"StableMap Object\n"
"(\n"
" [bar] => 7\n"
" [3] => foo\n"
")\n"
"{\"bar\":7,\"3\":\"foo\"}\n"
"StableMap::__set_state(array(\n"
" 'bar' => 7,\n"
" 3 => 'foo',\n"
"))\n"
"object(StableMap)#4 (2) {\n"
" [\"bar\"]=>\n"
" int(7)\n"
" [3]=>\n"
" string(3) \"foo\"\n"
"}\n"
"StableMap Object\n"
"(\n"
" [bar] => 7\n"
" [3] => foo\n"
")\n"
"{\"bar\":7,\"3\":\"foo\"}\n"
"StableMap::__set_state(array(\n"
" 'bar' => 7,\n"
" 3 => 'foo',\n"
"))\n"
);
MVCRO("<?php\n"
"var_dump(unserialize(\n"
" \"K:8:\\\"stdClass\\\":2:{i:0;i:0;i:1;i:1;}\"));\n"
"var_dump(unserialize(\n"
" \"O:6:\\\"Vector\\\":1:{s:3:\\\"foo\\\";i:7;}\"));\n"
,
"bool(false)\n"
"bool(false)\n"
);
MVCRO("<?php\n"
"$m = new Map();\n"
"$m['foo'] = new Map();\n"
"$m['foo'][123] = new Vector();\n"
"$m['foo'][123][] = 'bar';\n"
"var_dump($m['foo'][123][0]);\n"
,
"string(3) \"bar\"\n"
);
MVCRO("<?php\n"
"$v = Vector::fromArray(array('foo'));\n"
"var_dump($v[0]);\n"
"var_dump($v->at(0));\n"
"var_dump($v->get(0));\n"
"var_dump($v->get(1));\n"
"$m = Map::fromArray(array('foo'));\n"
"var_dump($m[0]);\n"
"var_dump($m->at(0));\n"
"var_dump($m->get(0));\n"
"var_dump($m->get(1));\n"
"$sm = StableMap::fromArray(array('foo'));\n"
"var_dump($sm[0]);\n"
"var_dump($sm->at(0));\n"
"var_dump($sm->get(0));\n"
"var_dump($sm->get(1));\n"
,
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"NULL\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"NULL\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"NULL\n"
);
MVCRO("<?php\n"
"$m = Map::fromArray(array('a' => 'foo'));\n"
"var_dump($m['a']);\n"
"var_dump($m->at('a'));\n"
"var_dump($m->get('a'));\n"
"var_dump($m->get('b'));\n"
"$sm = StableMap::fromArray(array('a' => 'foo'));\n"
"var_dump($sm['a']);\n"
"var_dump($sm->at('a'));\n"
"var_dump($sm->get('a'));\n"
"var_dump($sm->get('b'));\n"
,
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"NULL\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"string(3) \"foo\"\n"
"NULL\n"
);
MVCRO("<?php\n"
"$v = new Vector;\n"
"$v[] = 'c';\n"
"$v[] = 'a';\n"
"$v[] = 'b';\n"
"sort($v);\n"
"foreach ($v as $key => $val) {\n"
" echo $key . ' ' . $val . \"\\n\";\n"
"}\n"
"echo \"=======\\n\";\n"
"$s = new StableMap;\n"
"$s['w'] = 2;\n"
"$s['v'] = 4;\n"
"$s['y'] = 3;\n"
"$s['x'] = 5;\n"
"$s['z'] = 1;\n"
"ksort($s);\n"
"foreach ($s as $key => $val) {\n"
" echo $key . ' ' . $val . \"\\n\";\n"
"}\n"
"echo \"=======\\n\";\n"
"asort($s);\n"
"foreach ($s as $key => $val) {\n"
" echo $key . ' ' . $val . \"\\n\";\n"
"}\n"
,
"0 a\n"
"1 b\n"
"2 c\n"
"=======\n"
"v 4\n"
"w 2\n"
"x 5\n"
"y 3\n"
"z 1\n"
"=======\n"
"z 1\n"
"w 2\n"
"y 3\n"
"v 4\n"
"x 5\n"
);
MVCRO("<?php\n"
"function cmp($x, $y) {\n"
" if ($x < $y) return 1;\n"
" if ($x > $y) return -1;\n"
" return 0;\n"
"}\n"
"$v = new Vector;\n"
"$v[] = 'c';\n"
"$v[] = 'a';\n"
"$v[] = 'b';\n"
"usort($v, 'cmp');\n"
"foreach ($v as $key => $val) {\n"
" echo $key . ' ' . $val . \"\\n\";\n"
"}\n"
"echo \"=======\\n\";\n"
"$s = new StableMap;\n"
"$s['w'] = 2;\n"
"$s['v'] = 4;\n"
"$s['y'] = 3;\n"
"$s['x'] = 5;\n"
"$s['z'] = 1;\n"
"uksort($s, 'cmp');\n"
"foreach ($s as $key => $val) {\n"
" echo $key . ' ' . $val . \"\\n\";\n"
"}\n"
"echo \"=======\\n\";\n"
"uasort($s, 'cmp');\n"
"foreach ($s as $key => $val) {\n"
" echo $key . ' ' . $val . \"\\n\";\n"
"}\n"
,
"0 c\n"
"1 b\n"
"2 a\n"
"=======\n"
"z 1\n"
"y 3\n"
"x 5\n"
"w 2\n"
"v 4\n"
"=======\n"
"x 5\n"
"v 4\n"
"y 3\n"
"w 2\n"
"z 1\n"
);
MVCRO("<?hh\n"
"function f() {\n"
" var_dump(Vector {});\n"
" var_dump(Map {});\n"
" var_dump(Vector { 1, 2 });\n"
" var_dump(StableMap { 'a' => 1, 'b' => 2 });\n"
"\n"
" var_dump(Vector<int> {});\n"
" var_dump(Map<string,int> {});\n"
" var_dump(Vector<int> { 1, 2 });\n"
" var_dump(StableMap<string,int> { 'a' => 1, 'b' => 2 });\n"
"}\n"
"f();\n"
,
"object(Vector)#1 (0) {\n"
"}\n"
"object(Map)#1 (0) {\n"
"}\n"
"object(Vector)#1 (2) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(2)\n"
"}\n"
"object(StableMap)#1 (2) {\n"
" [\"a\"]=>\n"
" int(1)\n"
" [\"b\"]=>\n"
" int(2)\n"
"}\n"
"object(Vector)#1 (0) {\n"
"}\n"
"object(Map)#1 (0) {\n"
"}\n"
"object(Vector)#1 (2) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(2)\n"
"}\n"
"object(StableMap)#1 (2) {\n"
" [\"a\"]=>\n"
" int(1)\n"
" [\"b\"]=>\n"
" int(2)\n"
"}\n"
);
MVCRO("<?php\n"
"function f($x1, $x2, $x3, $x4) {\n"
" return Vector { $x1, $x2, $x3, $x4 };\n"
"}\n"
"function g($k1, $v1, $k2, $v2) {\n"
" $m = Map { $k1 => $v1, $k2 => $v2 };\n"
" return $m;\n"
"}\n"
"var_dump(f(42, 123.456, 'blah', array(3, 5, 7)));\n"
"var_dump(g('foo', 1, 2, 'bar'));\n"
,
"object(Vector)#1 (4) {\n"
" [0]=>\n"
" int(42)\n"
" [1]=>\n"
" float(123.456)\n"
" [2]=>\n"
" string(4) \"blah\"\n"
" [3]=>\n"
" array(3) {\n"
" [0]=>\n"
" int(3)\n"
" [1]=>\n"
" int(5)\n"
" [2]=>\n"
" int(7)\n"
" }\n"
"}\n"
"object(Map)#1 (2) {\n"
" [\"foo\"]=>\n"
" int(1)\n"
" [2]=>\n"
" string(3) \"bar\"\n"
"}\n"
);
return true;
}
///////////////////////////////////////////////////////////////////////////////
// comparisons
#define COMPARE(a, op, b) \
"print ++$i; print \"\\t\"; " \
"print (" #a #op #b ") ? 'Y' : 'N'; " \
"$a = 1; $a = 't'; $a = " #a "; " \
"print ($a " #op #b ") ? 'Y' : 'N'; " \
"$b = 1; $b = 't'; $b = " #b "; " \
"print (" #a #op "$b) ? 'Y' : 'N'; " \
"print ($a " #op "$b) ? 'Y' : 'N'; " \
"print \"\\t\"; " \
"print \"" #a " " #op " " #b "\t\"; " \
"print \"\\n\"; " \
#define COMPARE_ALL(a, op) \
COMPARE(a, op, true) \
COMPARE(a, op, false) \
COMPARE(a, op, 1) \
COMPARE(a, op, 0) \
COMPARE(a, op, -1) \
COMPARE(a, op, '1') \
COMPARE(a, op, '0') \
COMPARE(a, op, '-1') \
COMPARE(a, op, NULL) \
COMPARE(a, op, array()) \
COMPARE(a, op, array(1)) \
COMPARE(a, op, array(2)) \
COMPARE(a, op, array('1')) \
COMPARE(a, op, array('0' => '1')) \
COMPARE(a, op, array('a')) \
COMPARE(a, op, array('a' => 1)) \
COMPARE(a, op, array('b' => 1)) \
COMPARE(a, op, array('a' => 1, 'b' => 2)) \
COMPARE(a, op, array(array('a' => 1))) \
COMPARE(a, op, array(array('b' => 1))) \
COMPARE(a, op, 'php') \
COMPARE(a, op, '') \
#define COMPARE_OP(op) \
MVCR("<?php $i = 0; " COMPARE_ALL('1.2', op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(true, op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(false, op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(1, op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(0, op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(-1, op)); \
MVCR("<?php $i = 0; " COMPARE_ALL('1', op)); \
MVCR("<?php $i = 0; " COMPARE_ALL('0', op)); \
MVCR("<?php $i = 0; " COMPARE_ALL('-1', op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(NULL, op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array(), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array(1), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array(2), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array('1'), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array('0' => '1'), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array('a'), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array('a' => 1), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array('b' => 1), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array('a' => 1, 'b' => 2), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array(array('a' => 1)), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL(array(array('b' => 1)), op)); \
MVCR("<?php $i = 0; " COMPARE_ALL('php', op)); \
MVCR("<?php $i = 0; " COMPARE_ALL('', op)); \
bool TestCodeRun::TestComparisons() {
MVCR("<?php var_dump(array(1 => 1, 2 => 1) == array(2 => 1, 1 => 1));");
MVCR("<?php var_dump(array(1 => 1, 2 => 1) === array(2 => 1, 1 => 1));");
MVCR("<?php var_dump(array('a'=>1,'b'=> 1) == array('b'=>1,'a'=> 1));");
MVCR("<?php var_dump(array('a'=>1,'b'=> 1) === array('b'=>1,'a'=> 1));");
MVCR("<?php $a = '05/17'; $b = '05/18'; var_dump($a == $b);");
MVCR("<?php var_dump('05/17' == '05/18');");
MVCR("<?php var_dump('1.0' == '1');"
"var_dump('1.0E2' == '10E1');"
"var_dump('1' === '1');"
"var_dump('1.0' === '1.0');"
"var_dump('1' === '1.0');"
"var_dump('1.0' === '1.00');"
"var_dump(1.0 === 1.00);"
"var_dump('1' == '1');"
"var_dump('1.0' == '1.0');"
"var_dump('1' == '1.0');"
"var_dump('1.0' == '1.00');"
"var_dump(1.0 == 1.00);"
"function foo($a, $b) {"
" $s = (string)$a;"
" $t = (string)$b;"
" var_dump($s === $t);"
"}"
"foo('1.00', '1.0');"
"foo('1.0', '1.0');"
"foo('1.', '1.0');"
"foo('1', '1.0');");
COMPARE_OP(==);
COMPARE_OP(===);
COMPARE_OP(!=);
COMPARE_OP(<>);
COMPARE_OP(!==);
COMPARE_OP(<);
COMPARE_OP(>);
COMPARE_OP(<=);
COMPARE_OP(>=);
MVCR("<?php "
"class c {"
" public $x = 0;"
"}"
"$x = new c;"
"$x->x = 1;"
"$y = new c;"
"var_dump($x > $y);"
"var_dump(array($x) == array($y));");
MVCR("<?php "
"function foo($p) {"
" if ($p) {"
" $a = 'foo';"
" }"
" if ('' < $a) {"
" echo 'yes';"
" } else {"
" echo 'no';"
" }"
" if ($a > '') {"
" echo 'yes';"
" } else {"
" echo 'no';"
" }"
"}"
"foo(false);");
MVCR("<?php "
"$part = ' 1';"
"var_dump(trim($part) !== $part);");
MVCR("<?php "
"class C { }"
"function foo($p) {"
" if ($p) {"
" $obj = new C;"
" } else {"
" $a = array(1);"
" }"
" var_dump($obj == $a);"
"}"
"foo(false);");
MVCR("<?php\n"
"$x = (object)null;\n"
"var_dump ($x == 1 && 1 == $x);\n"
"var_dump ($x == 1.0 && 1.0 == $x);\n"
"var_dump ($x > 0);\n"
"var_dump ($x >= 1);\n"
"var_dump ($x < 5);\n"
"var_dump ($x <= 1);\n");
return true;
}
///////////////////////////////////////////////////////////////////////////////
// semantics
bool TestCodeRun::TestUnset() {
MVCR("<?php class A { static $foo = array(123);} $a = 'A'; "
"unset($a::$foo[0]); unset(A::$foo[0]);");
MVCR("<?php $a = 10; unset($a); var_dump($a);");
MVCR("<?php $a = array(10); "
"function test() { global $a; unset($a[0]); var_dump($a);}"
"var_dump($a); test(); var_dump($a);");
MVCR("<?php $a = 10; unset($GLOBALS); var_dump($a);");
MVCR("<?php "
"function f1() {"
" $x = array(1,2,3);"
" unset($x[0]);"
" var_dump($x);"
"}"
"function f2() {"
" $x = array(1,2,3);"
" unset($x[0][0]);"
" var_dump($x);"
"}"
"function f3() {"
" $x = array(array(4,5,6),2,3);"
" unset($x[0][0]);"
" var_dump($x);"
"}"
"function f4() {"
" $x = array(array(4,5,6),2,3);"
" unset($x[0][0][0]);"
" var_dump($x);"
"}"
"f1();"
"f2();"
"f3();"
"f4();");
MVCR("<?php class A { public $arr;} $obj = new A; $obj->arr[] = 'test';"
"var_dump($obj->arr); unset($obj->arr); var_dump($obj->arr);");
MVCR("<?php function test() {$a=array(1,2,3); unset($a[0]);}");
MVCR("<?php "
"function foo() {"
" $a = 1;"
" $b = 2;"
" $c = 3;"
" unset($a, $b, $c);"
" var_dump($b);"
"}"
"foo();");
MVCR("<?php "
"$a = 1;"
"function foo() {"
" $GLOBALS['foo'] = 1;"
" unset($GLOBALS['foo']);"
" var_dump(array_key_exists('foo', $GLOBALS));"
" $g['foo'] = 1;"
" unset($g['foo']);"
" var_dump(array_key_exists('foo', $g));"
" var_dump(array_key_exists('a', $GLOBALS));"
" unset($GLOBALS['a']);"
" var_dump(array_key_exists('a', $GLOBALS));"
"}"
"foo();");
MVCR("<?php "
"class A {"
" var $a;"
" public function __construct($p) {"
" $this->a = $p;"
" }"
"};"
"$obj = new A(1);"
"var_dump($obj);"
"unset($obj->a);"
"var_dump($obj);"
"$obj->a = 2;"
"var_dump($obj);"
"$obj->b = 3;"
"var_dump($obj);"
"unset($obj->b);"
"var_dump($obj);"
"$obj->a = 2;"
"var_dump($obj);"
"$obj->b = 3;"
"var_dump($obj);"
"unset($obj->a, $obj->b);"
"var_dump($obj);");
MVCR("<?php "
"class X {"
" function __construct() { echo 'construct\n'; }"
" function __destruct() { echo 'destruct\n'; }"
"}"
"function test() {"
" $a = new X;"
" echo 'before unset\n';"
" unset($a);"
" echo 'after unset\n';"
"}"
"test();");
MVCR("<?php "
"function foo() { return 42; }"
"$a = foo();"
"var_dump((unset)foo());"
"var_dump((unset)$a);"
"var_dump($a);");
MVCR("<?php "
"function return_true() { return true; }\n"
"function f(&$x, $y) {\n"
" $x = $y;\n"
" if (return_true())\n"
" unset($x);\n"
" $x = 0;\n"
"}\n"
"$myvar = 10;f($myvar, 30);var_dump($myvar);");
MVCR("<?php\n"
"$a = array(0, 1);\n"
"$b = array(0, 1);\n"
"$a[0] =& $b;\n"
"$c =& $a;\n"
"unset($a[0][0]);\n"
"var_dump($a);\n");
MVCR("<?php\n"
"class A {\n"
" public function foo() {\n"
" unset($this);\n"
" var_dump($this);\n"
" }\n"
" public static function bar() {\n"
" unset($this);\n"
" var_dump($this);\n"
" }\n"
"}\n"
"function goo() {\n"
" unset($this);\n"
" var_dump($this);\n"
"}\n"
"$obj = new A;\n"
"$obj->foo(); \n"
"$obj->bar();\n"
"A::bar();\n"
"goo();\n"
"unset($this);\n"
"var_dump($this);\n");
MVCR("<?php "
"function rmv($a, $b) { unset($a[$b]); return $a; }"
"$a = array('foo');"
"$b = array();"
"var_dump(rmv($a, $b));");
MVCR("<?php\n"
"class cls {}\n"
"$obj = new cls;\n"
"$a = array(1,2);\n"
"unset($a[$obj]);\n"
"var_dump($a);\n");
MVCR("<?php\n"
"$a = array(1,2);\n"
"unset($a[1.5]);\n"
"var_dump($a);\n");
MVCR("<?php\n"
"$a = array(1,2);\n"
"unset($a[false]);\n"
"var_dump($a);\n");
MVCR("<?php\n"
"$a = array(1,2);\n"
"unset($a[true]);\n"
"var_dump($a);\n");
MVCR("<?php\n"
"$a = array(1,2, '' => 'foo');\n"
"unset($a[null]);\n"
"var_dump($a);\n");
return true;
}
bool TestCodeRun::TestReference() {
MVCR("<?php $idxa = array('a' => 1240430476);"
"$idxa = &$idxa['a'];");
MVCR("<?php $a = array(1, 'a'); $b = $a; "
"foreach ($b as $k => &$v) { $v = 'ok';} var_dump($a, $b);");
MVCR("<?php $a = array(1, 'test'); $b = $a; $c = &$b[0]; "
"$c = 10; var_dump($a, $b);");
// reference expressions
MVCR("<?php $a = &$b; $a = 10; var_dump($b);");
MVCR("<?php $a = 1; $b = $a; $a = 2; var_dump($b);");
MVCR("<?php $a = 1; $b = &$a; $c = $b; $a = 2; var_dump($b); var_dump($c);");
MVCR("<?php $a = 1; $b = &$a; $b = 2; var_dump($a);");
MVCR("<?php $a = 1; $b = &$a; $c = $b; $b = 2; var_dump($a); var_dump($c);");
MVCR("<?php $a = 1; $c = $b = &$a; $b = 2; var_dump($a); var_dump($c);");
MVCR("<?php $a = 1; $b = &$a; $c = 2; $b = $c; $c = 5; "
"var_dump($a); var_dump($b); var_dump($c);");
MVCR("<?php $a = 1; $b = &$a; $c = 2; $d = &$c; $b = $d; "
"var_dump($a); var_dump($b); var_dump($c); var_dump($d);");
MVCR("<?php $a = 1; $b = &$a; $c = 2; $d = &$c; $b = &$d; "
"var_dump($a); var_dump($b); var_dump($c); var_dump($d);");
MVCR("<?php $a = 10; $b = array(&$a); var_dump($b); "
"$a = 20; var_dump($b);");
MVCR("<?php $a = array(); $b = 10; $a[] = &$b; $b = 20; var_dump($a);");
MVCR("<?php $a = 10; $b = array('test' => &$a); var_dump($b); "
"$a = 20; var_dump($b);");
MVCR("<?php $a = array(); $b = 1; $a['t'] = &$b; $b = 2; var_dump($a);");
MVCR("<?php $a = array(1, 2); foreach ($a as $b) { $b++;} var_dump($a);");
MVCR("<?php $a = array(1, 2); foreach ($a as &$b) { $b++;} var_dump($a);");
MVCR("<?php $a = array(1, array(2,3)); "
"foreach ($a[1] as &$b) { $b++;} var_dump($a);");
// reference parameters
MVCR("<?php function f(&$a) { $a = 'ok';} "
"$a = 10; f($a); var_dump($a);");
MVCR("<?php function f(&$a) { $a = 'ok';} "
"$a = array(); $c = &$a['b']; $c = 'ok'; var_dump($a);");
MVCR("<?php function f(&$a) { $a = 'ok';} "
"$a = array(); $c = &$a['b']; f($c); var_dump($a);");
MVCR("<?php function f(&$a) { $a = 'ok';} "
"$a = array(); f($a['b']); var_dump($a);");
MVCR("<?php function f(&$a) { $a = 'ok';} class T { public $b = 10;} "
"$a = new T(); $a->b = 10; f($a->b); var_dump($a);");
MVCR("<?php function f(&$a) { $a = 'ok';} class T {} "
"$a = new T(); $a->b = 10; f($a->b); var_dump($a);");
MVCR("<?php function f(&$a) {} "
"$a = array(); f($a['b']); var_dump($a);");
MVCR("<?php function f(&$a) {} class T {} "
"$a = new T(); $a->b = 10; f($a->b); var_dump($a);");
// reference returns
MVCR("<?php $a = 10; function &f() { global $a; return $a;} "
"$b = &f(); $b = 20; var_dump($a);");
MVCR("<?php function &f() { $a = 10; return $a;} "
"$b = &f(); $b = 20; var_dump($b);");
MVCR("<?php $a = array(); function &f() { global $a; return $a['b'];} "
"$b = &f(); $b = 20; var_dump($a);");
MVCR("<?php function &f() { $a = array(); return $a['b'];} "
"$b = &f(); $b = 20; var_dump($b);");
// circular references
//VCR("<?php $a = array('a' => &$a); var_dump($a);");
//VCR("<?php $a = array('a' => &$a); $b = array($a); var_dump($b);");
MVCR("<?php\n"
"$a1 = array(&$a1, 1); $a2 = $a1; unset($a1);\n"
"$a2[0][] = 2;\n"
"var_dump($a2[0][0][0][2]);\n");
// shallow copy of members (either of arrays or objects)
MVCR("<?php function test($a) { $a[1] = 10; $a['r'] = 20;} "
"$b = 5; $a = array('r' => &$b); $a['r'] = 6; test($a); var_dump($a);");
MVCR("<?php "
"$a = array('a'=>0);"
"$ref = &$a['a'];"
"var_dump($a);"
"$b = $a;"
"var_dump($a,$b);"
"$b['a'] = 1;"
"var_dump($a,$b);"
"$a = array(0);"
"$ref = &$a[0];"
"var_dump($a);"
"$b = $a;"
"var_dump($a,$b);"
"$b[0] = 1;"
"var_dump($a,$b);"
);
if (!hhvm) {
// call-time pass by reference -- not supported in the VM
MVCRNW("<?php "
"function foo($u, $v, $w) {"
" $u = 10;"
" $v = 20;"
" $w = 20;"
"}"
"$u = 1;"
"$v = 2;"
"$w = 3;"
"foo(&$u, &$v, $w);"
"var_dump($u, $v, $w);");
}
// reference self assignment
MVCR("<?php "
"class A {"
" function t($a, $arr) {"
" }"
"}"
"class B extends A {"
" function t($a, $arr) {"
" var_dump($a);"
" $arr['hello'] = $a;"
" var_dump($a);"
" }"
"}"
"function f() {"
" return new B();"
"}"
"function test() {"
" $v = 100;"
" $arr['hello'] = $v;"
" $a = new B();"
" $a->t($arr['hello'], $arr);"
"}"
"test();"
"$arr = array('hello' => 1);"
"$x = &$arr['hello'];"
"$arr['hello'] = $x;"
"var_dump($arr);"
"function test2(&$a, $b) {"
" $a = $b;"
"}"
"$v = 10;"
"test2($v, $v);"
"var_dump($v);");
// reference, parameter & assignment
MVCR("<?php "
"function test(&$some_ref) {"
" $some_ref = 42;"
"}"
"test($some_ref = 1);"
"var_dump($some_ref);"
"$var = null;"
"test($var);"
"var_dump($var);"
"$var = null;"
"test($some_ref = $var);"
"var_dump($some_ref, $var);"
"$var = null;"
"test($some_ref = &$var);"
"var_dump($some_ref, $var);"
"function test2($some_ref) {"
" $some_ref = 42;"
"}"
"test2($some_ref = 1);"
"var_dump($some_ref);"
"$var = null;"
"test2($var);"
"var_dump($var);"
"$var = null;"
"test2($some_ref = $var);"
"var_dump($some_ref, $var);"
"$var = null;"
"test2($some_ref = &$var);"
"var_dump($some_ref, $var);");
MVCR("<?php "
"$foo = 123;"
"function &baz() {"
" global $foo;"
" return $foo;"
"}"
"function bar() {"
" $baz = 'baz';"
" return $baz();"
"}"
"function buz() {"
" global $foo;"
" return ($foo);"
"}"
"$a = &bar();"
"$a = 456;"
"var_dump($a, $foo);"
"$a = &buz();"
"$a = 789;"
"var_dump($a, $foo);");
MVCR("<?php "
"function &test(&$x) {"
" $x = 1;"
" return $x;"
"}"
"$x = 0;"
"$y = &test($x);"
"$y++;"
"var_dump($x, $y);");
MVCR("<?php "
"function foo(&$a) { var_dump($a++); }"
"function test() {"
" foo($a = 6);"
" $a = null;"
" foo($b += 5);"
" $b = null;"
" foo($c -= 5);"
" $c = null;"
" $e = 0;"
" foo(++$e);"
" $e = 5;"
" $g = 0;"
" foo(--$g);"
" $g = 7;"
" $h = null;"
" foo($h += 5);"
" $h = null;"
" foo($h -= 5);"
" $h = null;"
"}"
"test();");
MVCR("<?php "
"function foo() {"
" $perms = array('x' => 1);"
" $t = &$perms;"
" $t = $t['x'];"
" unset($t);"
" return $perms;"
"}"
"var_dump(foo());");
MVCR("<?php "
"$a = array();"
"$a[0][0] = $a;"
"var_dump($a);"
"$b[0][0] = $b;"
"var_dump($b);"
"$c[0] = $c;"
"var_dump($c);");
MVCR("<?php "
"function foo($x) {"
" var_dump($x[0]->foo['a']['b']);"
" $x[0]->foo['a']['b'] = 5;"
" var_dump($x);"
"}"
"foo(false);"
"function baz(&$x) {}"
"foreach ($x->foo[1]->prop as &$y) {}"
"var_dump($x);"
"baz($q->foo[1]->prop);"
"var_dump($q);"
"$y = &$z->foo[1]->prop;"
"var_dump($z);"
"function &fiz(&$x) {"
" return $x->foo[1]->prop;"
"}"
"fiz($w);"
"var_dump($w);");
MVCR("<?php "
"$x = 0;\n"
"$foo0 = isset($g) ? \"ref\" : \"val\";\n"
"$foo1 = isset($g) ? \"val\" : \"ref\";\n"
"function ref(&$a, $b) { echo \"$a $b\"; }\n"
"function val($a, $b) { echo \"$a $b\"; }\n"
"$foo0($x, $x = 5);\n"
"$foo1($x, $x = 5);\n");
MVCR("<?php\n"
"function f($arg0, $arg1) { var_dump($arg0, $arg1); }\n"
"function g(&$arg0, $arg1) { var_dump($arg0, $arg1); }\n"
"class A {\n"
" function f($f, $var) {\n"
" $f($this, $$var = 5);\n"
" }\n"
" function g($f, $var) {\n"
" $f($this, $var++);\n"
" }\n"
"}\n"
"$a = new A;\n"
"$a->f('f', 'this');\n"
"$a->f('g', 'this');\n"
"$a->g('f', 30);\n"
"$a->g('g', 30);\n");
MVCR("<?php "
"function foo($a, &$b, $c) {"
" $a+=1;"
" $b+=2;"
" $c+=3;"
" var_dump($a,$b,$c);"
"}"
"function bar(&$a, &$b, &$c) {"
" $a+=1;"
" $b+=2;"
" $c+=3;"
" var_dump($a,$b,$c);"
"}"
"function test($fn, $arg) {"
" $fn($arg, $arg, $arg);"
" var_dump($arg);"
"}"
"test('foo', 1);"
"test('bar', 1);");
MVCR("<?php "
"class X {"
" public $x = 10;"
" function __destruct() {"
" var_dump('destruct');"
" $this->x = 0;"
" }"
"}"
"function test(&$a, $b) {"
" var_dump($a, $b);"
"}"
"function f($x) {"
" unset($GLOBALS['a']);"
" return 1;"
"}"
"$a = array(new X);"
"test($a[0], f(1));");
MVCR("<?php "
"function test(&$some_ref) { $some_ref = 42; }"
"function bar() { return 'test'; }"
"$p = bar();"
"$p($some_ref = 1);"
"var_dump($some_ref);"
"$p($some_ref = &$q);"
"var_dump($some_ref,$q);");
MVCR("<?php "
"function foo(&$x, $y) { $x++; var_dump($x); }"
"function bar(&$x, $y, $f) {"
" $f($x, $x = &$y);"
" foo($x, $x = &$y);"
" foo($y, $y = 2);"
"}"
"$x = 0;"
"bar($x, $x, 'foo');"
"var_dump($x);");
MVCR("<?php "
"function f($x) {"
" global $u;"
" if (isset($u)) return null;"
" return $x;"
"}"
"function test($a) {"
" $a++;"
" return $a;"
"}"
"function &foo() {"
" return $GLOBALS['x'];"
"}"
"$x = 1;"
"test(foo());"
"var_dump($x);"
"$f = f('foo');"
"$x = 1;"
"test($f());"
"var_dump($x);"
"$t = f('test');"
"$x = 1;"
"$t(foo());"
"var_dump($x);");
MVCR("<?php "
"function test() {"
" $x =& $y;"
" $x = false;"
" $y .= 'hello';"
" echo $x;"
"}"
"test();");
return true;
}
bool TestCodeRun::TestDynamicConstants() {
MVCR("<?php function foo($a) { return $a + 10;} define('TEST', foo(10)); "
"var_dump(TEST);");
MVCR("<?php function foo() { global $g; return $g ? -1 : 15;} "
"var_dump(TEST); define('TEST', foo()); var_dump(TEST);");
MVCR("<?php if (true) define('TEST', 1); else define('TEST', 2); "
"var_dump(TEST);");
MVCR("<?php var_dump(TEST); define('TEST', 1); var_dump(TEST); "
"define('TEST', 2); var_dump(TEST);");
MVCR("<?php if (false) define('TEST', 1); else define('TEST', 2); "
"var_dump(TEST);");
MVCR("<?php var_dump(defined('TEST')); var_dump(TEST);"
"define('TEST', 13);"
"var_dump(defined('TEST')); var_dump(TEST);");
MVCR("<?php define('FOO', BAR); define('BAR', FOO); echo FOO; echo BAR;");
MVCR("<?php define('A', 10); class T { static $a = array(A); } "
"define('A', 20); var_dump(T::$a);");
return true;
}
bool TestCodeRun::TestDynamicVariables() {
// r-value
MVCR("<?php $a = 1; function t() { global $a;$b = 'a'; var_dump($$b);} t();");
MVCR("<?php $a = 1; function t() { $b = 'a'; var_dump($$b);} t();");
MVCR("<?php function t() { $a = 'test'; $b = 'a'; var_dump($$b);} t();");
MVCR("<?php $a = 'test'; $b = 'a'; var_dump($$b);");
MVCR("<?php $a = 1; class A { public function t() { global $a; $b = 'a'; var_dump($$b);}} $obj = new A(); $obj->t();");
// l-value
MVCR("<?php $a = 'test'; $b = 'a'; $$b = 'ok'; var_dump($a);");
MVCR("<?php $a = 'test'; $b = 'a'; $$b = 10; var_dump($a);");
MVCR("<?php $a = 'd'; var_dump($$a); $$a = 10; var_dump($$a); var_dump($d);");
// ref-value
MVCR("<?php $a = 'test'; $b = 'a'; $c = &$$b; $c = 10; var_dump($a);");
// extract
MVCR("<?php extract(array('a' => 'aval')); var_dump($a);");
MVCR("<?php extract(array('a' => 'ok')); $a = 1; var_dump($a);");
MVCR("<?php $a = 1; extract(array('a' => 'ok'), EXTR_SKIP); var_dump($a);");
MVCR("<?php $a = 1; extract(array('a' => 'ok'), EXTR_PREFIX_SAME, 'p');"
" var_dump($p_a);");
MVCR("<?php extract(array('a' => 'ok'), EXTR_PREFIX_ALL, 'p');"
" var_dump($p_a);");
MVCR("<?php extract(array('ok'), EXTR_PREFIX_INVALID, 'p'); var_dump($p_0);");
MVCR("<?php $a = null; extract(array('a' => 'ok'), EXTR_IF_EXISTS); var_dump($a);");
MVCR("<?php $a = null; extract(array('a' => 'ok', 'b' => 'no'), EXTR_PREFIX_IF_EXISTS, 'p'); var_dump($p_a); var_dump($b); var_dump($p_b);");
MVCR("<?php $a = 'ok'; extract(array('b' => &$a), EXTR_REFS); $b = 'no'; var_dump($a);");
MVCR("<?php $a = 'ok'; $arr = array('b' => &$a); extract($arr, EXTR_REFS); $b = 'no'; var_dump($a);");
MVCR("<?php\n"
"function f() {\n"
" $arr = array(1 => 2, '1d' => 3);\n"
" extract($arr);\n"
" $vars = get_defined_vars(); asort($vars); var_dump($vars);\n"
"}\n"
"f();\n");
MVCR("<?php\n"
"$a = 123;\n"
"$b = 456;\n"
"function foo() {\n"
" global $a;\n"
" $b = &$GLOBALS['b'];\n"
" $d = 789; $e = 111;\n"
" $c = &$d;\n"
" $arr = get_defined_vars(); ksort($arr); var_dump($arr); return $arr;\n"
"}\n"
"function bar($arr) {\n"
" extract($arr, EXTR_REFS);\n"
" var_dump($a, $b, $c, $d, $e);\n"
" $a = 'aaa'; $b = 'bbb'; $c = 'ccc';\n"
" var_dump($d);\n"
"}"
"bar(foo());\n"
"var_dump($a, $b);\n"
);
// compact
MVCR("<?php function test() { $a = 10; $b = 'test'; "
" var_dump(compact('ab')); "
" var_dump(compact('a', 'ab', 'b')); "
" var_dump(compact('a', array('ab', 'b')));"
"} test(); ");
MVCR("<?php\n"
"function f() { return true; }\n"
"function test() {\n"
" $a = 100;\n"
" if (compact('a', 'b')) { }\n"
" var_dump(compact('a', 'b'));\n"
" if (f()) $b = 1; else $b = new Exception();\n"
" return $b;\n"
"}\n"
"test();\n");
MVCR("<?php "
"function f() { return 3; }"
"function test($f) {"
" $x = $f();"
" return compact('x');"
"}"
"var_dump(test('f'));");
MVCR("<?php\n"
"function foo($a) {\n"
" while ($a--) {\n"
" if (!$a) {\n"
" var_dump(compact('x', 'y'));\n"
" }\n"
" $x = $a;\n"
" $y = $a * $a;\n"
" }\n"
"}\n"
"foo(4);\n");
// get_defined_vars
MVCR("<?php\n"
"function simple_getdefined_test() {\n"
" $a = 'a';\n"
" var_dump(get_defined_vars());\n"
"}\n"
"simple_getdefined_test();\n"
);
MVCR("<?php "
"function foo() {"
" static $b = 20;"
" global $d;"
" $a = 10;"
" $b = 'c';"
" $$b = 20;"
" $gdv = get_defined_vars();"
" var_dump(isset($gdv['a']) && $gdv['a'] === 10);"
" var_dump(isset($gdv['b']) && $gdv['b'] === 'c');"
" var_dump(isset($gdv['c']) && $gdv['c'] === 20);"
" var_dump(isset($gdv['d']) && $gdv['d'] === 2.1);"
"}"
"$d = 2.1;"
"foo();"
"var_dump(isset($ggdv['argc']));"
"var_dump(isset($ggdv['argv']));"
"var_dump(isset($ggdv['_SERVER']));"
"var_dump(isset($ggdv['_GET']));"
"var_dump(isset($ggdv['_POST']));"
"var_dump(isset($ggdv['_COOKIE']));"
"var_dump(isset($ggdv['_FILES']));"
"var_dump(isset($ggdv['d']));"
);
MVCR("<?php "
"function foo(array $test) {"
" foreach ($test AS $var) {"
" global $$var;"
" $$var = $var . 'foo';"
" }"
"}"
"foo(array('a', 'b'));"
"var_dump($a, $b);");
MVCR("<?php "
"function test($a) {"
" $b = 5;"
" global $$a;"
" var_dump($b);"
"}"
"test('b');");
MVCR("<?php "
"$x = 'stuff';"
"$stuff = 1234;"
"echo \"${$x}\";");
MVCR("<?php "
"$i = 1;"
"$j = 2;"
"$k = 3;"
"$v = 'i';"
"var_dump($$v);"
"$v = 'j';"
"var_dump($$v);"
"$v = 'k';"
"var_dump($$v);"
"$v = '_FILES';"
"var_dump($$v);"
"$v = 'l';"
"var_dump($$v);"
"if (true) {"
" class A{"
" const C = 1;"
" }"
"} else {"
" class A{"
" const C = 1;"
" }"
"}"
"function foo($p) {"
" var_dump($p::C);"
"}"
"foo('A');");
MVCR("<?php\n"
"$MY_VAR_a = 123;\n"
"function foo() {\n"
" global $MY_VAR_a;\n"
" $arr = get_defined_vars();\n"
" asort($arr);\n"
" var_dump($arr);\n"
" return $arr;\n"
"}\n"
"foo();\n");
MVCR("<?php\n"
"function foo() {\n"
" $arr = get_defined_vars();\n"
" var_dump($arr);\n"
" return $arr;\n"
"}\n"
"foo();\n");
return true;
}
bool TestCodeRun::TestDynamicProperties() {
MVCR("<?php class A { public $a = 1;} "
"class B extends A { "
" public $m = 10;"
" public function test() { "
" $b = 'a';"
" $this->$b = 'test'; var_dump($this->$b); var_dump($this->a);"
" $c = &$this->$b; $c = array(1); var_dump($this->a);"
" }"
"} $obj = new B(); $obj->test();");
MVCR("<?php class A { public $a = 1;} class B { public $a = 2;} "
"$obj = 1; $obj = new A(); var_dump($obj->a);");
MVCR("<?php "
"class A { } "
"function f(&$a) { $a = 1000; } "
"$a = new A(); $f = 10; $a->$f = 100; var_dump($a); "
"var_dump((array)$a); "
"$f = 100; "
"f($a->$f); "
"foreach ($a as $k => &$v) { var_dump($k); $v = 1; } "
"var_dump($a); ");
return true;
}
bool TestCodeRun::TestDynamicFunctions() {
MVCR("<?php function test() { print 'ok';} $a = 'Test'; $a();");
MVCR("<?php function test($a) { print $a;} $a = 'Test'; $a('ok');");
MVCR("<?php function test($a, $b) { print $a.$b;} $a = 'Test'; $a('o','k');");
MVCR("<?php function t($a = 'k') { print $a;} "
"$a = 'T'; $a(); $a('o');");
MVCR("<?php function t($a, $b = 'k') { print $a.$b;} "
"$a = 'T'; $a('o'); $a('o', 'p');");
MVCR("<?php function t($a, $b = 'k', $c = 'm') { print $a.$b.$c;} "
"$a = 'T'; $a('o'); $a('o', 'p'); $a('o', 'p', 'q');");
MVCR("<?php function test() { var_dump(func_get_args());} "
"$a = 'Test'; $a();");
MVCR("<?php function test($a) { var_dump(func_get_args());} "
"$a = 'Test'; $a(1); $a(1, 2);");
MVCR("<?php function test($a, $b) { var_dump(func_get_args());} "
"$a = 'Test'; $a(1, 2); $a(1, 2, 3); $a(1, 2, 3, 4);");
MVCR("<?php function t($a = 'k') { var_dump(func_get_args());} "
"$a = 'T'; $a(); $a('o'); $a('o', 'p'); $a('o', 'p', 'q');");
MVCR("<?php function t($a, $b = 'k') { var_dump(func_get_args());} "
"$a = 'T'; $a('o'); $a('o', 'p'); $a('o', 'p', 'q');");
MVCR("<?php function t($a, $b = 'k', $c = 'q') { var_dump(func_get_args());} "
"$a = 'T'; $a('o'); $a('o', 'p'); $a('o', 'p', 'q');");
MVCR("<?php function test(&$a, $b) { $a = 'ok';} $a = 'Test'; "
"$a($a, 10); print $a;");
MVCR("<?php $a = 'test'; function &test() { global $a; return $a;} "
" $b = $a(); $b = 'ok'; var_dump($a); "
" $b = &$a(); $b = 'ok'; var_dump($a);");
MVCR("<?php function test($a, $b) { print $a.$b;} $a = 'Test'; $y = 'kqq'; "
"$a('o',$y[0]);");
MVCR("<?php function test($a, $b) { print $a.$b;} $a = 'Test'; "
"$y = array('k','q','q'); $a('o',$y[0]);");
MVCR("<?php "
"$a = 'test';"
"if ($a) {"
" function bar() {}"
"} else {"
" function bar() {}"
"}"
"function foo() {}"
"function goo(&$p) {}"
"$goo = 'goo';"
"goo(foo());"
"$goo(foo());"
"bar(foo());");
// Test dynamically calling a builtin that is RefVariableArguments
MVCR("<?php "
"if ($argc > 100) { $f = 'var_dump'; } else { $f = 'sscanf'; }"
"$auth = \"24\\tLewis Carroll\";"
"$n = $f($auth, \"%d\\t%s %s\", $id, $first, $last);"
"echo \"$id,$first,$last\\n\";");
// Test dynamically calling a builtin that is MixedVariableArguments
MVCR("<?php "
"function bar($flag) {"
" $arr = array(array('b' => 3, 'a' => 2, 'c' => 1),"
" array('x' => 6, 'y' => 4, 'z' => 5),"
" array('p' => 8, 'q' => 9, 'r' => 7));"
" if ($flag) { $f = 'var_dump'; } else { $f = 'array_multisort'; }"
" $f($arr[0], $arr[1], $arr[2]);"
" var_dump($arr);"
"}"
"bar($argc > 100);");
return true;
}
bool TestCodeRun::TestRenameFunction() {
OptionSetter w0(this, OptionSetter::CompileTime,
"-vDynamicInvokeFunctions.*=test1 "
"-vDynamicInvokeFunctions.*=test2");
OptionSetter w1(this, OptionSetter::RunTime,
"-vEval.JitEnableRenameFunction=true");
MVCRO("<?php "
"function test1() { print __FUNCTION__;} "
"function test2() { print __FUNCTION__;} "
"fb_rename_function('test2', 'test3');"
"fb_rename_function('test1', 'test2'); teSt2();"
"fb_rename_function('test2', 'test3'); teSt2();"
,
"test1test1"
);
MVCRO("<?php\n"
"function one() { echo 'one';}\n"
"fb_rename_function('one', 'two');\n"
"fb_rename_function('two', 'three');\n"
"three();",
"one");
MVCRO("<?php "
"function test1() { echo \"test1\n\"; }"
"function test3() { echo \"test3\n\"; }"
"function baz($test1, $test2) {"
" var_dump(function_exists(\"Test1\"));"
" var_dump(function_exists(\"tEst2\"));"
" var_dump(function_exists($test1));"
" var_dump(function_exists($test2));"
"}"
"baz(\"teSt1\", \"test2\");"
"fb_rename_function(\"test1\", \"test2\");"
"baz(\"TEst1\", \"test2\");"
"fb_rename_function(\"test3\", \"test1\");"
"baz(\"test1\", \"test2\");"
"test1();"
"test2();",
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"test3\n"
"test1\n");
MVCRO("<?php\n"
"function one() { echo 'one';}\n"
"fb_renamed_functions(array('one', 'three'));\n"
"var_dump(fb_rename_function('one', 'two'));\n",
"bool(true)\n");
MVCR("<?php "
"function err($code,$msg) { var_dump($code,$msg); }"
"set_error_handler('err');"
"function test1() {}"
"function test2() {}"
"fb_rename_function('test1', 'test3');"
"fb_rename_function('test2', 'test1');"
"fb_rename_function('test1', 'test2');"
"fb_rename_function('test3', 'test1');");
MVCRO("<?php "
"function test1() {"
" var_dump(__METHOD__);"
"}"
"function test2() {"
" var_dump(__METHOD__);"
"}"
"function test($test) {"
" test1();"
" TeSt1();"
" $test();"
" $test = strtolower($test);"
" $test(1,2,3);"
"}"
"test('Test1');"
"fb_rename_function('tEst1', 'fiz');"
"fb_rename_function('test2', 'Test1');"
"test('teSt1');",
"string(5) \"test1\"\n"
"string(5) \"test1\"\n"
"string(5) \"test1\"\n"
"string(5) \"test1\"\n"
"string(5) \"test2\"\n"
"string(5) \"test2\"\n"
"string(5) \"test2\"\n"
"string(5) \"test2\"\n");
return true;
}
bool TestCodeRun::TestIntercept() {
OptionSetter w0(this, OptionSetter::Env, "ENABLE_INTERCEPT=1");
OptionSetter w1(this, OptionSetter::RunTime,
"-vEval.JitEnableRenameFunction=true");
MVCRO("<?php "
"$a = 10; $b = 20;"
"function &foo(&$n, $p) { global $a; $n = 123; $p += 1; "
" var_dump('foo');"
"return $a;}"
"function &bar(&$n, $p) { global $b; $n = 456; $p += 2; "
" var_dump('bar');"
"return $b;}"
"fb_intercept('foo', 'fb_stubout_intercept_handler', 'bar');"
"$n = 0; $d = 3; $c = &foo($n, $d); var_dump($c, $d); $c = 30;"
//"var_dump($a, $b, $n);"
,
"string(3) \"bar\"\nint(20)\nint(3)\n"
//"int(10)\nint(30)\nint(456)\n"
);
MVCRO("<?php "
"$a = 10; $b = 20;"
"class A {"
"function &foo(&$n, $p) { global $a; $n = 123; $p += 1; "
" var_dump('foo');"
"return $a;}"
"}"
"class B {"
"function &bar(&$n, $p) { global $b; $n = 456; $p += 2; "
" var_dump('bar');"
"return $b;}"
"}"
"fb_intercept('A::foo', 'fb_stubout_intercept_handler', 'B::bar');"
"$n = 0; $d = 3; $c = &A::foo($n, $d); var_dump($c, $d); $c = 30;"
//"var_dump($a, $b, $n);"
,
"string(3) \"bar\"\nint(20)\nint(3)\n"
//"int(10)\nint(30)\nint(456)\n"
);
MVCRO("<?php "
"function foo(&$a) {"
" var_dump('foo');"
" $a = 1;"
"}"
"function bar(&$a) {"
" var_dump('bar');"
" $a = 2;"
"}"
"function goo($name, $obj, $params, $data, &$done) {"
" return call_user_func_array($data, $params);"
"}"
"fb_intercept('foo', 'goo', 'bar');"
"$a = 0;"
"foo($a);"
"var_dump($a);",
"string(3) \"bar\"\n"
"int(2)\n");
MVCRO("<?php "
"function test() {"
" define('X', 2);"
" define('Y', 3);"
" fb_intercept('foo', 'bar');"
" var_dump(X);"
" define('Y', 4);"
" var_dump(Y);"
"}"
"test();",
"int(2)\n"
"int(3)\n");
MVCRO("<?php"
"class X {"
" static function foo() { global$g; return $g; }"
"}"
"function bar() {"
" var_dump('Intercepted');"
"}"
"function test() {"
" X::foo();"
" fb_intercept('X::foo', 'bar', 'bar');"
" X::foo();"
"}"
"test();",
"string(11) \"Intercepted\"\n");
return true;
}
bool TestCodeRun::TestMaxInt() {
MVCR("<?php "
"$val1 = ~PHP_INT_MAX; "
"$val2 = PHP_INT_MAX; "
"var_dump($val1); "
"var_dump($val2); "
);
return true;
}
bool TestCodeRun::TestDynamicMethods() {
OptionSetter w(this, OptionSetter::CompileTime, "-vAllDynamic=1");
MVCR("<?php "
"class A { public function test() { print 'in A';} } "
"class B extends A { public function test() { print 'in B';} } "
"$obj = new B(); "
"call_user_func_array(array($obj, 'A::test'), array());");
MVCR("<?php $i = 'gi'; $s = 'gs'; class A { "
"public function &dyn_test(&$a) { global $i; $a = $i; return $i;}} "
"$obj = new A(); $f = 'dyn_test'; "
"$c = &$obj->$f($b); var_dump($b); var_dump($c);");
MVCR("<?php $i = 'gi'; $s = 'gs'; class A { "
"public static function &dyn_test(&$a) "
"{ global $s; $a = $s; return $s;}} "
"$f = 'dyn_test'; $e = A::$f($d); var_dump($d); var_dump($e);");
MVCR("<?php class dyn_A{} class B{} $cls = 'dyn_a'; $a = new $cls();");
MVCR("<?php class A { function _test() { print 'ok';} "
"function __call($name, $args) { $name = '_'.$name; $this->$name();} } "
"$obj = new A(); $obj->test();");
MVCR("<?php class A { function test($a, $b) { var_dump($a, $b);} } "
"$m = 'test'; $o = new A();"
"$ar = array(0,1); $st = 'abc';"
"$o->$m($ar[0], $st[0]); A::$m($ar[1], $st[1]);");
{
OptionSetter w(this, OptionSetter::CompileTime,
"-v DynamicMethodPrefix.*=_");
MVCR("<?php class A { function _test() { print 'ok';} "
"function __call($name, $args) { $name = '_'.$name; $this->$name();} }"
"$obj = new A(); $obj->test();");
}
MVCR("<?php "
"class z {"
" function minArgTest($a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $a10,"
" $a11=true, $a12 = true) {"
" var_dump($a1);"
" var_dump($a2);"
" var_dump($a3);"
" var_dump($a4);"
" var_dump($a5);"
" var_dump($a6);"
" var_dump($a7);"
" var_dump($a8);"
" var_dump($a9);"
" var_dump($a10);"
" var_dump($a11);"
" var_dump($a12);"
" }"
" function varArgsTest() {"
" $args = func_get_args();"
" var_dump($args);"
" }"
" function varArgsTest2($a1, $a2) {"
" $args = func_get_args();"
" var_dump($args);"
" }"
" function refTestHelper(&$x) {"
" $x *= 2;"
" }"
"}"
"function refTest($q) {"
" if (false) { $q = 1; }"
" $x = 1;"
" $q->refTestHelper($x);"
" var_dump($x);"
"}"
"$q = new z;"
"$f = 'minArgTest';"
"$q->minArgTest('one',2,3.333,4,5,6,7,8,9,10);"
"$q->minArgTest('one',2,3.333,4,5,6,7,8,9,10,11,12);"
"$q->$f('one',2,3.333,4,5,6,7,8,9,10);"
"$q->$f('one',2,3.333,4,5,6,7,8,9,10,11,12);"
"refTest($q);"
"$f = 'varArgsTest';"
"$q->varArgsTest('one',2,3.333,4,5,6,7,8,9,10);"
"$q->varArgsTest('one',2,3.333,4,5,6,7,8,9,10,11,12);"
"$q->$f('one',2,3.333,4,5,6,7,8,9,10);"
"$q->$f('one',2,3.333,4,5,6,7,8,9,10,11,12);"
"$f = 'varArgsTest2';"
"$q->varArgsTest2('one',2,3.333,4,5,6,7,8,9,10);"
"$q->varArgsTest2('one',2,3.333,4,5,6,7,8,9,10,11,12);"
"$q->$f('one',2,3.333,4,5,6,7,8,9,10);"
"$q->$f('one',2,3.333,4,5,6,7,8,9,10,11,12);");
MVCR("<?php "
"class z {"
" function __construct() { echo 'construct'; }"
" function z() { echo 'method'; }"
"}"
"$z = new z;"
"$z->z();");
MVCR("<?php "
"function bar() {"
" echo 'bar called';"
"}"
"class foo {"
" public $functions = array();"
" function foo() {"
" $function = 'bar';"
" print($function);"
" print($function());"
" $this->functions['test'] = $function;"
" print($this->functions['test']());"
" }"
"}"
"$a = new foo ();");
MVCR("<?php "
"function t($x) {"
" var_dump($x);"
"}"
"$x = array(1,2,3);"
"array_map('t', $x);"
"class z {"
" function q() {"
" $x = array(1,2,3);"
" array_map(array('self', 'p'), $x);"
" }"
" function p($x) {"
" var_dump($x);"
" }"
"}"
"$m = new z();"
"$m->q();");
MVCR("<?php "
"class A {"
" function foo(&$test) {"
" $test = 10;"
" }"
"}"
"$obj = new A();"
"$method = 'foo';"
"$obj->$method($aa[3]);"
"var_dump($aa);");
MVCR("<?php "
"abstract class Parent_ {"
" protected function overridden() {"
" var_dump(isset($this), __METHOD__);"
" }"
" protected function calledHere() {"
" if (isset($this)) {"
" $this->overridden();"
" } else {"
" static::overridden();"
" }"
" }"
"}"
"class Child extends Parent_ {"
" protected final function overridden() {"
" var_dump(isset($this), __METHOD__);"
" }"
" protected function calledHere() {"
" var_dump(__METHOD__);"
" }"
" public function entry($fun = 'calledHere') {"
" self::callParent($fun);"
" }"
" function callParent($fun) {"
" parent::$fun();"
" if (isset($this)) {"
" $this::$fun();"
" }"
" }"
"}"
"$c = new Child;"
"$c->entry();"
"$c->entry('overridden');"
"Child::entry();"
"Child::callParent('calledHere');"
"Child::callParent('overridden');");
return true;
}
bool TestCodeRun::TestVolatile() {
MVCR("<?php "
"for ($i = 0; $i < 4; $i++) {"
" if ($i > 1 && !defined('CON')) {"
" define(/*|Dynamic|*/'CON', 1);"
" }"
" if (defined('CON')) {"
" var_dump(CON);"
" } else {"
" echo \"CON does not exists\\n\";"
" }"
"}"
"for ($i = 0; $i < 4; $i++) {"
" if ($i > 1 && !function_exists('foo')) {"
" function foo() {"
" echo \"foo called\\n\";"
" }"
" }"
" if (function_exists('foo')) {"
" foo();"
" } else {"
" echo \"foo does not exists\\n\";"
" }"
"}"
"for ($i = 0; $i < 4; $i++) {"
" if ($i > 1 && !class_exists('bar')) {"
" class bar {"
" function bar() { echo \"bar called\\n\"; }"
" }"
" }"
" if (class_exists('bar')) {"
" $a = new bar;"
" } else {"
" echo \"bar does not exists\\n\";"
" }"
"}");
MVCR("<?php "
"function bar() {"
" for ($i = 0; $i < 4; $i++) {"
" if ($i > 1 && !function_exists('foo')) {"
" function foo() {"
" echo \"foo called\\n\";"
" }"
" }"
" $foo = 'foo';"
" if (function_exists($foo)) {"
" foo();"
" } else {"
" echo \"foo does not exists\\n\";"
" }"
" }"
" for ($i = 0; $i < 4; $i++) {"
" if ($i > 1 && !class_exists('goo')) {"
" class goo {"
" function goo() {"
" echo \"goo called\\n\";"
" }"
" }"
" }"
" $goo = 'goo';"
" if (class_exists($goo)) {"
" $a = new goo();"
" } else {"
" echo \"goo does not exists\\n\";"
" }"
" }"
"}"
"if (function_exists('bar')) bar();"
"$a = 'bar';"
"if (function_exists($a)) bar();"
"$a = 'later';"
"if (function_exists($a)) {"
" echo \"later exists\\n\";"
"} else {"
" echo \"later does not exists\\n\";"
"}"
"$a = 'later2';"
"if (class_exists($a)) {"
" echo \"later2 exists\\n\";"
"} else {"
" echo \"later2 does not exists\\n\";"
"}"
"$a = 'later3';"
"if (function_exists($a)) {"
" echo \"later3 exists\\n\";"
"} else {"
" echo \"later3 does not exists\\n\";"
"}"
"$a = 'later4';"
"if (class_exists($a)) {"
" echo \"later4 exists\\n\";"
"} else {"
" echo \"later4 does not exists\\n\";"
"}"
"function later3() {"
" echo \"later3 called\\n\";"
"}"
"class later4 {"
"}"
"if (function_exists('function_exists')) {"
" echo \"yes\\n\";"
"}"
"if (class_exists('exception')) {"
" echo \"yes\\n\";"
"}");
MVCR("<?php "
"function foo() {"
" if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {"
" define('Auth_OpenID_NO_MATH_SUPPORT', true);"
" }"
"}"
"function bar() {"
" return defined('Auth_OpenID_NO_MATH_SUPPORT');"
"}"
"if (defined('M_PI')) {"
" var_dump(bar());"
" foo();"
" var_dump(bar());"
"}");
MVCR("<?php "
"function foo() {"
" if (!interface_exists('MyInterface')) {"
" interface MyInterface{};"
" echo 'no';"
" } else {"
" echo 'yes';"
" }"
"}"
"foo();"
"foo();");
MVCR("<?php "
"function foo() {"
" if (function_exists('bar')) {"
" echo \"yes\\n\";"
" } else {"
" echo \"no\\n\";"
" }"
" function bar() {"
" echo \"bar\\n\";"
" }"
" if (function_exists('bar')) {"
" echo \"yes\\n\";"
" } else {"
" echo \"no\\n\";"
" }"
"}"
"foo();");
MVCR("<?php "
"function foo() {"
" if (class_exists('bar')) {"
" echo \"yes\\n\";"
" } else {"
" echo \"no\\n\";"
" }"
" class bar {"
" }"
" if (class_exists('bar')) {"
" echo \"yes\\n\";"
" } else {"
" echo \"no\\n\";"
" }"
"}"
"foo();");
// Autoloading
MVCR("<?php "
"function z() {"
" var_dump('__autoload');"
" var_dump(class_exists('cNew'));"
" var_dump(class_exists('cNew_r'));"
" var_dump(class_exists('cNew_d'));"
" var_dump(class_exists('csm'));"
" var_dump(class_exists('csm_r'));"
" var_dump(class_exists('CcOn'));"
" var_dump(class_exists('CcOn_r'));"
" var_dump(class_exists('CcOn_d'));"
" var_dump(class_exists('csmeth'));"
" var_dump(class_exists('csmeth_r'));"
" var_dump(class_exists('csmeth_d'));"
" var_dump(class_exists('cpar'));"
" var_dump(class_exists('cpar_r'));"
" var_dump(class_exists('cref'));"
" var_dump(class_exists('cex'));"
"}"
"function test() {"
" function t1() {"
" new cNew();"
" }"
" t1();"
" function t2() {"
" new cNew_r();"
" }"
" t2();"
" function t4() {"
" $x = 'cNew_d';"
" new $x();"
" }"
" t4();"
" function t5() {"
" var_dump(csm::$mem);"
" }"
" t5();"
" function t6() {"
" var_dump(csm_r::$mem);"
" }"
" t6();"
" function t7() {"
" var_dump(CcOn::C);"
" }"
" t7();"
" function t8() {"
" var_dump(CcOn_r::C);"
" }"
" t8();"
" function t9() {"
" var_dump(constant('CcOn_d::C'));"
" }"
" t9();"
" function t10() {"
" csmeth::m();"
" }"
" t10();"
" function t11() {"
" csmeth_r::m();"
" }"
" t11();"
" function t12() {"
" call_user_func(array('csmeth_d', 'm'));"
" }"
" t12();"
" function t13() {"
" class a extends cpar {}"
" new a;"
" }"
" t13();"
" function t14() {"
" class b extends cpar_r {}"
" new b;"
" }"
" t14();"
" function t15() {"
" new ReflectionClass('cref');"
" }"
" t15();"
" function t16() {"
" var_dump(class_exists('cex'));"
" }"
" t16();"
" function t17() {"
" var_dump(class_exists('cex_r'));"
" }"
" t17();"
"}"
"test();"
"z();"
"function __autoload($name) {"
" var_dump('autoload ' . $name);"
" switch ($name) {"
" case 'cNew':"
" class cNew {}"
" break;"
" case 'cNew_r':"
" class cNew_r {}"
" if (false) {"
" class cNew_r {}"
" }"
" break;"
" case 'cNew_d':"
" class cNew_d {}"
" break;"
" case 'csm':"
" class csm {"
" public static $mem = 1;"
" }"
" break;"
" case 'csm_r':"
" class csm_r {"
" public static $mem = 1;"
" }"
" if (false) {"
" class csm_r {}"
" }"
" break;"
" case 'CcOn':"
" class CcOn {"
" const C = 2;"
" }"
" break;"
" case 'CcOn_r':"
" class CcOn_r {"
" const C = 2;"
" }"
" if (false) {"
" class CcOn_r {}"
" }"
" break;"
" case 'CcOn_d':"
" class CcOn_d {"
" const C = 2;"
" }"
" break;"
" case 'csmeth':"
" class csmeth {"
" public static function m() { echo '1\n'; }"
" }"
" break;"
" case 'csmeth_r':"
" class csmeth_r {"
" public static function m() { echo '1'; }"
" }"
" if (false) {"
" class csmeth_r {}"
" }"
" break;"
" case 'csmeth_d':"
" class csmeth_d {"
" public static function m() { echo '1'; }"
" }"
" break;"
" case 'cpar':"
" class cpar {}"
" break;"
" case 'cpar_r':"
" class cpar_r {}"
" if (false) {"
" class cpar_r {}"
" }"
" break;"
" case 'cref':"
" class cref {}"
" break;"
" case 'cex':"
" class cex {}"
" break;"
" case 'cex_r':"
" class cex_r {}"
" if (false) {"
" class cex_r {}"
" }"
" break;"
" }"
"}");
MVCR("<?php "
"class_exists('c');"
"class c {"
" const A = 'a';"
" const B = 'b';"
" const C = 'c';"
" const D = 'd';"
" public static $S = array("
" self::A,"
" self::B,"
" self::C,"
" self::D);"
"}"
"var_dump(c::$S);");
MVCR("<?php "
"class B {}"
"class A extends B {"
" static function make() {"
" $b = new parent();"
" $a = new self();"
" }"
"}"
"if (false) { class A {};}"
"A::make();");
MVCR("<?php "
"function foo($a) {"
" if ($a) {"
" class A {}"
" }"
"}"
"foo(true);"
"function bar() {"
" if (class_exists('A')) {"
" class C extends A { }"
" $obj = new C;"
" var_dump($obj);"
" } else {"
" var_dump('no');"
" }"
"}"
"bar();");
MVCR("<?php "
"function foo($a) {"
" if ($a) {"
" interface A {}"
" }"
"}"
"foo(true);"
"function bar() {"
" if (interface_exists('A')) {"
" class C implements A { }"
" $obj = new C;"
" var_dump($obj);"
" } else {"
" var_dump('no');"
" }"
"}"
"bar();");
MVCR("<?php "
"if (class_exists('B')) {"
" class A extends B {"
" public function f() {"
" var_dump('A');"
" }"
" }"
"}"
"var_dump(class_exists('C'));"
"class B extends C {"
" public function f() {"
" var_dump('B');"
" }"
"}"
"class C {}"
"if (class_exists('A')) {"
" $obj = new A;"
" $obj->f();"
"} else {"
" var_dump('correct');"
"}");
MVCR("<?php "
"function wrapper($a) {"
" if ($a) {"
" class C {"
" private static $v;"
" public static function f() {"
" return self::$v;"
" }"
" }"
" }"
"}"
"class C2 {"
" private static $v;"
" public static function f() {"
" return self::$v;"
" }"
"}"
"function foo($a) {"
" if ($a == 0) return is_callable(array('C', 'f'), null);"
" return is_callable(array('C2', 'f'), null);"
"}"
"wrapper(false);"
"var_dump(foo(0));"
"var_dump(foo(1));"
"if (class_exists('C')) var_dump('yes'); else var_dump('no');");
MVCR("<?php "
"function __autoload($name) {"
" if ($name == 'CaT') {"
" class CaT {"
" function __construct() {}"
" }"
" }"
" var_dump($name);"
"}"
""
"new CaT(1);"
"class_exists('cat', false);");
MVCRO("<?php\n"
"function autoload_first($name) {\n"
" echo __METHOD__ . \"\\n\";\n"
" throw new Exception('first', 0, new Exception('first_inner'));\n"
"}\n"
"function autoload_second($name) {\n"
" echo __METHOD__ . \"\\n\";\n"
" throw new Exception('second', 0, new Exception('second_inner'));\n"
"}\n"
"function __autoload($name) {\n"
" echo __METHOD__ . \"\\n\";\n"
" throw new Exception('__autoload');\n"
"}\n"
"spl_autoload_register('autoload_first');\n"
"spl_autoload_register('autoload_second');\n"
"try {\n"
" var_dump(class_exists('A'));\n"
"} catch(Exception $e) {\n"
" do {\n"
" echo $e->getMessage() . \"\\n\";\n"
" } while($e = $e->getPrevious());\n"
"}\n"
"try {\n"
" $obj = new A();\n"
"} catch(Exception $e) {\n"
" do {\n"
" echo $e->getMessage() . \"\\n\";\n"
" } while($e = $e->getPrevious());\n"
"}\n"
"// hphpc won't call the autoloader unless there exists a \n"
"// definition for the class somewhere\n"
"if (true) {\n"
" class A {}\n"
"}\n",
"autoload_first\n"
"autoload_second\n"
"second\n"
"second_inner\n"
"first\n"
"first_inner\n"
"autoload_first\n"
"autoload_second\n"
"second\n"
"second_inner\n"
"first\n"
"first_inner\n");
MVCRO("<?php\n"
"function f($cls) {}\n"
"var_dump(spl_autoload_functions());\n"
"spl_autoload_register('f');\n"
"var_dump(spl_autoload_functions());\n"
"spl_autoload_unregister('f');\n"
"var_dump(spl_autoload_functions());\n"
"spl_autoload_unregister('spl_autoload_call');\n"
"var_dump(spl_autoload_functions());\n"
"spl_autoload_register('f');\n"
"var_dump(spl_autoload_functions());\n"
"spl_autoload_unregister('spl_autoload_call');\n"
"var_dump(spl_autoload_functions());\n",
"bool(false)\n"
"array(1) {\n"
" [0]=>\n"
" string(1) \"f\"\n"
"}\n"
"array(0) {\n"
"}\n"
"bool(false)\n"
"array(1) {\n"
" [0]=>\n"
" string(1) \"f\"\n"
"}\n"
"bool(false)\n");
MVCRO("<?php\n"
"function autoload_first($name) {\n"
" echo __METHOD__ . \"\\n\";\n"
"}\n"
"function autoload_second($name) {\n"
" echo __METHOD__ . \"\\n\";\n"
"}\n"
"function __autoload($name) {\n"
" echo __METHOD__ . \"\\n\";\n"
"}\n"
"echo \"**************\\n\";\n"
"class_exists('A');\n"
"echo \"**************\\n\";\n"
"spl_autoload_register('autoload_first');\n"
"spl_autoload_register('autoload_second');\n"
"class_exists('B');\n"
"echo \"**************\\n\";\n"
"spl_autoload_unregister('autoload_first');\n"
"spl_autoload_unregister('autoload_second');\n"
"class_exists('C');\n"
"echo \"**************\\n\";\n"
"spl_autoload_unregister('spl_autoload_call');\n"
"class_exists('D');\n"
"echo \"**************\\n\";\n"
"// hphpc won't call the autoloader unless there exists a \n"
"// definition for the class somewhere\n"
"if (true) {\n"
" class A {}\n"
" class B {}\n"
" class C {}\n"
" class D {}\n"
"}\n",
"**************\n"
"__autoload\n"
"**************\n"
"autoload_first\n"
"autoload_second\n"
"**************\n"
"**************\n"
"__autoload\n"
"**************\n");
// Github Issue#619
MVCRO("<?php "
"spl_autoload_register(function($f) { var_dump(1); });\n"
"spl_autoload_register(function($f) { var_dump(2); });\n"
"class_exists('A');\n"
"// hphpc won't call the autoloader unless there exists a\n"
"// definition for the class somewhere\n"
"if (true) {\n"
" class A {}\n"
"}\n",
"int(1)\n"
"int(2)\n"
);
MVCRO("<?php "
"var_dump(fb_autoload_map("
" array('function' => array(),"
" 'constant' => array(),"
" 'failure' => 'failure'),"
" ''));"
"function failure($kind, $name) {"
" if ($kind == 'constant' && $name == 'bar') define('bar', 'baz');"
" var_dump($kind, $name);"
"}"
"var_dump(function_exists('foo'));"
"var_dump(function_exists('bar', false));"
"var_dump(defined('foo'));"
"var_dump(defined('bar', false));"
"var_dump(constant('foo'));"
"var_dump(constant('bar'));"
"if (0) {"
" function foo() {}"
" function foo() {}"
" define('foo', 0);"
" define('bar', 0);"
"}",
"bool(true)\n"
"string(8) \"function\"\n"
"string(3) \"foo\"\n"
"bool(false)\n"
"bool(false)\n"
"string(8) \"constant\"\n"
"string(3) \"foo\"\n"
"bool(false)\n"
"bool(false)\n"
"string(8) \"constant\"\n"
"string(3) \"foo\"\n"
"NULL\n"
"string(8) \"constant\"\n"
"string(3) \"bar\"\n"
"string(3) \"baz\"\n");
return true;
}
bool TestCodeRun::TestHereDoc() {
MVCR("<?php\n"
"$nullherequote= <<<fail\n"
"fail;\n"
"echo \"--$nullherequote--\\n\";"
"$x=\"foo\";"
"$threestops= <<<pass\n"
"passable $x\n"
"pass;x\n"
"ss;\n"
"pass;\n"
"echo \"$threestops\\n\";");
return true;
}
bool TestCodeRun::TestProgramFunctions() {
//VCR("<?php var_dump($_SERVER);");
MVCR("<?php var_dump($argc, count($argv));");
//VCR("<?php var_dump($_ENV);");
MVCR("<?php function p($a) { print $a;} "
"register_shutdown_function('p', 'shutdown');");
return true;
}
bool TestCodeRun::TestCompilation() {
MVCR("<?php class A { public static $foo = 123;} $a = foo(); "
"function foo() { return 'foo';} var_dump(A::$$a);");
MVCRNW("<?php fun foo() {}");
// testing re-declared classes with missing parents, VM raises error
// but the compiled code does not.
//MVCR("<?php $a = bar(); if ($a) { class fOO extends Unknown {} } else "
// "{ class Foo extends unknOwn {} } function bar() { return 123;}");
// testing re-declared classes with different cases
MVCR("<?php $a = bar(); if ($a) { class fOO {} } else "
"{ class Foo {} } function bar() { return 123;} $obj = new foo();");
// testing re-declared functions with different cases
MVCR("<?php $a = bar(); if ($a) { function fOO() {} } else "
"{ function Foo() {} } function bar() { return 123;} foo();");
// overlapped interface
MVCR("<?php interface A {} class B implements A {} "
"class C extends B implements A {} $obj = new C();");
// trigraph
MVCR("<?php print '\?\?/';");
// testing type inference on a re-declared constant
MVCR("<?php if (false) define('a', 'test'); define('a', 5); print $b % a;");
// testing type inference on a special type casting: PlusOperand -> Double
MVCR("<?php function d() { return '2009';} $y = (d()) + 6;");
MVCR("<?php class A { public static $a = array('a', 'b'); public static function test() { self::$a[] = 'c'; var_dump(self::$a);} } A::test();");
// \x65D is invalid in C++
MVCR("<?php var_dump(\"[\\x][\\xA][\\x65][\\x65D]\");");
MVCR("\\x65D");
// float vs. double
MVCR("<?php $a = 1; $a = 'test'; var_dump($a + 2.5);");
// +/- String
MVCR("<?php $a = -date('w');");
// ObjectOffset.at()
MVCR("<?php class A { public $a = array('t' => 't');} class B { public $a;} "
"$a = 1; $a = new A(); $a->a['t'] = true; var_dump($a->a['t']);");
// Variant % operator
MVCR("<?php $a = date('d') % 10;");
MVCR("<?php $a = 'test'; $a = 1; print $a % 10;");
// defining a constant after it's used
MVCR("<?php $a = MAX_LATITUDE + 5;"
"if (12 > -MAX_LATITUDE) define('MAX_LATITUDE', 90); ");
// toInt64() wrapper
MVCR("<?php print 1 << 32;");
// !$a is closer in C++
MVCR("<?php if (!$a = true) {}");
// integer as array element
MVCR("<?php function test($a = 0) { $b = $a; $c = $b[$a];}");
// String/Array operators
MVCR("<?php function str() { return 'test';} "
"function test() { var_dump(str() - $a);}");
// unused variable warning
MVCR("<?php function test() {} function foo() { test($a = 1);}");
// void return functions
MVCR("<?php function test() {} true ? test() : 1;");
// uninitialized variables need to be Variant
MVCR("<?php function test() { $a = 0; $a += $b;} test();");
// VariantOffset = VariantOffset
MVCR("<?php class A {} $a = new A(); $a->a = $a->b = 'test'; var_dump($a);");
MVCR("<?php $a = 1; $a = array(); $a['a'] = $a['b'] = 'test'; var_dump($a);");
// lval on Variant
MVCR("<?php function test() { return array();} reset(test());");
// variant.o_lval() needs lval() wrapper
MVCR("<?php class A { public $prop = 1;} class B { public $prop = 5;} "
"$a = 1; $a = new A(); $a->prop++; var_dump($a->prop);");
// obj->prop doesn't need lval() wrapper
MVCR("<?php class A { public $prop = 1;} "
"$a = new A(); $a->prop++; var_dump($a->prop);");
// ((p_obj)variant)->prop
MVCR("<?php class A { public $prop = 1;} "
"$a = 1; $a = new A(); $a->prop++; var_dump($a->prop);");
// unsigned int should never be seen
MVCR("<?php $a = 0xC0000000 & $b;");
// redefine properties
MVCR("<?php class E extends exception { public $message; public $code;}");
// redefine static members
MVCR("<?php class A { static $a = 1;} "
"class B extends A { static $a = 2;} var_dump(B::$a);");
// overriding function with assignment on parameters
MVCR("<?php class A { "
"function __call($a, $b) { $b = 'a'; $b = 1; "
"var_dump($a, $b[0], $b[1]);}} "
"$obj = new A(); $a = 1; $b = 'a'; $b = 2; $obj->test($a, $b);");
// method->method
MVCR("<?php class A { public function getA() { return $this;} "
"public function test() { var_dump('test');}} "
"class B { public function getA() {} public function test(){}}"
"$obj = new A(); $obj->getA()->test();"
);
// constructor fallback
MVCR("<?php class A { function __construct($a) { var_dump($a);} } "
"class B extends A {} "
"$a = new B('test');");
// prop->method
MVCR("<?php class A { function test() {}} class B { public $b;} "
"class C { function test() {}} "
"$a = 'test'; $a = new B(); $a->b = new A(); $a->b->test();");
// testing code generation order
MVCR("<?php "
"$global = B::CLASS_CONSTANT; "
"$another = test2($global); "
"define('CONSTANT', test2('defining')); "
//"test();"
//"function test($a = CONSTANT) { test2($a);} "
"function test2($a) { var_dump($a); return 12345;} "
"class A extends B {} "
"class B { const CLASS_CONSTANT = 1;} ");
// $_SERVER is already defined
MVCR("<?php $_SERVER = array('test' => 1); var_dump($_SERVER);");
MVCR("<?php $GLOBALS['_SERVER'] = array('test' => 1); var_dump($_SERVER);");
// class constant as default
MVCR("<?php "
"class A { const C = 123; static function t($a = B::C) {} } A::t();"
"class B { const C = 456; static function t($a = A::C) {} } B::t();");
// base virtual function prototype
MVCR("<?php class T { function __toString() { return 123;}} "
"$obj = new T(); var_dump($obj);");
// void wrapper
MVCR("<?php function test() {} var_dump(test()); $a = test();");
// ambiguous overload
MVCR("<?php $a = 'test'; $a = 123; switch ($a) { case -1: var_dump($a);}");
// [][]
MVCR("<?php $a['a']['b'] = 'test'; var_dump($a['a']['b']);");
// testing Variant to specific class conversion
MVCR("<?php class A { function test(A $a) { $a->foo();} "
"function foo() { print 'foo';}}");
MVCR("<?php "
"class A { function f($a) {} }"
"$obj = new A;"
"$obj->f(date('m/d/y H:i:s', 123456789));"
"$v = date(\"m\",123456789)+1;");
// no side effect optimization met if() short
MVCR("<?php if ($a) $a == 0;");
// */ and // in default argument
MVCR("<?php "
"function foo($p1=\"/.*/\", $p2=\"//\") {"
" var_dump($p1, $p2);"
"}"
"foo();");
MVCR("<?php "
"$n = floor(1.0);"
"var_dump(($n > 0) ? $n : $n + 1);");
MVCR("<?php "
"class X {"
" function test($a, $b, $c) {"
" return $a != $b;"
" }"
"}"
"function test($a) {"
" $x = new X;"
" return $a ? $x->test(1, 2) : false;"
"}"
"var_dump(test(1));");
MVCR("<?php function bug1($a, $b) {"
"foreach ($b[$a++ + $a++] as &$x) { echo $x; }}");
MVCR("<?php "
"function f($a, $b, $c) { return 'hello'; }"
"function test($a) {"
" $x = ($a->foo = f($b++, $b++, $b++)) . f(1,2,3);"
" return $x;"
"}");
MVCR("<?php "
"function g() {}"
"function test1() {"
" return '' . g();"
"}");
MVCR("<?php "
"function g() {}"
"function test1() {"
" return 0 + g();"
"}");
MVCR("<?php "
"function g() {}"
"function test1() {"
" return 1 * g();"
"}");
MVCR("<?php "
"$data = new stdclass;"
"$type = 'OCI-Lob';"
"if ($data instanceof $type) {"
" echo 'true';"
"}"
"class X {"
" static $foo;"
"};"
"function test() {"
" $x = new X;"
" $foo = 'foo';"
" if (isset($x->$foo) || empty($x->$foo) ||"
" isset($x->{'bar'})) {"
" unset($x->$foo);"
" unset($x->{'bar'});"
" echo true;"
" }"
"}");
MVCR("<?php "
"class X {"
" static function g() {}"
"};"
"@X::g();"
"function g($a,$b) {}"
"function f() { return 3; }"
"@g(f(),f());");
MVCR("<?php for ($i = 0; $i++,$i - 10;) {}");
MVCR("<?php function test($className) {"
"$x = new ReflectionClass($className);"
"return $x->newInstance()->loadAll(); }");
MVCR("<?php var_dump(array(1,2,3)+array(4,5,6));");
MVCR("<?php "
"function foo($a) {"
" $r = '';"
" if ($a) {"
" $r ->error = '';"
" }"
" return $r;"
"}"
"var_dump(foo(true));"
"var_dump(foo(false));");
MVCR("<?php "
"function foo($a) {"
" $r = '';"
" if ($a) {"
" $r ->error->line = 1;"
" }"
" return $r;"
"}"
"var_dump(foo(true));"
"var_dump(foo(false));");
MVCR("<?php "
"call_user_func_array(array('Normalizer','normalize'),array('bar'));");
MVCR("<?php "
"function bar($g) { return $g; }"
"class X {"
" static function foo() {"
" echo $this->baz(bar(1), bar(''));"
" }"
"}");
MVCR("<?php "
"function foo() {}"
"function test() {"
" foo()->bar();"
"}");
MVCR("<?php "
"function checker($x) {"
" $msg = foo();"
" $notice = $msg['title'].'. '.$msg['body'];"
" foo();"
" @list($a,$b) = $x;"
" $x = @$x['a'];"
" $x = @$x['b'];"
" return $a - $b + $x;"
"}");
MVCR("<?php "
"class C {"
" function foo($a) {"
" var_dump($this + $a);"
" var_dump($this - $a);"
" var_dump($this * $a);"
" var_dump($this / $a);"
" var_dump($a + $this);"
" var_dump($a - $this);"
" var_dump($a * $this);"
" var_dump($a / $this);"
" }"
"}"
"$obj = new C;"
"$obj->foo(1);");
MVCR("<?php "
"class X {}"
"class Y extends X { public $foo; }"
"function foo() {"
" $x = new Y;"
" $x && var_dump($x->foo);"
" $x = new X;"
" var_dump($x);"
"}"
"foo();");
MVCR("<?php "
"function bar($a) {}"
"function foo($x) {"
" $a = $x;"
" echo $x;"
" unset($a);"
" $a = bar(1);"
" bar($a++);"
"}");
MVCR("<?php function test($a) { return null * $a; }");
MVCR("<?php "
"function foo() {"
" define('AAA', 1);"
" if (false) {"
" define('BBB', 'bbb');"
" }"
"}");
MVCR("<?php "
"function foo() { return array(1,2,3); }"
"function bar($a, $b, $c) { $a = 4; }"
"$x = foo();"
"bar($x[3][4], $y);"
"var_dump($x);");
MVCR("<?php "
"function test($a) {"
" print \"hello $a world!\" and die;"
"}");
MVCR("<?php "
"if(0){class y{}}else{class y{}}"
"abstract class x extends y {"
" private static $nextSerial = 1;"
" private $serial = 0;"
" public function __construct() {"
" $this->serial = self::$nextSerial++;"
" }"
"}");
{
OptionSetter w1(this, OptionSetter::CompileTime,
"-vLocalCopyProp=0 -vEliminateDeadCode=0");
MVCR("<?php "
"function setAttribute() {"
" if (($v_size = func_num_args()) == 0) {"
" return true;"
" }"
" $v_att_list = &func_get_args();"
" return true;"
"}"
"setAttribute('a');");
}
{
HipHopSyntax w1(this);
MVCR("<?php "
"class X {}"
"function bar(string $x = X::FIZ, $y=null, $z=null,"
" $a=null, $b=null, $c=null, $d=null) {}");
}
MVCR("<?php "
"function foo($a,$b,$c,$d) { return implode($a,$b); }"
"function bar($values, $parent_fields) {"
" $full_name = implode('___', $parent_fields);"
" $body = '';"
" $body .= '<div>';"
" $body .= '<table id=' . 'bar_' . $full_name . ' border=1>';"
" $item_num = 0;"
" if (null !== $values) {"
" foreach($values as $val) {"
" $row_id = 'tr_sentrylist_' . $item_num . '_' . $full_name;"
" $body .= '<tr id=' . $row_id . '>';"
" $body .= '<td>';"
" $body .= foo($item_num, 0,"
" $val, $parent_fields);"
" $body .= '</td>';"
" $body .= '<td>';"
" $body .= foo($item_num, $full_name, 0, 0);"
" $body .= '</td>';"
" $body .= '</tr>';"
" $item_num += 1;"
" }"
" }"
" $body .= '</table>';"
"}");
MVCR("<?php "
"class X {"
" function foo() {"
" return function() use(&$this) {"
" return $this->bar();"
" };"
" }"
" function bar() {}"
"}");
MVCR("<?php "
"$x = 1;"
"switch ($x++ ?: -1) {};"
"var_dump($x);");
MVCR("<?php "
"function f() {"
" global $g;"
" $g++;"
"}"
"var_dump((boolean)f(),(int)f(),(double)f(),(string)f());"
"var_dump((array)f(),(object)f(),(unset)f());");
MVCR("<?php "
"if (isset($g)) {"
" class X {"
" private static $i = null;"
" function foo() {"
" self::$i = $this;"
" }"
" }"
"} else {"
" class X {}"
"}");
MVCRNW("<?php "
"class X { const FOO = 'hello'; }"
"function foo(&$a) { static $s; }"
"if (class_exists('X')) foo(X::FOO);");
MVCR("<?php "
"class X {"
" static function foo() { return new X; }"
" function bar() { var_dump(__METHOD__); }"
"};"
"function id($x) { return $x; }"
"function test() {"
" id(X::foo(1))->bar();"
"}"
"test();");
MVCRNW("<?php "
"class X {"
" function bar(X $x) {"
" $x->foo();"
" $x->foo();"
" }"
" function foo() { var_dump(__METHOD__); }"
"}"
"function test() {"
" X::bar(null);"
"}"
"test();");
MVCR("<?php "
"class X {"
" public function foo($offset) {"
" if (isset($this->__array[$offset])) {"
" return $this->initializeOffset($offset);"
" } else {"
" return null;"
" }"
" return $this->__array[$offset];"
" }"
"}");
MVCR("<?php "
"class Y {"
" function bar() {}"
"}"
"class X {"
" function foo() {"
" $x = $this;"
" if ($this instanceof y) {"
" $this->bar();"
" }"
" return $x;"
" }"
"}");
MVCR("<?php"
"function foo(&$a, &$b) {}"
"if (isset($g)) {"
" function foo($a, $b) {}"
"}"
"function bar() {"
" foo($x, $y);"
"}"
"bar();");
MVCR("<?php "
"class X {"
" function foo($x,$y) {"
" $a = null;"
" if ($x) {"
" $a = new X;"
" }"
" new X($y ? null : $a);"
" return $a;"
" }"
"}"
"$x = new X;"
"var_dump($x->foo(false, true));");
MVCR("<?php \n"
"\n"
"class C {\n"
" public function loadAllWithIDs($ids) {\n"
" if (!count($ids = array_filter($ids))) {\n"
" return array();\n"
" }\n"
" var_dump('muy malo', $ids);\n"
" return -666;\n"
" }\n"
"}\n"
"\n"
"function main() {\n"
" $testA = array(4 => false, 5 => false);\n"
" $c = new C();\n"
" var_dump($c->loadAllWithIDs($testA));\n"
"}\n"
"\n"
"main();\n");
MVCR("<?php "
"class A {"
" public $a;"
" function foo() {"
" $this->bar();"
" if ($this instanceof B) {"
" $this->b = 1;"
" }"
" $this->a = 1;"
" }"
"}"
"class B extends A {"
" public $b;"
" function bar() {}"
"}"
"function main() {"
" $b = new B;"
" $b->foo();"
" var_dump($b);"
"}"
"main();");
return true;
}
bool TestCodeRun::TestReflection() {
MVCR("<?php\n"
"class A { public function foo() {}}\n"
"$x = new ReflectionMethod('A::foo');\n"
"var_dump($x->name, $x->class);\n");
MVCR("<?php class A { public static function test() { print 'ok';}}"
"var_dump(is_callable('A::test'));"
"var_dump(function_exists('A::test'));");
MVCR("<?php function test($a) { return 'ok'.$a;}"
"var_dump(function_exists('TEst')); "
"var_dump(is_callable('teSt'));"
"var_dump(call_user_func('teST', 'blah')); "
"var_dump(call_user_func_array('teST', array('blah'))); "
);
MVCR("<?php class B { public function f($a) { return 'ok'.$a;}} "
"class A extends B { public $p = 'g';} "
"$obj = new A(); "
"var_dump(get_class($obj)); "
"var_dump(get_parent_class($obj)); "
"var_dump(is_a($obj, 'b')); "
"var_dump(is_subclass_of($obj, 'b'));"
"var_dump(method_exists($obj, 'f'));"
"var_dump(method_exists('A', 'f'));"
"var_dump(is_callable(array($obj, 'f')));"
"var_dump(is_callable(array('A', 'f')));"
"var_dump(get_object_vars($obj));"
"var_dump(call_user_method('f', $obj, 'blah'));"
"var_dump(call_user_method_array('f', $obj, array('blah')));"
);
MVCR("<?php class A { public static function f($a) { return 'ok'.$a;}} "
"$obj = new A(); "
"var_dump(method_exists($obj, 'f'));"
"var_dump(method_exists('A', 'f'));"
"var_dump(is_callable(array($obj, 'f')));"
"var_dump(is_callable(array('A', 'f')));"
"var_dump(call_user_func(array($obj,'f'), 'blah'));"
"var_dump(call_user_func_array(array($obj,'f'), array('blah')));"
"var_dump(call_user_func(array('A','f'), 'blah'));"
"var_dump(call_user_func_array(array('A','f'), array('blah')));"
);
MVCR("<?php "
"class A { function foo() {} }"
"class B extends A { function bar() {}}"
"var_dump(get_class_methods(new B()));");
MVCR("<?php "
"class X {"
" public function a() { var_dump(get_class_methods($this)); }"
" protected function b() {}"
" private function c() {}"
" final function d() {}"
" public function e() {}"
"}"
"class Y {"
" public function a() { var_dump(get_class_methods($this)); }"
"}"
"$x = new X;"
"$x->a();"
"$y = new Y;"
"$y->a();"
"var_dump(get_class_methods($x));"
"var_dump(get_class_methods($y));");
MVCR("<?php "
"interface A { function foo(); }"
"abstract class B implements A { function bar() {}}"
"var_dump(get_class_methods('B'));");
MVCR("<?php "
"interface I1 { function ifoo2(); function ifoo1(); }"
"interface I2 { function ifoo4(); function ifoo3(); }"
"class A { function foo() {} function foo2() {} }"
"abstract class B extends A implements I1, I2 { function bar() {}}"
"abstract class C extends A implements I2, I1 { function bar() {}}"
"class D extends C { function ifoo2() {} function ifoo1() {}"
" function ifoo4() {} function ifoo3() {} function bar() {} }"
"var_dump(get_class_methods('B'));"
"var_dump(get_class_methods('C'));"
);
MVCR("<?php class A { static $a = 10; public $b = 20;}"
"$obj = new A(); var_dump(get_object_vars($obj));");
MVCR("<?php\n"
"function foo($a = null) {}\n"
"$func = new ReflectionFunction('foo');\n"
"$params = $func->getParameters();\n"
"var_dump($params[0]->isDefaultValueAvailable());\n");
MVCR("<?php "
"class X {"
" function X() { }"
" function __construct() { }"
"}"
"class Y {"
" function Y() { }"
"}"
"class Z {"
" function z() { }"
"}"
"function test($cname, $mname) {"
" $x = new ReflectionClass($cname);"
" $m = $x->getMethod($mname);"
" echo \"$cname:$mname:\"; var_dump($m->isConstructor());"
"}"
"test('X', 'X');"
"test('Y', 'Y');"
"test('Y', 'y');"
"test('Z', 'Z');"
"test('Z', 'z');");
MVCR("<?php "
"function foo($a, $b) { }"
"$funcs = get_defined_functions();"
"var_dump($funcs['user']);");
{
HipHopSyntax w(this);
MVCRO("<?php "
"class bar { function baz() { yield 5; } }"
"$x = new ReflectionClass('bar');"
"var_dump(count($x->getMethods()));",
"int(1)\n");
MVCRO("<?php"
"Trait T { function bar() { yield 1; } }"
"class X { use T; }"
"function test() {"
" $r = new ReflectionClass('X');"
" foreach ($r->getMethods() as $m) {"
" var_dump($m->name);"
" }"
"}"
"test();",
"string(3) \"bar\"\n");
MVCRO("<?php\n"
"\n"
"/**\n"
" * Doc comment on a function generator\n"
" */\n"
"function foo() {\n"
" yield null;\n"
"}\n"
"$rf = new ReflectionFunction('foo');\n"
"var_dump($rf->getDocComment());\n"
"\n"
"class C {\n"
" /**\n"
" * Doc comment on a method generator\n"
" */\n"
" public function bar() {\n"
" yield null;\n"
" }\n"
"}\n"
"$rm = new ReflectionMethod('C','bar');\n"
"var_dump($rm->getDocComment());\n"
,
"string(46) \"/**\n"
" * Doc comment on a function generator\n"
" */\"\n"
"string(48) \"/**\n"
" * Doc comment on a method generator\n"
" */\"\n"
);
}
MVCR("<?php"
"function test() {"
" try {"
" $classes = get_declared_classes();"
" foreach ($classes as $class) {"
" $r = new ReflectionClass($class);"
" $t += count($r->getMethods());"
" }"
" var_dump('ok');"
" } catch (Exception $e) {"
" var_dump($e->getMessage());"
" }"
"}"
"test();");
MVCRO("<?php "
"trait T {}"
"interface I {}"
"foreach (get_declared_classes() as $c) {"
" if ($c == 'T' || $c == 'I') {"
" var_dump('failed');"
" exit(0);"
" }"
"}"
"var_dump('OK!');",
"string(3) \"OK!\"\n");
/* is_a - objects */
MVCRO("<?php "
"class A {} class B extends A {}"
"$a = new A; $b = new B;"
"var_dump(is_a($a, 'A'));"
"var_dump(is_a($a, 'B'));"
"var_dump(is_a($b, 'A'));"
"var_dump(is_a($b, 'A', true));"
,
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
);
/* is_a - classes */
MVCRO("<?php "
"class A {}"
"class B extends A {}"
"class C extends B {}"
"$a = new A; $b = new B;"
"var_dump(is_a('a', 'A', true));"
"var_dump(is_a('a', 'A', false));"
"var_dump(is_a('b', 'A', true));"
"var_dump(is_a('a', 'B', true));"
"var_dump(is_a('c', 'A', true));"
,
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
);
/* is_a - interfaces */
MVCRO("<?php "
"interface A {}"
"interface B extends A {}"
"interface C extends B {}"
"class D implements A {}"
"$d = new D;"
"var_dump(is_a($d, 'A'));"
"var_dump(is_a($d, 'B'));"
"var_dump(is_a('B', 'A', true));"
"var_dump(is_a('B', 'B', true));"
"var_dump(is_a('C', 'A', true));"
,
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
);
/* is_subclass_of - objects */
MVCRO("<?php "
"class A {} class B extends A {}"
"$a = new A; $b = new B;"
"var_dump(is_subclass_of($a, 'A'));"
"var_dump(is_subclass_of($a, 'B'));"
"var_dump(is_subclass_of($b, 'A'));"
"var_dump(is_subclass_of($b, 'A', false));"
,
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
);
/* is_subclass_of - classes */
MVCRO("<?php "
"class A {}"
"class B extends A {}"
"class C extends B {}"
"$a = new A; $b = new B;"
"var_dump(is_subclass_of('a', 'A', true));"
"var_dump(is_subclass_of('a', 'A', false));"
"var_dump(is_subclass_of('b', 'A', true));"
"var_dump(is_subclass_of('a', 'B', true));"
"var_dump(is_subclass_of('c', 'A', true));"
,
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
);
/* is_subclass_of - interfaces */
MVCRO("<?php "
"interface A {}"
"interface B extends A {}"
"interface C extends B {}"
"class D implements A {}"
"$d = new D;"
"var_dump(is_subclass_of($d, 'A'));"
"var_dump(is_subclass_of($d, 'B'));"
"var_dump(is_subclass_of('B', 'A'));"
"var_dump(is_subclass_of('B', 'B'));"
"var_dump(is_subclass_of('C', 'A'));"
,
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
);
/* reflection function for closures */
MVCRO("<?php\n"
"$f = function() { echo \"in \\$f\\n\"; };\n"
"$g = function($a = 'default') { echo \"in \\$g; passed $a\\n\"; };\n"
"\n"
"/** This doc comment is so helpful and descriptive. */\n"
"$add = function($x, $y) {\n"
" $sum = $x + $y;\n"
" echo 'x + y = ' . $sum . \"\\n\";\n"
"};\n"
"\n"
"function show_params($params) {\n"
" echo 'parameters => array(' . count($params) . \") {\\n\";\n"
" foreach ($params as $p) {\n"
" echo \" name => {$p->getName()}\\n\";\n"
" }\n"
" echo \"}\\n\";\n"
"}\n"
"function show($rf) {\n"
" var_dump($rf->getName());\n"
" var_dump($rf->isUserDefined());\n"
" var_dump($rf->getStartLine());\n"
" var_dump($rf->getEndLine());\n"
" var_dump($rf->getDocComment());\n"
" var_dump($rf->getFileName() === __FILE__);\n"
" show_params($rf->getParameters());\n"
" var_dump($rf->getNumberOfParameters());\n"
" var_dump($rf->getNumberOfRequiredParameters());\n"
"}\n"
"\n"
"$rf = new ReflectionFunction($f);\n"
"$rg = new ReflectionFunction($g);\n"
"$radd = new ReflectionFunction($add);\n"
"\n"
"echo \"invoking f\\n\";\n"
"$rf->invoke();\n"
"\n"
"echo \"\\ninvoking g\\n\";\n"
"$rg->invoke('hello');\n"
"$rg->invokeArgs(array('goodbye'));\n"
"\n"
"echo \"\\ninvoking add\\n\";\n"
"$radd->invoke(1, 2);\n"
"$radd->invokeArgs(array(5000000000, 5000000000));\n"
"\n"
"echo \"\\nshowing f\\n\";\n"
"show($rf);\n"
"\n"
"echo \"\\nshowing g\\n\";\n"
"show($rg);\n"
"\n"
"echo \"\\nshowing add\\n\";\n"
"show($radd);\n"
,
"invoking f\n"
"in $f\n"
"\n"
"invoking g\n"
"in $g; passed hello\n"
"in $g; passed goodbye\n"
"\n"
"invoking add\n"
"x + y = 3\n"
"x + y = 10000000000\n"
"\n"
"showing f\n"
"string(9) \"{closure}\"\n"
"bool(true)\n"
"int(4)\n"
"int(4)\n"
"bool(false)\n"
"bool(true)\n"
"parameters => array(0) {\n"
"}\n"
"int(0)\n"
"int(0)\n"
"\n"
"showing g\n"
"string(9) \"{closure}\"\n"
"bool(true)\n"
"int(5)\n"
"int(5)\n"
"bool(false)\n"
"bool(true)\n"
"parameters => array(1) {\n"
" name => a\n"
"}\n"
"int(1)\n"
"int(0)\n"
"\n"
"showing add\n"
"string(9) \"{closure}\"\n"
"bool(true)\n"
"int(8)\n"
"int(11)\n"
"string(54) \"/** This doc comment is so helpful and descriptive. */\"\n"
"bool(true)\n"
"parameters => array(2) {\n"
" name => x\n"
" name => y\n"
"}\n"
"int(2)\n"
"int(2)\n"
);
MVCR("<?php "
"function __autoload($name) {"
" switch ($name) {"
" case 'C':"
" class C {}"
" break;"
" case 'M':"
" class M { function foo() {} }"
" break;"
" default: class C{} class M {}"
" }"
" var_dump($name);"
"}"
"$r1 = new ReflectionClass('C');"
"$r2 = new ReflectionMethod('M', 'foo');");
return true;
}
bool TestCodeRun::TestReflectionClasses() {
MVCR("<?php "
// declarations
"interface i1 {} interface i2 {}"
"class cls1 implements i1, i2 { "
" const CLS_CONST = 2;"
" protected $prop1;"
" public static $prop2 = 23;"
" function method1($param1) { print $param1;} "
"} "
"function &func1(cls1 $p1, &$p2, $p3='def') { "
" static $a=1; var_dump($p1);"
"} "
"function func2($a) { var_dump($a);} "
"class cls2 extends cls1 {}"
""
// helpers
"function dump_func($func) {"
" var_dump($func->getName()); "
" var_dump($func->isInternal()); "
" var_dump($func->isUserDefined()); "
" var_dump($func->isClosure()); "
" $vars = $func->getStaticVariables(); "
" var_dump(count($vars));"
" var_dump(isset($vars['a']));"
" var_dump($func->returnsReference()); "
" var_dump($func->getNumberOfParameters()); "
" var_dump($func->getNumberOfRequiredParameters()); "
" foreach ($func->getParameters() as $name => $param) {"
" var_dump($name); "
" dump_param($param); "
" }"
"} "
""
"function verify_class($cls) {"
" if ($cls) {"
" var_dump($cls->getName()); "
" } else {"
" var_dump(null);"
" }"
"}"
""
"function verify_classes($classes) {"
" ksort($classes);"
" foreach ($classes as $cls) {"
" verify_class($cls); "
" }"
"}"
""
"function dump_param($param) {"
" var_dump($param->getName()); "
" var_dump($param->isPassedByReference()); "
" verify_class($param->getDeclaringClass()); "
" verify_class($param->getClass()); "
" var_dump($param->isArray()); "
" var_dump($param->allowsNull()); "
" var_dump($param->isOptional()); "
" var_dump($param->isDefaultValueAvailable()); "
" if ($param->isOptional()) { "
//" var_dump($param->getDefaultValue()); "
" } "
" var_dump($param->getPosition()); "
"} "
""
"function dump_prop($prop, $obj) {"
" var_dump($prop->getName()); "
" var_dump($prop->isPublic()); "
" var_dump($prop->isPrivate()); "
" var_dump($prop->isProtected()); "
" var_dump($prop->isStatic()); "
//" var_dump($prop->isDefault()); "
" var_dump($prop->getModifiers() & 0xffff); "
" if ($prop->isPublic()) { "
" var_dump($prop->getValue($obj)); "
" if (!$prop->isStatic()) {"
" var_dump($prop->setValue($obj, 78)); "
" }"
" var_dump($prop->getValue($obj)); "
" } "
" verify_class($prop->getDeclaringClass()); "
"} "
""
"function dump_class($cls, $obj) {"
" var_dump($cls->isInstance($obj)); "
" var_dump($cls->getName()); "
" var_dump($cls->isInternal()); "
" var_dump($cls->isUserDefined()); "
" var_dump($cls->isInstantiable()); "
" var_dump($cls->hasConstant('CLS_CONST')); "
" var_dump($cls->hasMethod('method1')); "
" var_dump($cls->hasProperty('prop1')); "
" dump_func($cls->getMethod('method1')); "
" dump_prop($cls->getProperty('prop1'), $obj); "
" verify_classes($cls->getInterfaces()); "
" var_dump($cls->isInterface()); "
" var_dump($cls->isAbstract()); "
" var_dump($cls->isFinal()); "
" var_dump($cls->getModifiers() & 0xffff); "
" verify_class($cls->getParentClass()); "
" var_dump($cls->isSubclassOf('i1')); "
" var_dump($cls->getStaticPropertyValue('prop2')); "
//" var_dump($cls->setStaticPropertyValue('prop2', 45)); "
" cls1::$prop2 = 45; "
" var_dump($cls->getStaticPropertyValue('prop2')); "
" var_dump(cls1::$prop2); "
" var_dump($cls->isIterateable()); "
" var_dump($cls->implementsInterface('i2')); "
" foreach ($cls->getProperties() as $name => $prop) {"
" var_dump($name); "
" dump_prop($prop, $obj); "
" }"
" foreach ($cls->getMethods() as $name => $func) {"
" var_dump($name); "
" dump_func($func); "
" var_dump($func->isFinal()); "
" var_dump($func->isAbstract()); "
" var_dump($func->isPublic()); "
" var_dump($func->isPrivate()); "
" var_dump($func->isProtected()); "
" var_dump($func->isStatic()); "
" var_dump($func->isConstructor()); "
" var_dump($func->isDestructor()); "
" var_dump($func->getModifiers() & 0xFFFF); "
" verify_class($func->getDeclaringClass()); "
" if ($name == 'method1') $func->invoke($obj, 'invoked'); "
" }"
"}"
""
// verification
"$func = new ReflectionFunction('func1'); "
"dump_func($func); "
""
"$func = new ReflectionFunction('func2'); "
"$func->invoke('invoked');"
""
"$cls = new ReflectionClass('cls1'); "
"$obj = $cls->newInstance(); "
"dump_class($cls, $obj);"
""
"$cls = new ReflectionClass('cls2'); "
"$obj = $cls->newInstance(); "
"dump_class($cls, $obj);"
"");
MVCR("<?php "
"abstract class c {"
" public static $arr = array();"
" function g() {"
" $cl = new ReflectionClass(get_class($this));"
" $p = $cl->getProperty('arr');"
" return $p->getValue();"
" }"
"}"
"abstract class aa extends c {"
" public function get_arr() {"
" $actions = parent::get_arr();"
" return $actions;"
" }"
"}"
"class a extends aa {"
" public static $arr = array('v');"
"}"
"$x = new a;"
"var_dump($x->g());");
MVCR("<?php "
"$z=true;"
"if ($z) {"
" class AaaA {"
" function f() {"
" var_dump(get_class());"
" }"
" }"
"} else {"
" class aAAa {}"
"}"
"class BbBb {}"
"$r = new ReflectionClass('aaaa');"
"var_dump($r->getName());"
"$r = new ReflectionClass('bbbb');"
"var_dump($r->getName());"
"$a = new aaaa;"
"$a->f();");
MVCR("<?php "
"class z {"
" const foo = 10;"
"}"
"class c {"
" const bar = z::foo;"
"}"
"var_dump(c::bar);"
"$r = new ReflectionClass('c');"
"var_dump($r->getConstant(\"bar\"));");
MVCR("<?php "
"class fOo {}"
"interface ioO {}"
"$c = new ReflectionClass('Foo');"
"$i = new ReflectionClass('Ioo');"
"var_dump($c->getFileName() !== '');"
"var_dump($i->getFileName() !== '');");
MVCR("<?php "
"class C {"
"public function mE() {"
"echo 'fail';"
"}"
"}"
"$ref = new ReflectionClass('C');"
"var_dump($ref->hasMethod('mE'));"
"var_dump($ref->hasMethod('me'));"
"$m = $ref->getMethod('me');"
"var_dump($m->getName());");
MVCR("<?php "
"class Base {"
" function foo() {"
" $m = new ReflectionMethod(get_class($this), 'bar');"
" var_dump($m->name);"
" }"
"}"
"$condition = 123;"
"if ($condition) {"
" class A extends Base {}"
"} else {"
" class A extends Base {}"
"}"
"class B extends A {"
" function bar() {"
" }"
"}"
"$obj = new B();"
"$obj->foo();");
MVCR("<?php "
"interface A {function foo();}"
"interface B extends A {}"
"class C implements B {function foo() {}};"
"$klass = new ReflectionClass('C');"
"var_dump($klass->implementsInterface('A'));"
"$inter = new ReflectionClass('B');"
"var_dump($inter->hasMethod('foo'));");
MVCR("<?php\n"
"class A { private $a; protected $b; public $c; static $d; }\n"
"function f($a) { asort($a); foreach ($a as $v) { var_dump($v->getName()); } }\n"
"$r = new ReflectionClass('A');\n"
"$a = $r->getProperties(); f($a);\n"
"$a = $r->getProperties(ReflectionProperty::IS_PUBLIC); f($a);\n"
"$a = $r->getProperties(ReflectionProperty::IS_PRIVATE); f($a);\n"
"$a = $r->getProperties(ReflectionProperty::IS_PROTECTED); f($a);\n"
"$a = $r->getProperties(ReflectionProperty::IS_STATIC); f($a);\n");
{
HipHopSyntax w(this);
MVCROF(
"<?php "
"function not_a_closure() { "
" return 1; "
"}; "
"$rf = new ReflectionFunction('not_a_closure'); "
"var_dump($rf->isClosure()); "
"var_dump($rf->isGenerator()); "
" "
"function is_a_generator() { "
" yield 1; "
" yield 2; "
"}; "
"$rf = new ReflectionFunction('is_a_generator'); "
"var_dump($rf->isClosure()); "
"var_dump($rf->isGenerator()); "
" "
"$cl = function() { "
" return 1; "
"}; "
"$rf = new ReflectionFunction($cl); "
"var_dump($rf->isClosure()); "
"var_dump($rf->isGenerator()); "
" "
"$cl = function() { "
" yield 1; "
" yield 2; "
"}; "
"$rf = new ReflectionFunction($cl); "
"var_dump($rf->isClosure()); "
"var_dump($rf->isGenerator()); "
,
"test/vm/reflection_isclosure.php.exp"
);
}
return true;
}
bool TestCodeRun::TestErrorHandler() {
MVCR("<?php function handler($code, $msg) { "
" var_dump(strpos($msg, 'system error') !== false); return true;"
"} "
"set_error_handler('handler');"
"function a() {} set_error_handler('a');restore_error_handler();"
"trigger_error('system error'); "
);
MVCR("<?php function handler($code, $msg) { "
" var_dump(strpos($msg, 'system error') !== false); return true;"
"} "
"set_error_handler('handler');"
"user_error('system error'); "
);
MVCR("<?php function handler($e) { "
" var_dump(strpos((string)$e, 'bomb') !== false); return true;"
"} "
"set_exception_handler('handler');"
"function a() {} set_exception_handler('a');restore_exception_handler();"
"throw new Exception('bomb'); "
);
MVCR("<?php "
"ob_start();"
"set_exception_handler('user_exception_handler');"
"echo 'Hello World';"
"throw new Exception;"
"function user_exception_handler($e) {"
" ob_end_clean();"
" var_dump(error_get_last());"
" echo 'Goodbye';"
" var_dump(error_get_last());"
"}");
MVCR("<?php\n"
"function handler($code, $msg, $file, $line) { var_dump($line); }\n"
"set_error_handler('handler');\n"
"function f($a) {\n"
" $b = $a[100];\n"
" return $b;\n"
"}\n"
"f(array(1, 2, 3));\n");
MVCR("<?php\n"
"class C {"
" public static function log(Exception $exception) {"
" $msg = get_class($exception).': '.$exception->getMessage();"
" var_dump($msg);"
" }"
" public static function setup() {"
" set_exception_handler(array(__CLASS__, 'log'));"
" }"
"}"
"$obj = new C;"
"$obj->setup();"
"throw new Exception('test');");
return true;
}
bool TestCodeRun::TestAssertOptions() {
MVCR("<?php "
"assert_options(ASSERT_ACTIVE, 0);"
"assert_options(ASSERT_WARNING, 0);"
"var_dump(assert(false));"
"var_dump(assert_options(ASSERT_ACTIVE, 0));"
"var_dump(assert_options(ASSERT_WARNING, 1));"
"var_dump(assert(false));"
"var_dump(assert_options(ASSERT_ACTIVE, 0));"
"var_dump(assert_options(ASSERT_WARNING, 2));"
"var_dump(assert(false));"
"var_dump(assert_options(ASSERT_ACTIVE, 1));"
"var_dump(assert_options(ASSERT_WARNING, 0));"
"var_dump(assert(false));"
"var_dump(assert_options(ASSERT_ACTIVE, 2));"
"var_dump(assert_options(ASSERT_WARNING, 0));"
"var_dump(assert(false));");
return true;
}
bool TestCodeRun::TestExtMisc() {
XhpSyntax w(this);
MVCR("<?php var_dump(pack('nvc*', 0x1234, 0x5678, 65, 66));");
MVCR("<?php var_dump(unpack('nfrist/vsecond/c2chars', "
"pack('nvc*', 0x1234, 0x5678, 65, 66)));");
MVCR("<?php $d=fopen('test/test_code_run.cpp', 'r');\n"
"var_dump(is_object($d));\n"
"var_dump(is_resource($d));\n"
"var_dump(gettype((string)$d));");
MVCR("<?php "
"class X {};"
"$x = new X;"
"$x->a = 1;"
"$x->b = 'hello';"
"$x->c = $x;"
"var_dump(http_build_query($x));");
MVCR("<?php "
"function __autoload($c) {"
" var_dump($c);"
"}"
"function test() {"
" var_dump(is_subclass_of('C', 'D'));"
" var_dump(get_class_methods('C'));"
" var_dump(method_exists('C', 'foo'));"
" class C {}"
" var_dump(is_subclass_of('C', 'D'));"
" var_dump(is_subclass_of('C', 'C'));"
"}"
"test();"
"var_dump(class_exists('C'));");
MVCRO("<?php "
"var_dump(hex2bin(\";lwekn\"));"
"var_dump(hex2bin(\"68656c6c6f\"));"
"var_dump(hex2bin(\"68656c6c6f6\"));"
,
"bool(false)\n"
"string(5) \"hello\"\n"
"bool(false)\n");
MVCRO("<?php\n"
"var_dump(token_name(396));\n"
"$str = \"<?php \\$x=<foo:bar/>;\\$y=<foo:bar>woo!</foo:bar>;\\n\";\n"
"$arr = token_get_all($str);\n"
"foreach ($arr as $t) {\n"
" if ($t[0] == 396) {\n"
" var_dump($t[1]);\n"
" }\n"
"}\n"
,
"string(12) \"T_XHP_TAG_LT\"\n"
"string(1) \"<\"\n"
"string(1) \"<\"\n"
"string(1) \"<\"\n"
);
return true;
}
bool TestCodeRun::TestInvalidArgument() {
MVCRO("<?php "
"var_dump(fb_rename_function('', ''));"
"var_dump(hotprofiler_enable(-1));"
"var_dump(mysql_fetch_array(null, 0));"
"var_dump(mysql_fetch_object(null, 'stdClass'));"
,
"bool(false)\n"
"NULL\n"
"bool(false)\n"
"bool(false)\n");
MVCR("<?php "
"$ch = curl_init();"
"var_dump(curl_setopt($ch, -1, 'http://www.example.com/'));"
"curl_close($ch);"
"var_dump(iconv_set_encoding('internal_encoding',"
" str_pad('invalid-charset', 64)));"
"var_dump(iconv_mime_decode("
" 'Subject: =?UTF-8?B?UHLDvGZ1bmcgUHLDvGZ1bmc=?=',"
" 0, str_pad('invalid-charset', 64)));"
"var_dump(iconv_mime_decode_headers("
" 'Subject: =?UTF-8?B?UHLDvGZ1bmcgUHLDvGZ1bmc=?=', 0,"
" str_pad('invalid-charset', 64)));"
"var_dump(iconv_strlen('UHLDvGZ1bmcgUHLDvGZ1bmc=',"
" str_pad('invalid-charset', 64)));"
"$subject = 'Subject: =?UTF-8?B?UHLDvGZ1bmcgUHLDvGZ1bmc=?=';"
"var_dump(iconv_strpos($subject,"
" 'H', 0, str_pad('invalid-charset', 64)));"
"var_dump(iconv_strrpos($subject,"
" 'H', str_pad('invalid-charset', 64)));"
"var_dump(iconv_substr('AB',0,1, str_pad('invalid-charset', 64)));"
"$preferences = array("
" 'output-charset' => 'UTF-8',"
" 'line-length' => 76,"
" 'line-break-chars' => '\n'"
");"
"$preferences['scheme'] = 'Q';"
"$preferences['input-charset'] = str_pad('invalid-charset', 64);"
"var_dump(iconv_mime_encode('Subject', 'Pr\xc3\274fung Pr\xc3\274fung',"
" $preferences));"
"$preferences['input-charset'] = 'ISO-8859-1';"
"$preferences['output-charset'] = str_pad('invalid-charset', 64);"
"var_dump(iconv_mime_encode('Subject', 'Pr\xc3\274fung Pr\xc3\274fung',"
" $preferences));"
"var_dump(iconv_set_encoding('internal_encoding',"
" str_pad('invalid-charset', 64)));"
"var_dump(iconv('UTF-8', str_pad('invalid-charset', 64), ''));"
"var_dump(iconv(str_pad('invalid-charset', 64), 'UTF-8', ''));"
"var_dump(time_nanosleep(-1, 0));"
"var_dump(time_nanosleep(0, -1));"
"var_dump(time_sleep_until(0));"
"var_dump(gzcompress('abc', -2));"
"var_dump(gzdeflate('abc', -2));"
"var_dump(http_build_query(1));"
"var_dump(parse_url('http://www.example.com', 100));"
"var_dump(dns_check_record('127.0.0.1', 'INVALID_TYPE'));"
"var_dump(assert_options(-1));"
"var_dump(simplexml_load_string('', 'INVALID_CLASS'));"
"var_dump(simplexml_load_string('', 'stdClass'));"
"var_dump(stream_get_contents('', -1));"
"$fp = fopen('test/test_ext_file.txt', 'r');"
"var_dump(fgets($fp, -1));"
/*
Not handled correctly. Invalid arg /types/ should result in
the function not being called, and null returned (even though
the functions are documented as returning false on failure).
"var_dump(fputcsv($fp, array(), 'abc'));"
"var_dump(fputcsv($fp, array(), 'a', 'def'));"
"var_dump(fgetcsv($fp, array(), 'abc'));"
"var_dump(fgetcsv($fp, array(), 'a', 'def'));"
*/
"fclose($fp);"
"$tmpfname = tempnam('', str_repeat('a', 128));"
"var_dump(strlen(basename($tmpfname)));"
"unlink($tmpfname);"
"$tmpfname = tempnam('', '/var/www' . str_repeat('a', 128));"
"var_dump(strlen(basename($tmpfname)));"
"unlink($tmpfname);"
"$ar1 = array(10, 100, 100, 0);"
"$ar2 = array(1, 3, 2);"
"var_dump(array_multisort($ar1, $ar2));"
"$phrase = 'eat fruits, vegetables, and fiber every day.';"
"$healthy = array('fruits', 'vegetables');"
"$yummy = array('pizza', 'beer', 'ice cream');"
"var_dump(str_replace($healthy, $yummy, $phrase));"
"var_dump(str_replace('ll', $yummy, 'good golly miss molly!',"
" $count));"
"var_dump(setlocale(LC_ALL, array('de_DE@euro', 'de_DE', 'deu_deu'),"
" array(1, 2)));"
"var_dump(setlocale(LC_ALL, str_pad('a', 255)));"
"var_dump(pack(\"\\xf4\", 0x1234, 0x5678, 65, 66));"
"var_dump(pack(\"x5\", 0x1234, 0x5678, 65, 66));"
"var_dump(pack(\"h\", -0x1234));"
"var_dump(pack(\"h\", 12345678900));"
"var_dump(unpack(\"\\xf4\", \"0x1234\"));"
"var_dump(sscanf('foo', '[%s', $id, $first, $last));"
"var_dump(sscanf('foo', '%z', $id, $first, $last));"
"var_dump(sscanf(\"SN/abc\", \"SN/%d%d\", $out));"
"var_dump($out);"
"var_dump(sscanf(\"SN/abc\", \"\", $out));"
"var_dump($out);"
"var_dump(printf('%$', 3));"
"var_dump(vsprintf('%$', 3));"
"var_dump(sprintf('%$', 3));"
"var_dump(vsprintf('%$', 3));"
"var_dump(str_word_count('abc', 2, '...'));"
"var_dump(str_word_count('abc', 2, 'b..a'));"
"var_dump(str_word_count('abc', 2, 'a..b..c'));"
"var_dump(base_convert('05678', 8, 37));"
"var_dump(convert_cyr_string('abc', 'y', 'z'));"
"var_dump(money_format('%abc', 1.33));"
"var_dump(money_format('%i%i', 1.33));"
"var_dump(str_pad('abc', 10, '', 100));"
"var_dump(str_pad('abc', 10, ' ', 100));"
"var_dump(wordwrap('', 75, '', true));"
"var_dump(wordwrap(null, 75, '', true));"
"var_dump(wordwrap('abc', 75, '', true));"
"var_dump(wordwrap('abc', 0, '', true));");
MVCR("<?php "
"function bar($a) { return $a; }"
"function baz($a) { return $a; }"
"function foo($x) {"
" return fb_call_user_func_safe_return('baz',"
" fb_call_user_func_safe_return('bar', $x));"
"}");
MVCR("<?php "
"function handler($err, $errstr) {"
" $errstr = preg_replace('/given,.*$/','given', $errstr);"
" var_dump($err, $errstr);"
"}"
"set_error_handler('handler');"
"class y {}"
"class x {"
" function __construct(y $y) {}"
"}"
"var_dump(new X(null));");
return true;
}
bool TestCodeRun::TestSuperGlobals() {
if (false) {
// This test is flaky on machines with both ipv6 and ipv4
MVCR("<?php function foo() { "
"file_get_contents('http://www.facebook.com/status.php');"
"var_dump(empty($http_response_header));"
"} foo();");
}
MVCR("<?php "
"function test() {"
" unset($GLOBALS['_SERVER']);"
" $GLOBALS['_SERVER']['foo'] = 'bar';"
" var_dump($_SERVER['foo']);"
" }"
"test();");
MVCR("<?php "
"function test() {"
" $_POST = array('HELLO' => 1);"
"}"
"test();"
"var_dump($_POST);");
MVCR("<?php "
"class X {"
" static function test() {"
" var_dump(__FUNCTION__);"
" var_dump(__CLASS__);"
" var_dump(__METHOD__);"
" return array($GLOBALS[__FUNCTION__],"
" $GLOBALS[__CLASS__],"
" $GLOBALS[__METHOD__]);"
" }"
"}"
"$test = 'this_is_function_test';"
"$X = 'this_is_class_x';"
"$GLOBALS['X::test'] = 'this_is_method_test::x';"
"var_dump(X::test());");
MVCR("<?php\n"
"$a = 100;\n"
"function f() {\n"
" foreach ($GLOBALS as $k => &$v) {\n"
" if ($k == 'a') { $v = -1; }\n"
" }\n"
" global $a;\n"
" var_dump($a);\n"
" $b = $GLOBALS;\n"
" $b['a'] = 0;\n"
" var_dump($GLOBALS['a']);\n"
"}\n"
"f();\n");
return true;
}
bool TestCodeRun::TestGlobalStatement() {
MVCR("<?php\n"
"global $c;\n"
"function &foo() {\n"
" $a = 5;\n"
" global $c;\n"
" $c = &$a;\n"
" var_dump($c);\n"
" return $a;\n"
"}\n"
"$b = foo();\n"
"$b = 6;\n"
"var_dump($c);\n"
"var_dump($b);\n"
);
MVCR("<?php "
"$global_var = 10;"
"function test_unset() {"
" global $global_var;"
" var_dump( isset($global_var) );"
" var_dump( empty($global_var) );"
" unset($global_var);"
" var_dump( isset($global_var) );"
" var_dump( empty($global_var) ); }"
"var_dump($global_var);"
"test_unset();"
"var_dump($global_var);"
);
MVCR("<?php "
"$a = 0;"
"function test() {"
" $a = 1;"
" if (true) global $a;"
" $a = 2;"
"}"
"test();"
"print \"$a\\n\";"
);
MVCR("<?php "
"$a = 1;"
"function test() {"
" $b = 1;"
" global $a;"
" $a = 10;"
"}"
"var_dump($a);"
"test();"
"var_dump($a);"
" return true;"
);
MVCR("<?php "
"function test() {"
" if (true) {"
" global $a;"
" $a = 10;"
" }"
"}"
"test();"
"var_dump($a);"
);
MVCR("<?php "
"$x = 1;"
"$GLOBALS['x'] = 2;"
"var_dump($x);"
"function test() {"
" global $x;"
" $x = 3;"
" $GLOBALS['x'] = 4;"
" var_dump($x);"
"}"
"test();");
return true;
}
bool TestCodeRun::TestStaticStatement() {
MVCR("<?php "
"function test_unset_static() {"
" static $static_var;"
" $static_var ++;"
" echo \"value of static_var before unset: $static_var\\n\";"
" var_dump( isset($static_var) );"
" var_dump( empty($static_var) );"
" unset($static_var);"
" echo \"value of static_var after unset: $static_var\\n\";"
" var_dump( isset($static_var) );"
" var_dump( empty($static_var) );"
" $static_var = 20;"
" echo \"value of static_var after new assignment: $static_var\\n\";"
"}"
"test_unset_static();"
"test_unset_static();"
"test_unset_static();"
);
MVCR("<?php "
"function test() {"
" $static_var = 3;"
" echo $static_var;"
" static $static_var;"
" $static_var ++;"
" echo $static_var;"
"}"
"test();"
)
MVCR("<?php "
"class A { static function test() {"
" $static_var = 3;"
" echo $static_var;"
" static $static_var;"
" $static_var ++;"
" echo $static_var;"
"} }"
"A::test();"
)
MVCR("<?php "
" $static_var = 1;"
" echo $static_var . \"\\n\";"
" static $static_var;"
" echo $static_var . \"\\n\";"
" $static_var ++;"
" echo $static_var . \"\\n\";"
)
MVCR("<?php "
" $static_var = 1;"
" global $static_var;"
" echo $static_var . \"\\n\";"
" $static_var --;"
" echo $static_var . \"\\n\";"
)
MVCR("<?php "
" $static_var = 1;"
" echo $static_var . \"\\n\";"
" static $static_var;"
" echo $static_var . \"\\n\";"
" $static_var ++;"
" echo $static_var . \"\\n\";"
" global $static_var;"
" echo $static_var . \"\\n\";"
" $static_var --;"
" echo $static_var . \"\\n\";"
)
MVCR("<?php "
"static $static_var = 1;"
"echo $static_var . \"\\n\";"
"function test()"
"{"
" static $static_var = -1;"
" echo $static_var . \"\\n\";"
" $static_var = 2;"
" echo $static_var . \"\\n\";"
" $static_var++;"
" echo $static_var . \"\\n\";"
"}"
"test();"
"test();"
)
MVCR("<?php "
"static $static_var;"
"echo $static_var . \"\\n\";"
"$static_var = 1;"
"echo $static_var . \"\\n\";"
)
MVCR("<?php "
"function test() {"
" if (false) {"
" static $static_var = +3;"
" }"
" echo $static_var . \"\\n\";"
" $static_var = 4;"
" echo $static_var . \"\\n\";"
"}"
"test();"
)
MVCR("<?php "
"if (false) {"
" static $static_var = +3;"
"}"
"echo $static_var . \"\\n\";"
"$static_var = 4;"
"echo $static_var . \"\\n\";"
)
MVCR("<?php "
"echo $static_var . \"\\n\";"
"static $static_var = 4;"
"echo $static_var . \"\\n\";"
);
MVCR("<?php "
"static $a = 5;"
"echo $a . \"\\n\";"
"global $a;"
"echo $a . \"\\n\";"
);
MVCR("<?php "
"function test() {"
" static $commenced = false;"
" if ($commenced === false) {"
" return 1;"
" }"
" $commenced = true;"
" unset($args);"
"}"
"echo test();"
);
MVCR("<?php "
"static $a = 1, $b = 2;"
"static $c = 1;"
"static $d = 1;"
"static $e = 1;"
"static $f = 1;"
"static $g = 1;"
"static $h = 1;"
"static $i = 1;"
"static $i = 2;"
"if (false) {"
" static $a = 2;"
" static $b = 3;"
" static $c = 2;"
" static $g;"
" static $i;"
" $e = 2;"
"} else {"
" static $d = 2;"
" static $h;"
" $f = 2;"
"}"
"echo $a;"
"echo $b;"
"echo $c;"
"echo $d;"
"echo $e;"
"echo $f;"
"echo $g;"
"echo $h;"
"echo $i;"
""
"function f() {"
" static $a = 1, $b = 2;"
" static $c = 1;"
" static $d = 1;"
" static $e = 1;"
" static $f = 1;"
" static $g = 1;"
" static $h = 1;"
" static $i = 1;"
" static $i = 2;"
" if (false) {"
" static $a = 2;"
" static $b = 3;"
" static $c = 2;"
" static $g;"
" static $i;"
" $e = 2;"
" } else {"
" static $d = 2;"
" static $h;"
" $f = 2;"
" }"
" echo $a;"
" echo $b;"
" echo $c;"
" echo $d;"
" echo $e;"
" echo $f;"
" echo $g;"
" echo $h;"
" echo $i;"
"}"
"f();"
"class foo {"
" static $a = 1, $b = 2;"
" static $c = 1;"
" static $d = 1;"
" static $e = 1;"
" static $f = 1;"
" function bar() {"
" static $a = 1, $b = 2;"
" static $c = 1;"
" static $d = 1;"
" static $e = 1;"
" static $f = 1;"
" static $g = 1;"
" static $h = 1;"
" static $i = 1;"
" static $i = 2;"
" if (false) {"
" static $a = 2;"
" static $b = 3;"
" static $c = 2;"
" static $g;"
" static $i;"
" $e = 2;"
" } else {"
" static $d = 2;"
" static $h;"
" $f = 2;"
" }"
" echo foo::$a;"
" echo foo::$b;"
" echo foo::$c;"
" echo foo::$d;"
" echo foo::$e;"
" echo foo::$f;"
" echo $a;"
" echo $b;"
" echo $c;"
" echo $d;"
" echo $e;"
" echo $f;"
" echo $g;"
" echo $h;"
" echo $i;"
" }"
"}"
"echo foo::$a;"
"echo foo::$b;"
"$v = new foo;"
"$v->bar();");
MVCR("<?php "
"define('FOO', 1);"
"class a {"
" static $b = FOO;"
"}"
"function foo() {"
" static $a;"
" static $a = FOO;"
" echo $a;"
"}"
"foo();"
"echo a::$b;");
MVCR("<?php "
"class c {"
" public $q = 20;"
" function x() {"
" $foo = 20;"
" static $foo;"
" $foo = $this->q;"
" echo $foo;"
" }"
" function y() {"
" static $foo = 20;"
" $foo++;"
" echo $foo;"
" }"
" static function sf() {"
" static $foo = 0;"
" $foo++;"
" echo $foo;"
" }"
"}"
"class d extends c {"
" public $q = 30;"
"}"
"$x = new c();"
"$x->x();"
"$x->y();"
"$x->y();"
"$x->y();"
"$x->y();"
"$x = new d();"
"$x->x();"
"$x->y();"
"$x->y();"
"$x->y();"
"c::sf();"
"c::sf();"
"c::sf();"
"d::sf();"
"d::sf();"
"d::sf();");
MVCR("<?php "
"class A {"
" private function foo() {"
" static $x = null;"
" var_dump(get_class($this), $x);"
" $x = 1;"
" }"
" public function run() {"
" $this->foo();"
" }"
"}"
"class B extends A {}"
"class C extends A {}"
"$a = new A;"
"$b = new B;"
"$c = new C;"
"$a->run();"
"$b->run();"
"$c->run();");
return true;
}
bool TestCodeRun::TestIfStatement() {
MVCR("<?php "
"if (false) {"
" echo \"case 1\\n\";"
"}"
"if (false) {"
" echo \"case 2\\n\";"
" function f1() {"
" $v = 1;"
" }"
"}"
"if (true) {"
" echo \"case 3\\n\";"
"}"
"if (true) {"
" echo \"case 4\\n\";"
" function f2() {"
" $v = 1;"
" }"
"}"
"if (true) {"
" echo \"case 5\\n\";"
"} else {"
" echo \"case 6\\n\";"
"}"
"if (true) {"
" echo \"case 7\\n\";"
"} else {"
" echo \"case 8\\n\";"
" function f3() {"
" $v = 1;"
" }"
"}"
"if ($a) {"
" echo \"case 9\\n\";"
"} elseif (true) {"
" echo \"case 10\\n\";"
" function f4() {"
" $v = 1;"
" }"
"} else {"
" echo \"case 11\\n\";"
"}"
"if ($a) {"
" echo \"case 12\\n\";"
"} elseif (true) {"
" echo \"case 13\\n\";"
"} else {"
" echo \"case 14\\n\";"
" function f5() {"
" $v = 1;"
" }"
"}"
"if ($a) {"
" echo \"case 15\\n\";"
"} elseif (true) {"
" echo \"case 16\\n\";"
"} elseif (true) {"
" echo \"case 17\\n\";"
" function f6() {"
" $v = 1;"
" }"
"} else {"
" echo \"case 18\\n\";"
"}"
"if ($a) {"
" echo \"case 19\\n\";"
"} elseif (true) {"
" echo \"case 20\\n\";"
"} elseif (true) {"
" echo \"case 21\\n\";"
" function f7() {"
" $v = 1;"
" }"
"}"
"if ($a) {"
" echo \"case 22\\n\";"
"} elseif (true) {"
" echo \"case 23\\n\";"
"} elseif (false) {"
" echo \"case 24\\n\";"
" function f8() {"
" $v = 1;"
" }"
"} else {"
" echo \"case 25\\n\";"
"}"
"if ($a) {"
" echo \"case 26\\n\";"
"} elseif (true) {"
" echo \"case 27\\n\";"
"} elseif (false) {"
" echo \"case 28\\n\";"
" function f9() {"
" $v = 1;"
" }"
"}");
MVCR("<?php "
"if (true) {"
" function foo() { echo \"foo\\n\"; }"
"} else if (false) {"
" function bar() { echo \"bar\\n\"; }"
"}");
MVCR("<?php "
"if (true) {"
" function foo() { echo \"foo\\n\"; }"
"} elseif (false) {"
" function bar() { echo \"bar\\n\"; }"
"}");
MVCR("<?php "
"function test($a,$b = 0) {"
" if ($a == 2) {"
" if ($b == 1) {"
" return;"
" }"
" $a = 5;"
" }"
" if ($a == 3) {"
" var_dump($a);"
" }"
"}"
"test(3);");
return true;
}
bool TestCodeRun::TestBreakStatement() {
MVCR("<?php "
"$arr = array('one', 'two', 'three', 'four', 'stop', 'five');"
"while (list(, $val) = each($arr)) {"
" if ($val == 'stop') {"
" break;"
" }"
" echo \"$val\\n\";"
"}"
""
"$i = 0;"
"while (++$i) {"
" switch ($i) {"
" case 5:"
" echo \"At 5\\n\";"
" break 1;"
" case 10:"
" echo \"At 10; quitting\\n\";"
" break 2;"
" default:"
" break;"
" }"
"}");
return true;
}
bool TestCodeRun::TestContinueStatement() {
MVCR("<?php "
"for ($i = 0;$i<3;$i++) {"
" echo \"Start Of I loop\\n\";"
" for ($j=0;;$j++) {"
" if ($j >= 2) continue 2;"
" echo \"I : $i J : $j\".\"\\n\";"
" }"
" echo \"End\\n\";"
"}"
"for ($i = 0;$i<10;$i++) {"
" if ($i % 2 == 0) continue 1;"
" echo $i . \"\\n\";"
"}"
"for ($i = 0;$i<10;$i++) {"
" if ($i % 2 == 0) continue;"
" echo $i . \"\\n\";"
"}");
MVCR("<?php "
"for ($i1 = 0; $i1 < 2; $i1++) {"
" for ($i2 = 0; $i2 < 2; $i2++) {"
" switch ($i2 % 2) {"
" case 0:"
" continue;"
" break;"
" }"
" print \"[\" . $i2 . \"]\\n\";"
" }"
" print $i1 . \"\\n\";"
"}");
return true;
}
bool TestCodeRun::TestReturnStatement() {
MVCR("<?php "
"function foo1($a) {"
" if ($a) return \"ok\";"
"}"
"function foo2($a) {"
" if ($a > 1) return;"
" if ($a == 1) return 1;"
"}"
"function foo3($a) {"
" if ($a > 1) return;"
" if ($a == 1) return;"
"}"
"function bar() {"
" $v1 = foo1(0);"
" var_dump($v1);"
" $v2 = foo2(0);"
" var_dump($v2);"
" $v3 = foo3(0);"
" var_dump($v3);"
"}"
"bar();");
MVCR("<?php "
"class q {}"
"function g() {"
" return null;"
" return new q;"
"}"
"function f() {"
" return;"
" return new q;"
"}"
"var_dump(g());"
"var_dump(f());"
);
return true;
}
bool TestCodeRun::TestAdd() {
MVCR("<?php "
"printf(\"%s\\n\", 30 + 30);"
"printf(\"%s\\n\", \"30\" + 30);"
"printf(\"%s\\n\", 30 + \"30\");"
"printf(\"%s\\n\", \"30\" + \"30\");"
);
MVCR("<?php "
"$a = \"123.456\" + 123;"
"var_dump($a);"
"$a = \"123.456\" + 456.123;"
"var_dump($a);"
"$a = \"123.456\" + \"123\";"
"var_dump($a);"
"$a = \"123.456\" + \"456.123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a += 123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a += 456.123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a += \"123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a += \"456.123\";"
"var_dump($a);"
);
MVCR("<?php "
"var_dump(1.7976931348623157e+308 + 1.7976931348623157e+308);"
);
return true;
}
bool TestCodeRun::TestMinus() {
MVCR("<?php "
"printf(\"%s\\n\", 30 - 30);"
"printf(\"%s\\n\", \"30\" - 30);"
"printf(\"%s\\n\", 30 - \"30\");"
"printf(\"%s\\n\", \"30\" - \"30\");"
);
MVCR("<?php "
"$a = \"123.456\" - 123;"
"var_dump($a);"
"$a = \"123.456\" - 456.123;"
"var_dump($a);"
"$a = \"123.456\" - \"123\";"
"var_dump($a);"
"$a = \"123.456\" - \"456.123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a -= 123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a -= 456.123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a -= \"123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a -= \"456.123\";"
"var_dump($a);"
);
return true;
}
bool TestCodeRun::TestMultiply() {
MVCR("<?php "
"printf(\"%s\\n\", 30 * 30);"
"printf(\"%s\\n\", \"30\" * 30);"
"printf(\"%s\\n\", 30 * \"30\");"
"printf(\"%s\\n\", \"30\" * \"30\");"
);
MVCR("<?php "
"$a = \"123.456\" * 123;"
"var_dump($a);"
"$a = \"123.456\" * 456.123;"
"var_dump($a);"
"$a = \"123.456\" * \"123\";"
"var_dump($a);"
"$a = \"123.456\" * \"456.123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a *= 123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a *= 456.123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a *= \"123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a *= \"456.123\";"
"var_dump($a);"
);
return true;
}
bool TestCodeRun::TestDivide() {
MVCR("<?php "
"printf(\"%s\\n\", 30 / 30);"
"printf(\"%s\\n\", \"30\" / 30);"
"printf(\"%s\\n\", 30 / \"30\");"
"printf(\"%s\\n\", \"30\" / \"30\");"
);
MVCR("<?php "
"$a = \"123.456\" / 123;"
"var_dump($a);"
"$a = \"123.456\" / 456.123;"
"var_dump($a);"
"$a = \"123.456\" / \"123\";"
"var_dump($a);"
"$a = \"123.456\" / \"456.123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a /= 123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a /= 456.123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a /= \"123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a /= \"456.123\";"
"var_dump($a);"
"$a = \"123\" / 123;"
"var_dump($a);"
"$a = \"123\" / \"123\";"
"var_dump($a);"
"$a = \"321\" / 123;"
"var_dump($a);"
"$a = \"321\" / 123.456;"
"var_dump($a);"
);
return true;
}
bool TestCodeRun::TestModulus() {
MVCR("<?php "
"printf(\"%s\\n\", 30 % 30);"
"printf(\"%s\\n\", \"30\" % 30);"
"printf(\"%s\\n\", 30 % \"30\");"
"printf(\"%s\\n\", \"30\" % \"30\");"
);
MVCR("<?php "
"$a = \"123.456\" % 123;"
"var_dump($a);"
"$a = \"123.456\" % 456.123;"
"var_dump($a);"
"$a = \"123.456\" % \"123\";"
"var_dump($a);"
"$a = \"123.456\" % \"456.123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a %= 123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a %= 456.123;"
"var_dump($a);"
"$a = \"123.456\";"
"$a %= \"123\";"
"var_dump($a);"
"$a = \"123.456\";"
"$a %= \"456.123\";"
"var_dump($a);"
"$a = \"123\" % 123;"
"var_dump($a);"
"$a = \"123\" % \"123\";"
"var_dump($a);"
"$a = \"321\" % 123;"
"var_dump($a);"
"$a = \"321\" % 123.456;"
"var_dump($a);"
);
MVCR("<?php "
"$a = 1 % 9223372036854775807;"
"var_dump($a);");
return true;
}
bool TestCodeRun::TestOperationTypes() {
MVCR("<?php "
"$a = null; var_dump(+$a);"
"$a = null; var_dump(-$a);"
""
"$a = null; $b = null; var_dump($a + $b);"
"$a = null; $b = true; var_dump($a + $b);"
"$a = null; $b = 0; var_dump($a + $b);"
"$a = null; $b = 1; var_dump($a + $b);"
"$a = null; $b = 1.0; var_dump($a + $b);"
"$a = null; $b = '1.0'; var_dump($a + $b);"
"$a = null; $b = 'foo'; var_dump($a + $b);"
"$a = null; $b = new Exception(); var_dump($a + $b);"
"$a = null; $b = null; $b = 0; var_dump($a + $b);"
"$a = null; $b = null; $b = 1; var_dump($a + $b);"
"$a = null; $b = null; $b = 1.0; var_dump($a + $b);"
"$a = null; $b = null; $b = '1.0'; var_dump($a + $b);"
"$a = null; $b = null; $b = 'foo'; var_dump($a + $b);"
"$a = null; $b = null; $b = new Exception(); var_dump($a + $b);"
"$a = null; $b = null; $a += $b; var_dump($a);"
"$a = null; $b = true; $a += $b; var_dump($a);"
"$a = null; $b = 0; $a += $b; var_dump($a);"
"$a = null; $b = 1; $a += $b; var_dump($a);"
"$a = null; $b = 1.0; $a += $b; var_dump($a);"
"$a = null; $b = '1.0'; $a += $b; var_dump($a);"
"$a = null; $b = 'foo'; $a += $b; var_dump($a);"
"$a = null; $b = new Exception(); $a += $b; var_dump($a);"
"$a = null; $b = null; $b = 0; $a += $b; var_dump($a);"
"$a = null; $b = null; $b = 1; $a += $b; var_dump($a);"
"$a = null; $b = null; $b = 1.0; $a += $b; var_dump($a);"
"$a = null; $b = null; $b = '1.0'; $a += $b; var_dump($a);"
"$a = null; $b = null; $b = 'foo'; $a += $b; var_dump($a);"
"$a = null; $b = null; $b = new Exception(); $a += $b; var_dump($a);"
""
"$a = null; $b = null; var_dump($a - $b);"
"$a = null; $b = true; var_dump($a - $b);"
"$a = null; $b = 0; var_dump($a - $b);"
"$a = null; $b = 1; var_dump($a - $b);"
"$a = null; $b = 1.0; var_dump($a - $b);"
"$a = null; $b = '1.0'; var_dump($a - $b);"
"$a = null; $b = 'foo'; var_dump($a - $b);"
"$a = null; $b = new Exception(); var_dump($a - $b);"
"$a = null; $b = null; $b = 0; var_dump($a - $b);"
"$a = null; $b = null; $b = 1; var_dump($a - $b);"
"$a = null; $b = null; $b = 1.0; var_dump($a - $b);"
"$a = null; $b = null; $b = '1.0'; var_dump($a - $b);"
"$a = null; $b = null; $b = 'foo'; var_dump($a - $b);"
"$a = null; $b = null; $b = new Exception(); var_dump($a - $b);"
"$a = null; $b = null; $a -= $b; var_dump($a);"
"$a = null; $b = true; $a -= $b; var_dump($a);"
"$a = null; $b = 0; $a -= $b; var_dump($a);"
"$a = null; $b = 1; $a -= $b; var_dump($a);"
"$a = null; $b = 1.0; $a -= $b; var_dump($a);"
"$a = null; $b = '1.0'; $a -= $b; var_dump($a);"
"$a = null; $b = 'foo'; $a -= $b; var_dump($a);"
"$a = null; $b = new Exception(); $a -= $b; var_dump($a);"
"$a = null; $b = null; $b = 0; $a -= $b; var_dump($a);"
"$a = null; $b = null; $b = 1; $a -= $b; var_dump($a);"
"$a = null; $b = null; $b = 1.0; $a -= $b; var_dump($a);"
"$a = null; $b = null; $b = '1.0'; $a -= $b; var_dump($a);"
"$a = null; $b = null; $b = 'foo'; $a -= $b; var_dump($a);"
"$a = null; $b = null; $b = new Exception(); $a -= $b; var_dump($a);"
""
"$a = null; $b = null; var_dump($a * $b);"
"$a = null; $b = true; var_dump($a * $b);"
"$a = null; $b = 0; var_dump($a * $b);"
"$a = null; $b = 1; var_dump($a * $b);"
"$a = null; $b = 1.0; var_dump($a * $b);"
"$a = null; $b = '1.0'; var_dump($a * $b);"
"$a = null; $b = 'foo'; var_dump($a * $b);"
"$a = null; $b = new Exception(); var_dump($a * $b);"
"$a = null; $b = null; $b = 0; var_dump($a * $b);"
"$a = null; $b = null; $b = 1; var_dump($a * $b);"
"$a = null; $b = null; $b = 1.0; var_dump($a * $b);"
"$a = null; $b = null; $b = '1.0'; var_dump($a * $b);"
"$a = null; $b = null; $b = 'foo'; var_dump($a * $b);"
"$a = null; $b = null; $b = new Exception(); var_dump($a * $b);"
"$a = null; $b = null; $a *= $b; var_dump($a);"
"$a = null; $b = true; $a *= $b; var_dump($a);"
"$a = null; $b = 0; $a *= $b; var_dump($a);"
"$a = null; $b = 1; $a *= $b; var_dump($a);"
"$a = null; $b = 1.0; $a *= $b; var_dump($a);"
"$a = null; $b = '1.0'; $a *= $b; var_dump($a);"
"$a = null; $b = 'foo'; $a *= $b; var_dump($a);"
"$a = null; $b = new Exception(); $a *= $b; var_dump($a);"
"$a = null; $b = null; $b = 0; $a *= $b; var_dump($a);"
"$a = null; $b = null; $b = 1; $a *= $b; var_dump($a);"
"$a = null; $b = null; $b = 1.0; $a *= $b; var_dump($a);"
"$a = null; $b = null; $b = '1.0'; $a *= $b; var_dump($a);"
"$a = null; $b = null; $b = 'foo'; $a *= $b; var_dump($a);"
"$a = null; $b = null; $b = new Exception(); $a *= $b; var_dump($a);"
""
"$a = null; $b = true; var_dump($a / $b);"
"$a = null; $b = 1; var_dump($a / $b);"
"$a = null; $b = 1.0; var_dump($a / $b);"
"$a = null; $b = '1.0'; var_dump($a / $b);"
"$a = null; $b = null; $b = 1; var_dump($a / $b);"
"$a = null; $b = null; $b = 1.0; var_dump($a / $b);"
"$a = null; $b = null; $b = '1.0'; var_dump($a / $b);"
"$a = null; $b = true; $a /= $b; var_dump($a);"
"$a = null; $b = 1; $a /= $b; var_dump($a);"
"$a = null; $b = 1.0; $a /= $b; var_dump($a);"
"$a = null; $b = '1.0'; $a /= $b; var_dump($a);"
"$a = null; $b = null; $b = 1; $a /= $b; var_dump($a);"
"$a = null; $b = null; $b = 1.0; $a /= $b; var_dump($a);"
"$a = null; $b = null; $b = '1.0'; $a /= $b; var_dump($a);"
""
"$a = true; $b = null; var_dump($a + $b);"
"$a = true; $b = true; var_dump($a + $b);"
"$a = true; $b = 0; var_dump($a + $b);"
"$a = true; $b = 1; var_dump($a + $b);"
"$a = true; $b = 1.0; var_dump($a + $b);"
"$a = true; $b = '1.0'; var_dump($a + $b);"
"$a = true; $b = 'foo'; var_dump($a + $b);"
"$a = true; $b = new Exception(); var_dump($a + $b);"
"$a = true; $b = null; $b = 0; var_dump($a + $b);"
"$a = true; $b = null; $b = 1; var_dump($a + $b);"
"$a = true; $b = null; $b = 1.0; var_dump($a + $b);"
"$a = true; $b = null; $b = '1.0'; var_dump($a + $b);"
"$a = true; $b = null; $b = 'foo'; var_dump($a + $b);"
"$a = true; $b = null; $b = new Exception(); var_dump($a + $b);"
"$a = true; $b = null; $a += $b; var_dump($a);"
"$a = true; $b = true; $a += $b; var_dump($a);"
"$a = true; $b = 0; $a += $b; var_dump($a);"
"$a = true; $b = 1; $a += $b; var_dump($a);"
"$a = true; $b = 1.0; $a += $b; var_dump($a);"
"$a = true; $b = '1.0'; $a += $b; var_dump($a);"
"$a = true; $b = 'foo'; $a += $b; var_dump($a);"
"$a = true; $b = new Exception(); $a += $b; var_dump($a);"
"$a = true; $b = null; $b = 0; $a += $b; var_dump($a);"
"$a = true; $b = null; $b = 1; $a += $b; var_dump($a);"
"$a = true; $b = null; $b = 1.0; $a += $b; var_dump($a);"
"$a = true; $b = null; $b = '1.0'; $a += $b; var_dump($a);"
"$a = true; $b = null; $b = 'foo'; $a += $b; var_dump($a);"
"$a = true; $b = null; $b = new Exception(); $a += $b; var_dump($a);"
""
"$a = true; $b = null; var_dump($a - $b);"
"$a = true; $b = true; var_dump($a - $b);"
"$a = true; $b = 0; var_dump($a - $b);"
"$a = true; $b = 1; var_dump($a - $b);"
"$a = true; $b = 1.0; var_dump($a - $b);"
"$a = true; $b = '1.0'; var_dump($a - $b);"
"$a = true; $b = 'foo'; var_dump($a - $b);"
"$a = true; $b = new Exception(); var_dump($a - $b);"
"$a = true; $b = null; $b = 0; var_dump($a - $b);"
"$a = true; $b = null; $b = 1; var_dump($a - $b);"
"$a = true; $b = null; $b = 1.0; var_dump($a - $b);"
"$a = true; $b = null; $b = '1.0'; var_dump($a - $b);"
"$a = true; $b = null; $b = 'foo'; var_dump($a - $b);"
"$a = true; $b = null; $b = new Exception(); var_dump($a - $b);"
"$a = true; $b = null; $a -= $b; var_dump($a);"
"$a = true; $b = true; $a -= $b; var_dump($a);"
"$a = true; $b = 0; $a -= $b; var_dump($a);"
"$a = true; $b = 1; $a -= $b; var_dump($a);"
"$a = true; $b = 1.0; $a -= $b; var_dump($a);"
"$a = true; $b = '1.0'; $a -= $b; var_dump($a);"
"$a = true; $b = 'foo'; $a -= $b; var_dump($a);"
"$a = true; $b = new Exception(); $a -= $b; var_dump($a);"
"$a = true; $b = null; $b = 0; $a -= $b; var_dump($a);"
"$a = true; $b = null; $b = 1; $a -= $b; var_dump($a);"
"$a = true; $b = null; $b = 1.0; $a -= $b; var_dump($a);"
"$a = true; $b = null; $b = '1.0'; $a -= $b; var_dump($a);"
"$a = true; $b = null; $b = 'foo'; $a -= $b; var_dump($a);"
"$a = true; $b = null; $b = new Exception(); $a -= $b; var_dump($a);"
""
"$a = true; $b = null; var_dump($a * $b);"
"$a = true; $b = true; var_dump($a * $b);"
"$a = true; $b = 0; var_dump($a * $b);"
"$a = true; $b = 1; var_dump($a * $b);"
"$a = true; $b = 1.0; var_dump($a * $b);"
"$a = true; $b = '1.0'; var_dump($a * $b);"
"$a = true; $b = 'foo'; var_dump($a * $b);"
"$a = true; $b = new Exception(); var_dump($a * $b);"
"$a = true; $b = null; $b = 0; var_dump($a * $b);"
"$a = true; $b = null; $b = 1; var_dump($a * $b);"
"$a = true; $b = null; $b = 1.0; var_dump($a * $b);"
"$a = true; $b = null; $b = '1.0'; var_dump($a * $b);"
"$a = true; $b = null; $b = 'foo'; var_dump($a * $b);"
"$a = true; $b = null; $b = new Exception(); var_dump($a * $b);"
"$a = true; $b = null; $a *= $b; var_dump($a);"
"$a = true; $b = true; $a *= $b; var_dump($a);"
"$a = true; $b = 0; $a *= $b; var_dump($a);"
"$a = true; $b = 1; $a *= $b; var_dump($a);"
"$a = true; $b = 1.0; $a *= $b; var_dump($a);"
"$a = true; $b = '1.0'; $a *= $b; var_dump($a);"
"$a = true; $b = 'foo'; $a *= $b; var_dump($a);"
"$a = true; $b = new Exception(); $a *= $b; var_dump($a);"
"$a = true; $b = null; $b = 0; $a *= $b; var_dump($a);"
"$a = true; $b = null; $b = 1; $a *= $b; var_dump($a);"
"$a = true; $b = null; $b = 1.0; $a *= $b; var_dump($a);"
"$a = true; $b = null; $b = '1.0'; $a *= $b; var_dump($a);"
"$a = true; $b = null; $b = 'foo'; $a *= $b; var_dump($a);"
"$a = true; $b = null; $b = new Exception(); $a *= $b; var_dump($a);"
""
"$a = true; $b = true; var_dump($a / $b);"
"$a = true; $b = 1; var_dump($a / $b);"
"$a = true; $b = 1.0; var_dump($a / $b);"
"$a = true; $b = '1.0'; var_dump($a / $b);"
"$a = true; $b = null; $b = 1; var_dump($a / $b);"
"$a = true; $b = null; $b = 1.0; var_dump($a / $b);"
"$a = true; $b = null; $b = '1.0'; var_dump($a / $b);"
"$a = true; $b = true; $a /= $b; var_dump($a);"
"$a = true; $b = 1; $a /= $b; var_dump($a);"
"$a = true; $b = 1.0; $a /= $b; var_dump($a);"
"$a = true; $b = '1.0'; $a /= $b; var_dump($a);"
"$a = true; $b = null; $b = 1; $a /= $b; var_dump($a);"
"$a = true; $b = null; $b = 1.0; $a /= $b; var_dump($a);"
"$a = true; $b = null; $b = '1.0'; $a /= $b; var_dump($a);");
MVCR("<?php "
"var_dump(1 / 1.7976931348623157e+308 || false);");
/*
Fails under release build due to g++ optimization
MVCR("<?php "
"var_dump((1.7976931348623157e+308 + 1.7976931348623157e+308) << 0);");
*/
MVCR("<?php "
"function foo() {"
" return '1';"
"}"
"function bar() {"
" $a = 1;"
" $a += foo();"
" var_dump($a);"
" $b = 1;"
" $b -= foo();"
" var_dump($b);"
"}"
"bar();");
MVCR("<?php "
"$a = null;"
"$a += new Exception();"
"var_dump($a);");
return true;
}
#define UNARY_OP_DATA(op) \
"<?php " \
#op"(!null);" \
#op"(!true);" \
#op"(!false);" \
#op"(!0);" \
#op"(!1);" \
#op"(!1.2);" \
#op"(!\"\");" \
#op"(!\"0\");" \
#op"(!\"1\");" \
#op"(!\"1.2\");" \
#op"(!'');" \
#op"(!'0');" \
#op"(!'1');" \
#op"(!'1.2');" \
#op"(!__LINE__);" \
#op"(!__FUNCTION__);" \
#op"(!0x10);" \
#op"(!010);" \
#op"(!\"0x10\");" \
#op"(!\"010\");" \
#op"(+null);" \
#op"(+true);" \
#op"(+false);" \
#op"(+0);" \
#op"(+1);" \
#op"(+1.2);" \
#op"(+\"\");" \
#op"(+\"0\");" \
#op"(+\"1\");" \
#op"(+\"1.2\");" \
#op"(+'');" \
#op"(+'0');" \
#op"(+'1');" \
#op"(+'1.2');" \
#op"(+__LINE__);" \
#op"(+__FUNCTION__);" \
#op"(+0x10);" \
#op"(+010);" \
#op"(+\"0x10\");" \
#op"(+\"010\");" \
#op"(-null);" \
#op"(-true);" \
#op"(-false);" \
#op"(-0);" \
#op"(-1);" \
#op"(-1.2);" \
#op"(-\"\");" \
#op"(-\"0\");" \
#op"(-\"1\");" \
#op"(-\"1.2\");" \
#op"(-'');" \
#op"(-'0');" \
#op"(-'1');" \
#op"(-'1.2');" \
#op"(-__LINE__);" \
#op"(-__FUNCTION__);" \
#op"(-0x10);" \
#op"(-010);" \
#op"(-\"0x10\");" \
#op"(-\"010\");" \
#op"(~0);" \
#op"(~1);" \
#op"(~1.2);" \
#op"(~\"\");" \
#op"(~\"0\");" \
#op"(~\"1\");" \
#op"(~\"1.2\");" \
#op"(~'');" \
#op"(~'0');" \
#op"(~'1');" \
#op"(~'1.2');" \
#op"(~__LINE__);" \
#op"(~__FUNCTION__);" \
#op"(~0x10);" \
#op"(~010);" \
#op"(~\"0x10\");" \
#op"(~\"010\");" \
#op"((null));" \
#op"((true));" \
#op"((false));" \
#op"((0));" \
#op"((1));" \
#op"((1.2));" \
#op"((\"\"));" \
#op"((\"0\"));" \
#op"((\"1\"));" \
#op"((\"1.2\"));" \
#op"((''));" \
#op"(('0'));" \
#op"(('1'));" \
#op"(('1.2'));" \
#op"((__LINE__));" \
#op"((__FUNCTION__));" \
#op"((0x10));" \
#op"((010));" \
#op"((\"0x10\"));" \
#op"((\"010\"));" \
#op"((int)null);" \
#op"((int)true);" \
#op"((int)false);" \
#op"((int)0);" \
#op"((int)1);" \
#op"((int)1.2);" \
#op"((int)\"\");" \
#op"((int)\"0\");" \
#op"((int)\"1\");" \
#op"((int)\"1.2\");" \
#op"((int)'');" \
#op"((int)'0');" \
#op"((int)'1');" \
#op"((int)'1.2');" \
#op"((int)__LINE__);" \
#op"((int)__FUNCTION__);" \
#op"((int)0x10);" \
#op"((int)010);" \
#op"((int)\"0x10\");" \
#op"((int)\"010\");" \
#op"((integer)null);" \
#op"((integer)true);" \
#op"((integer)false);" \
#op"((integer)0);" \
#op"((integer)1);" \
#op"((integer)1.2);" \
#op"((integer)\"\");" \
#op"((integer)\"0\");" \
#op"((integer)\"1\");" \
#op"((integer)\"1.2\");" \
#op"((integer)'');" \
#op"((integer)'0');" \
#op"((integer)'1');" \
#op"((integer)'1.2');" \
#op"((integer)__LINE__);" \
#op"((integer)__FUNCTION__);" \
#op"((integer)0x10);" \
#op"((integer)010);" \
#op"((integer)\"0x10\");" \
#op"((integer)\"010\");" \
#op"((bool)null);" \
#op"((bool)true);" \
#op"((bool)false);" \
#op"((bool)0);" \
#op"((bool)1);" \
#op"((bool)1.2);" \
#op"((bool)\"\");" \
#op"((bool)\"0\");" \
#op"((bool)\"1\");" \
#op"((bool)\"1.2\");" \
#op"((bool)'');" \
#op"((bool)'0');" \
#op"((bool)'1');" \
#op"((bool)'1.2');" \
#op"((bool)__LINE__);" \
#op"((bool)__FUNCTION__);" \
#op"((bool)0x10);" \
#op"((bool)010);" \
#op"((bool)\"0x10\");" \
#op"((bool)\"010\");" \
#op"((boolean)null);" \
#op"((boolean)true);" \
#op"((boolean)false);" \
#op"((boolean)0);" \
#op"((boolean)1);" \
#op"((boolean)1.2);" \
#op"((boolean)\"\");" \
#op"((boolean)\"0\");" \
#op"((boolean)\"1\");" \
#op"((boolean)\"1.2\");" \
#op"((boolean)'');" \
#op"((boolean)'0');" \
#op"((boolean)'1');" \
#op"((boolean)'1.2');" \
#op"((boolean)__LINE__);" \
#op"((boolean)__FUNCTION__);" \
#op"((boolean)0x10);" \
#op"((boolean)010);" \
#op"((boolean)\"0x10\");" \
#op"((boolean)\"010\");" \
#op"((float)null);" \
#op"((float)true);" \
#op"((float)false);" \
#op"((float)0);" \
#op"((float)1);" \
#op"((float)1.2);" \
#op"((float)\"\");" \
#op"((float)\"0\");" \
#op"((float)\"1\");" \
#op"((float)\"1.2\");" \
#op"((float)'');" \
#op"((float)'0');" \
#op"((float)'1');" \
#op"((float)'1.2');" \
#op"((float)__LINE__);" \
#op"((float)__FUNCTION__);" \
#op"((float)0x10);" \
#op"((float)010);" \
#op"((float)\"0x10\");" \
#op"((float)\"010\");" \
#op"((double)null);" \
#op"((double)true);" \
#op"((double)false);" \
#op"((double)0);" \
#op"((double)1);" \
#op"((double)1.2);" \
#op"((double)\"\");" \
#op"((double)\"0\");" \
#op"((double)\"1\");" \
#op"((double)\"1.2\");" \
#op"((double)'');" \
#op"((double)'0');" \
#op"((double)'1');" \
#op"((double)'1.2');" \
#op"((double)__LINE__);" \
#op"((double)__FUNCTION__);" \
#op"((double)0x10);" \
#op"((double)010);" \
#op"((double)\"0x10\");" \
#op"((double)\"010\");" \
#op"((real)null);" \
#op"((real)true);" \
#op"((real)false);" \
#op"((real)0);" \
#op"((real)1);" \
#op"((real)1.2);" \
#op"((real)\"\");" \
#op"((real)\"0\");" \
#op"((real)\"1\");" \
#op"((real)\"1.2\");" \
#op"((real)'');" \
#op"((real)'0');" \
#op"((real)'1');" \
#op"((real)'1.2');" \
#op"((real)__LINE__);" \
#op"((real)__FUNCTION__);" \
#op"((real)0x10);" \
#op"((real)010);" \
#op"((real)\"0x10\");" \
#op"((real)\"010\");" \
#op"((string)null);" \
#op"((string)true);" \
#op"((string)false);" \
#op"((string)0);" \
#op"((string)1);" \
#op"((string)1.2);" \
#op"((string)\"\");" \
#op"((string)\"0\");" \
#op"((string)\"1\");" \
#op"((string)\"1.2\");" \
#op"((string)'');" \
#op"((string)'0');" \
#op"((string)'1');" \
#op"((string)'1.2');" \
#op"((string)__LINE__);" \
#op"((string)__FUNCTION__);" \
#op"((string)0x10);" \
#op"((string)010);" \
#op"((string)\"0x10\");" \
#op"((string)\"010\");" \
#op"(1.7e+319);" \
#op"(!1.7e+319);" \
#op"(+1.7e+319);" \
#op"(-1.7e+319);" \
#op"(~1.7e+319);" \
#op"((1.7e+319));" \
#op"((int)1.7e+319);" \
#op"((integer)1.7e+319);" \
#op"((bool)1.7e+319);" \
#op"((boolean)1.7e+319);" \
#op"((float)1.7e+319);" \
#op"((double)1.7e+319);" \
#op"((real)1.7e+319);" \
#op"((string)1.7e+319);" \
#op"(\"1.7e+319\");" \
#op"(!\"1.7e+319\");" \
#op"(+\"1.7e+319\");" \
#op"(-\"1.7e+319\");" \
#op"(~\"1.7e+319\");" \
#op"((\"1.7e+319\"));" \
#op"((int)\"1.7e+319\");" \
#op"((integer)\"1.7e+319\");" \
#op"((bool)\"1.7e+319\");" \
#op"((boolean)\"1.7e+319\");" \
#op"((float)\"1.7e+319\");" \
#op"((double)\"1.7e+319\");" \
#op"((real)\"1.7e+319\");" \
#op"((string)\"1.7e+319\");"
#define UNARY_OP_ARRAY_DATA(op) \
"<?php " \
#op"(array(\"\\0\" => 1));" \
#op"(array(\"\\0\" => \"\\0\"));" \
#op"(array(\"\\0\" => \"\\\\\"));" \
#op"(array(\"\\0\" => \"\\'\"));" \
#op"(array(\"\\\\\" => 1));" \
#op"(array(\"\\\\\" => \"\\0\"));" \
#op"(array(\"\\\\\" => \"\\\\\"));" \
#op"(array(\"\\\\\" => \"\\'\"));" \
#op"(array(\"\\'\" => 1));" \
#op"(array(\"\\'\" => \"\\0\"));" \
#op"(array(\"\\'\" => \"\\\\\"));" \
#op"(array(\"\\'\" => \"\\'\"));" \
#op"(array(\"\\a\" => \"\\a\"));" \
#op"(!array(\"\\0\" => \"\\0\"));" \
#op"((array(\"\\0\" => \"\\0\")));" \
#op"((int)array(\"\\0\" => \"\\0\"));" \
#op"((integer)array(\"\\0\" => \"\\0\"));" \
#op"((bool)array(\"\\0\" => \"\\0\"));" \
#op"((boolean)array(\"\\0\" => \"\\0\"));" \
#op"((float)array(\"\\0\" => \"\\0\"));" \
#op"((double)array(\"\\0\" => \"\\0\"));" \
#op"((real)array(\"\\0\" => \"\\0\"));" \
#op"((string)array(\"\\0\" => \"\\0\"));" \
"$a = \"0x10\";" \
#op"($a);" \
#op"(\"\\0\");" \
"$a = array(\"\\0\" => 1);" \
#op"($a);" \
"$a = array(\"\\0\" => \"\\0\");" \
#op"($a);" \
"$a = array(\"\\0\" => \"\\\\\");" \
#op"($a);" \
"$a = array(\"\\0\" => \"\\'\");" \
#op"($a);" \
"$a = array(\"\\\\\" => 1);" \
#op"($a);" \
"$a = array(\"\\\\\" => \"\\0\");" \
#op"($a);" \
"$a = array(\"\\\\\" => \"\\\\\");" \
#op"($a);" \
"$a = array(\"\\\\\" => \"\\'\");" \
#op"($a);" \
"$a = array(\"\\'\" => 1);" \
#op"($a);" \
"$a = array(\"\\'\" => \"\\0\");" \
#op"($a);" \
"$a = array(\"\\'\" => \"\\\\\");" \
#op"($a);" \
"$a = array(\"\\'\" => \"\\'\");" \
#op"($a);" \
"$a = array(\"\\a\" => \"\\a\");" \
#op"($a);"
#define UNARY_OP(op) \
MVCR(UNARY_OP_DATA(op)) \
MVCR(UNARY_OP_ARRAY_DATA(op))
bool TestCodeRun::TestUnaryOperators() {
UNARY_OP(var_dump);
MVCR("<?php "
"function foo($x) {"
" if ($x) {"
" $a = array();"
" $s = 'hello';"
" $o = (object)null;"
" }"
" var_dump((array)$a, (array)$s, (array)$o);"
" var_dump((string)$a, (string)$s, (string)$o);"
" var_dump((object)$a);"
"var_dump((object)$s);"
"var_dump((object)$o);"
"}"
"foo(false);");
MVCR("<?php "
"function test($x) {"
" switch ($x) {"
" case 1:"
" $y = true;"
" case 2:"
" var_dump(isset($y), $y);"
" }"
"}"
"test(2);");
return true;
}
bool TestCodeRun::TestSilenceOperator() {
MVCR("<?php "
"@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX', \" />\");");
return true;
}
bool TestCodeRun::TestPrint() {
UNARY_OP(echo);
UNARY_OP(print);
UNARY_OP(print_r);
UNARY_OP(serialize);
return true;
}
bool TestCodeRun::TestVarExport() {
MVCR(UNARY_OP_DATA(var_export));
MVCRO(UNARY_OP_ARRAY_DATA(var_export),
"array (\n"
" '' . \"\\0\" . '' => 1,\n"
")array (\n"
" '' . \"\\0\" . '' => '' . \"\\0\" . '',\n"
")array (\n"
" '' . \"\\0\" . '' => '\\\\',\n"
")array (\n"
" '' . \"\\0\" . '' => '\\\\\\\'',\n"
")array (\n"
" '\\\\' => 1,\n"
")array (\n"
" '\\\\' => '' . \"\\0\" . '',\n"
")array (\n"
" '\\\\' => '\\\\',\n"
")array (\n"
" '\\\\' => '\\\\\\\'',\n"
")array (\n"
" '\\\\\\\'' => 1,\n"
")array (\n"
" '\\\\\\\'' => '' . \"\\0\" . '',\n"
")array (\n"
" '\\\\\\\'' => '\\\\',\n"
")array (\n"
" '\\\\\\\'' => '\\\\\\\'',\n"
")array (\n"
" '\\\\a' => '\\\\a',\n"
")falsearray (\n"
" '' . \"\\0\" . '' => '' . \"\\0\" . '',\n"
")11truetrue111'Array''0x10''' . \"\\0\" . ''array (\n"
" '' . \"\\0\" . '' => 1,\n"
")array (\n"
" '' . \"\\0\" . '' => '' . \"\\0\" . '',\n"
")array (\n"
" '' . \"\\0\" . '' => '\\\\',\n"
")array (\n"
" '' . \"\\0\" . '' => '\\\\\\\'',\n"
")array (\n"
" '\\\\' => 1,\n"
")array (\n"
" '\\\\' => '' . \"\\0\" . '',\n"
")array (\n"
" '\\\\' => '\\\\',\n"
")array (\n"
" '\\\\' => '\\\\\\\'',\n"
")array (\n"
" '\\\\\\\'' => 1,\n"
")array (\n"
" '\\\\\\\'' => '' . \"\\0\" . '',\n"
")array (\n"
" '\\\\\\\'' => '\\\\',\n"
")array (\n"
" '\\\\\\\'' => '\\\\\\\'',\n"
")array (\n"
" '\\\\a' => '\\\\a',\n"
")");
return true;
}
bool TestCodeRun::TestLocale() {
MVCRO("<?php "
"class A { public $a; function __toString() { return $this->a;}} "
"$a = new A; $a->a = 'a'; $b = new A; $b->a = 'b'; "
"$arr = array($a, $b); sort($arr, SORT_REGULAR, true); "
"print ((string)$arr[0]);",
"a");
MVCRO("<?php "
"class A { public $a; }"
"$a = new A; $a->a = 'a'; $b = new A; $b->a = 'b'; "
"$arr = array($b, $a);"
"print $arr[0]->a;"
"sort($arr, SORT_REGULAR, true); "
"print $arr[0]->a;",
"ba");
MVCRO("<?php "
"$a = array(1);"
"$b = array(2);"
"$arr = array($b, $a);"
"print $arr[0][0];"
"asort($arr, SORT_REGULAR, true); "
"print $arr[0][0];",
"22");
MVCR("<?php "
"$a = array(\"a bc\", \"\\xc1 bc\", \"d ef\");"
"asort($a);"
"print_r($a);"
"$a = array(\"a bc\", \"\\xc1 bc\", \"d ef\");"
"asort($a, SORT_LOCALE_STRING);"
"print_r($a);"
"$a = array(\"a bc\", \"\\xc1 bc\", \"d ef\");"
"setlocale(LC_ALL, \"pt_PT\");"
"asort($a);"
"print_r($a);"
"$a = array(\"a bc\", \"\\xc1 bc\", \"d ef\");"
"setlocale(LC_ALL, \"pt_PT\");"
"asort($a, SORT_LOCALE_STRING);"
"print_r($a);");
return true;
}
bool TestCodeRun::TestLogicalOperators() {
MVCR("<?php "
"function foo() { echo \"foo\"; }"
"$a = (false && foo());"
"$b = (true || foo());"
"$c = (false and foo());"
"$d = (true or foo());"
"$e = ($e || true);"
"$f = ($f or true);"
"$g = ($g && false);"
"$h = ($h and false);"
"var_dump($a, $b, $c, $d, $e, $f, $g, $h);");
MVCR("<?php "
"function foo($a) { echo \"foo\"; return $a; }"
"$x = true;"
"$x = $x and foo(false);"
"var_dump($x);"
"$x = $x && foo(false);"
"var_dump($x);"
"$x = false;"
"$x = $x or foo(true);"
"var_dump($x);"
"$x = $x || foo(true);"
"var_dump($x);");
MVCR("<?php var_dump($a || null);");
MVCR("<?php "
"function f($a) { var_dump('f:'.$a); return $a; }"
"function foo($a) {"
" var_dump($a && true);"
" var_dump(f($a) && true);"
" var_dump(true && $a);"
" var_dump(true && f($a));"
" var_dump($a && false);"
" var_dump(f($a) && false);"
" var_dump(false && $a);"
" var_dump(false && f($a));"
" var_dump($a || true);"
" var_dump(f($a) || true);"
" var_dump(true || $a);"
" var_dump(true || f($a));"
" var_dump($a || false);"
" var_dump(f($a) || false);"
" var_dump(false || $a);"
" var_dump(false || f($a));"
"}"
"foo(34);"
"foo(0);");
return true;
}
bool TestCodeRun::TestGetClass() {
MVCR("<?php "
"class foo {"
" function bar () {"
" var_dump(get_class());"
" var_dump(get_class(null));"
" }"
"}"
"class foo2 extends foo {"
"}"
"$f1 = new foo;"
"$f2 = new foo2;"
"var_dump(get_class($f1));"
"$f1->bar();"
"$f2->bar();"
"var_dump(get_class(\"qwerty\"));"
"var_dump(get_class($f1));"
"var_dump(get_class($f2));"
);
MVCR("<?php "
"abstract class bar {"
" public function __construct()"
" {"
" var_dump(get_class($this));"
" var_dump(get_class());"
" }"
"}"
"class foo extends bar {"
"}"
"new foo;"
);
return true;
}
bool TestCodeRun::TestGetParentClass() {
MVCR("<?php "
"class dad {"
" function dad()"
" {}"
"}"
"class child extends dad {"
" function child()"
" {"
" echo \"I'm \" , get_parent_class($this) , \"'s son\\n\";"
" }"
"}"
"class child2 extends dad {"
" function child2()"
" {"
" echo \"I'm \" , get_parent_class('child2') , \"'s son too\n\";"
" }"
"}"
"$foo = new child();"
"$bar = new child2();"
);
MVCR("<?php "
"interface i {"
" function test();"
"}"
"class foo implements i {"
" function test() {"
" var_dump(get_parent_class());"
" }"
"}"
"class bar extends foo {"
" function test_bar() {"
" var_dump(get_parent_class());"
" }"
"}"
"class goo extends bar {"
" function test_goo() {"
" var_dump(get_parent_class());"
" }"
"}"
"$bar = new bar;"
"$foo = new foo;"
"$goo = new goo;"
"$foo->test();"
"$bar->test();"
"$bar->test_bar();"
"$goo->test();"
"$goo->test_bar();"
"$goo->test_goo();"
"var_dump(get_parent_class($bar));"
"var_dump(get_parent_class($foo));"
"var_dump(get_parent_class($goo));"
"var_dump(get_parent_class(\"bar\"));"
"var_dump(get_parent_class(\"foo\"));"
"var_dump(get_parent_class(\"goo\"));"
"var_dump(get_parent_class(\"i\"));"
"var_dump(get_parent_class(\"\"));"
"var_dump(get_parent_class(\"[[[[\"));"
"var_dump(get_parent_class(\" \"));"
"var_dump(get_parent_class(new stdclass));"
"var_dump(get_parent_class(array()));"
"var_dump(get_parent_class(1));"
);
return true;
}
bool TestCodeRun::TestRedeclaredFunctions() {
MVCR("<?php "
"if (true) {"
" function test() {"
" echo('a');"
" }"
"} else {"
" function test() {"
" echo('b');"
" }"
"}"
"test();"
);
MVCR("<?php "
"function test($a, $b, $c, $d, $e, $f, $g = 0) {"
" return $a;"
"}"
"if (0) { function test($a) {} }"
"test(1,2,3,4,5,6);");
return true;
}
bool TestCodeRun::TestRedeclaredClasses() {
MVCR(
"<?php\n"
"$b = 123;\n"
"if ($b) {\n"
" class Exception1 extends Exception {}\n"
"} else {\n"
" class Exception1 extends Exception {}\n"
"}\n"
"class Exception2 extends Exception1 {}\n"
"\n"
"function foo() {\n"
" $e = new Exception();\n"
" try {\n"
" throw new Exception2();\n"
" } catch (Exception $e) {\n"
" var_dump($e->getCode());\n"
" }\n"
"}\n"
"foo();\n"
);
MVCR("<?php "
"class base1 {}"
"class base2 {}"
"if (true) {"
" class a extends base1 {"
" const aconst = \"firstA\";"
" const a1const = 0;"
" static $astat = 1;"
" static $a1stat = 1;"
" function __construct() { echo \"first def made\n\"; }"
" static function foo() { return 1;}"
" }"
"} else {"
" class a extends base2 {"
" const aconst = \"secondA\";"
" const a2const = 0;"
" static $astat = 2;"
" static $a2stat = 2;"
" function __construct() { echo \"second def made\n\"; }"
" static function foo() { return 2;}"
" }"
"}"
"$foo = \"foo\";"
"$y = new a;"
"var_dump(a::foo());"
"var_dump(a::$foo());"
"var_dump(call_user_func(array('a','foo')));"
"var_dump(a::$astat);"
"var_dump(a::$a1stat);"
"var_dump(a::aconst);"
"var_dump(a::a1const);"
"var_dump(method_exists('a',\"foo\"));"
"var_dump(method_exists($y,\"foo\"));"
"var_dump(property_exists(\"a\",\"astat\"));"
"var_dump(property_exists(\"a\",\"a1stat\"));"
"var_dump(property_exists(\"a\",\"a2stat\"));"
"var_dump(get_parent_class($y));"
"var_dump(is_subclass_of(\"a\", \"base1\"));"
"var_dump(is_subclass_of(\"a\", \"base2\"));"
"var_dump(get_object_vars($y));"
);
MVCR("<?php "
"if (true) {"
" class base {"
" public $baseVal = 'base';"
" static $baseStatic = 'baseStat';"
" function childProp() { return $this->childProp; }"
" function testChildMeth() { return $this->childMeth(); }"
" static function baseStatMeth() {"
" return 'Base static method';"
" }"
" function childMeth() { return 'I am base'; }"
" }"
"} else {"
" class base {"
" }"
"}"
"class child1 extends base {"
" public $child1Val = 'child1';"
" public $childProp = 'IamChild1';"
" static $child1Static = 'child1Stat';"
" function childMeth() {"
" return 'I am child1';"
" }"
" static function child1StatMeth() {"
" return 'Child 1 static method';"
" }"
" function parentChildMeth() {"
" return parent::childMeth();"
" }"
"}"
"class child2 extends child1 {"
" public $child2Val = 'child2';"
" public $childProp = 'IamChild2';"
" static $child2Static = 'child2Stat';"
" static function child2StatMeth() {"
" return 'Child 2 static method';"
" }"
" function childMeth() {"
" return 'I am child2';"
" }"
" function parentChildMeth() {"
" return parent::childMeth();"
" }"
" function testChildMeth2() { return $this->childMeth(); }"
"}"
"if (true) {"
" class child3 extends child2 {"
" public $child3Val = 'child3';"
" public $childProp = 'IamChild3';"
" static $child3Static = 'child3Stat';"
" function childMeth() {"
" return 'I am child3';"
" }"
" static function child3StatMeth() {"
" return 'Child 3 static method';"
" }"
" function parentChildMeth() {"
" return parent::childMeth();"
" }"
""
" }"
"} else {"
" class child3 {}"
"}"
"function test($val, $exp, $feature) {"
" if ($val !== $exp) {"
" echo $feature . \" failed. Got:\\n\";"
" var_dump($val);"
" echo \"But expected:\\n\";"
" var_dump($exp);"
" } else {"
" echo $feature . \" passed\\n\";"
" }"
"}"
"function run() {"
" $base = new base;"
" test($base->baseVal, 'base', 'Base object member');"
" test(base::$baseStatic, 'baseStat', 'Base static member');"
" test(base::baseStatMeth(), 'Base static method', 'Base static method');"
" test($base->baseStatMeth(), 'Base static method', 'Base static method obj syntax');"
" $child1 = new child1;"
" test($child1->baseVal, 'base', 'dRedec inherited property');"
" test($child1->child1Val, 'child1', 'dRedec property');"
" test($child1->testChildMeth(), 'I am child1', 'dRedec parent->virtual method');"
" test($child1->childProp(), 'IamChild1', 'dRedec parent->child prop method');"
" test(child1::child1StatMeth(), 'Child 1 static method', 'dRedec static method');"
" test(child1::baseStatMeth(), 'Base static method', 'dRedec parent static method');"
" test($child1->child1StatMeth(), 'Child 1 static method', 'dRedec static method obj syntax');"
" test($child1->baseStatMeth(), 'Base static method', 'dRedec parent static method obj syntax');"
" test(child1::$baseStatic, 'baseStat', 'dRedec parent static prop');"
" test(child1::$child1Static, 'child1Stat', 'dRedec static prop');"
" test($child1->parentChildMeth(), 'I am base', 'dRedec parent method');"
" $child2 = new child2;"
" test($child2->baseVal, 'base', 'ddRedec grandparent property');"
" test($child2->child1Val, 'child1', 'ddRedec parent property');"
" test($child2->child2Val, 'child2', 'ddRedec property');"
" test($child2->testChildMeth(), 'I am child2', 'ddRedec grandparent->virtual method');"
" test($child2->testChildMeth2(), 'I am child2', 'ddRedec parent->virtual method');"
" test($child2->childProp(), 'IamChild2', 'ddRedec grandparent->child prop method');"
" test(child2::baseStatMeth(), 'Base static method', 'ddRedec grandparent static method');"
" test(child2::child1StatMeth(), 'Child 1 static method', 'ddRedec parent static method');"
" test(child2::child2StatMeth(), 'Child 2 static method', 'ddRedec static method');"
" test($child2->baseStatMeth(), 'Base static method', 'ddRedec grandparent static method obj syntax');"
" test($child2->child1StatMeth(), 'Child 1 static method', 'ddRedec parent static method obj syntax');"
" test($child2->child2StatMeth(), 'Child 2 static method', 'ddRedec static method obj syntax');"
" test(child2::$baseStatic, 'baseStat', 'ddRedec grandparent static prop');"
" test(child2::$child1Static, 'child1Stat', 'ddRedec parent static prop');"
" test(child2::$child2Static, 'child2Stat', 'ddRedec static prop');"
" test($child2->parentChildMeth(), 'I am child1', 'ddRedec parent method');"
" $child3 = new child3;"
" test($child3->baseVal, 'base', 'RddRedec greatgrandparent property');"
" test($child3->child1Val, 'child1', 'RddRedec grandparent property');"
" test($child3->child2Val, 'child2', 'RddRedec parent property');"
" test($child3->child3Val, 'child3', 'RddRedec property');"
" test($child3->testChildMeth(), 'I am child3', 'RddRedec greatgrandparent->virtual method');"
" test($child3->testChildMeth2(), 'I am child3', 'RddRedec grandparent->virtual method');"
" test($child3->childProp(), 'IamChild3', 'RddRedec greatgrandparent->child prop method');"
" test(child3::baseStatMeth(), 'Base static method', 'RddRedec greatgrandparent static method');"
" test(child3::child1StatMeth(), 'Child 1 static method', 'RddRedec grandparent static method');"
" test(child3::child2StatMeth(), 'Child 2 static method', 'RddRedec parent static method');"
" test(child3::child3StatMeth(), 'Child 3 static method', 'RddRedec static method');"
" test($child3->baseStatMeth(), 'Base static method', 'RddRedec greatgrandparent static method obj syntax');"
" test($child3->child1StatMeth(), 'Child 1 static method', 'RddRedec grandparent static method obj syntax');"
" test($child3->child2StatMeth(), 'Child 2 static method', 'RddRedec parent static method obj syntax');"
" test($child3->child3StatMeth(), 'Child 3 static method', 'RddRedec static method obj syntax');"
" test(child3::$baseStatic, 'baseStat', 'RddRedec greatgrandparent static prop');"
" test(child3::$child1Static, 'child1Stat', 'RddRedec grandparent static prop');"
" test(child3::$child2Static, 'child2Stat', 'RddRedec parent static prop');"
" test(child3::$child3Static, 'child3Stat', 'RddRedec static prop');"
" test($child3->parentChildMeth(), 'I am child2', 'RddRedec parent method');"
"}"
"run();"
);
MVCR("<?php "
"$i = 1;"
"if ($i == 1) {"
" class foo {"
" function foo() {"
" echo \"foo 1\";"
" }"
" function bar() {"
" echo \"bar 1\";"
" }"
" }"
"} else {"
" class foo {"
" function foo() {"
" echo \"foo 2\";"
" }"
" function bar() {"
" echo \"bar 2\";"
" }"
" }"
"}"
"$t = new foo();"
"$t->foo();"
"$t->bar();");
MVCR("<?php "
"$i = 2;"
"if ($i == 1) {"
" class foo {"
" function foo() {"
" echo \"foo 1\";"
" }"
" function bar() {"
" echo \"bar 1\";"
" }"
" }"
"} else {"
" class foo {"
" function foo() {"
" echo \"foo 2\";"
" }"
" function bar() {"
" echo \"bar 2\";"
" }"
" }"
"}"
"$t = new foo();"
"$t->foo();"
"$t->bar();");
MVCR("<?php "
"class a {"
" public static function x() {"
" echo 'x';"
" }"
"}"
"if (0) {"
" class b {"
" }"
"}"
"class b extends a{"
" public static function z() {"
" self::x();"
" }"
"}"
"b::x();");
MVCR("<?php "
"function f($i) {"
" $j = 1;"
" var_dump($j);"
" if ($i == 1) {"
" class p {"
" public $data1;"
" }"
" class c extends p {"
" }"
" function r() { echo \"r1\\n\"; }"
" } else {"
" class p {"
" public $data2;"
" }"
" class c extends p {"
" }"
" function r() { echo \"r2\\n\"; }"
" }"
"}"
"if ($i == 1) {"
" class p {"
" public $data1;"
" }"
" class c extends p {"
" }"
" function r() { echo \"r3\\n\"; }"
"}"
"f(1);"
"$obj = new p();"
"var_dump($obj);"
"$obj = new c();"
"var_dump($obj);"
"r();");
MVCR("<?php "
"class A {"
" protected static function foo() {}"
"}"
"if (false) {"
" class A{"
" protected static function foo() {}"
" }"
"}"
"class B extends A{}"
""
"class C extends B {"
" function x() {"
" self::FOO();"
" }"
"}");
MVCR("<?php "
"class A {"
" static function foo() {"
" static $z = 0;"
" $z++;"
" var_dump($z);"
" }"
"}"
"if (false) {"
" class A{}"
"}"
"class B extends A{}"
"class C extends B {}"
"A::foo();"
"B::foo();"
"C::foo();");
MVCR("<?php "
"$a = 1;"
"if ($a) {"
"interface A {}"
"} else {"
"interface A {}"
"}"
"if ($a) {"
"interface B extends A {}"
"} else {"
"interface B extends A {}"
"}"
"class Z implements B {}");
MVCR("<?php "
"$ok = 1;"
"if ($ok) {"
"class A {"
"const FOO = 'test';"
"public $a = A::FOO;"
"}"
"} else {"
"class A {"
"const FOO = 'test';"
"public $a = A::FOO;"
"}"
"}");
MVCR("<?php "
"class B {};"
"if (0) {"
" class B {}"
"}"
"class A extends B {"
" function __call($name,$args) { echo 'A::$name\n'; }"
"};"
"$a = new A;"
"call_user_func_array(array($a, 'foo'), array());");
MVCR("<?php "
"class A extends Exception { public $a = 1; }"
"if (0) {"
" class A { public $a = 2; }"
"}"
"function test() {"
"try {"
" throw new A;"
"} catch (A $e) {"
" echo $e->a, '\n';"
"}} test();");
MVCR("<?php "
"function nop($en,$es){};set_error_handler('nop');"
"class X { function bar() { var_dump($this); } }"
"if (1) {"
" class U {"
" }"
"} else {"
" class U extends X {"
" }"
"}"
"class V extends U {}"
"function test() {"
" $x = new X;"
" $x->bar();"
" $x = new V;"
" $x->bar();"
"}"
"test();");
MVCR("<?php "
"if (true) { class base extends Exception {} } else { class base {} }"
"class child1 extends base {}"
"$obj = new child1;"
"echo ($obj instanceof Exception) ? \"Passed\n\" : \"Failed\n\";");
MVCR("<?php "
"class PEAR {"
" static function f() { PEAR::g(); }"
" function g() { echo 'This is g()'; }"
"}"
"if ($x) {"
" class PEAR {}"
"}"
"class D1 extends PEAR {"
" public $foo;"
" private $bar;"
" function bar() { return $this->foo + $this->bar; }"
"}"
"class D2 extends D1 {"
" public $foo;"
" private $bar;"
" function bar() { return $this->foo + $this->bar; }"
"}"
"PEAR::f();");
MVCR("<?php\n"
"function __autoload($c) { var_dump($c); }\n"
"function f() { return false; }\n"
"if (f()) {\n"
" interface A { }\n"
" class B { }\n"
" interface C { }\n"
"} else {\n"
" class A { }\n"
" interface B { }\n"
" interface C { }\n"
"}\n"
"function test($c) {\n"
" var_dump(class_exists('A'));\n"
" var_dump(interface_exists('A'));\n"
" var_dump(class_exists('B'));\n"
" var_dump(interface_exists('B'));\n"
" var_dump(class_exists($c));\n"
" var_dump(interface_exists('C'));\n"
"}\n"
"test('C');\n");
MVCR("<?php "
"class A {"
" static function bar(&$a) {"
" $a = 'ok';"
" }"
"}"
"$a = 'failed';"
"A::bar($a);"
"var_dump($a);"
"if (false) {"
" class A{}"
" class A2{}"
"}"
"class C {"
" static function bar() {"
" }"
"}"
"class A2 extends C {"
" static function bar(&$a) {"
" $a = 'ok';"
" }"
"}"
"$a = 'failed';"
"A2::bar($a);"
"var_dump($a);");
MVCR("<?php "
"if (!isset($g2)) {"
" class test {}"
"} else {"
" class test {"
" static $foo = 27;"
" }"
" var_dump(test::$foo);"
"}"
"$x = new test();"
"$x->bar = 1;"
"$x->foo = 2;"
"var_dump($x);");
MVCR("<?php "
"class A { function fun() { return 'A'; } }"
"if (true) { class B {}} else { class B {} }"
"class C extends B {"
" public function foo() { $this->out(A::fun()); }"
" public function out($arg) { var_dump($arg); }"
"}"
"$c = new C();"
"$c->foo();");
MVCR("<?php "
"class b {"
" function z() {"
" $this->x();"
" }"
" function y() {"
" echo 'y';"
" }"
"}"
"class c extends b {"
" function x() {"
" $this->y();"
" }"
"}"
"if (false) {"
" class b{}"
" class c{}"
"}"
"$x = new c();"
"$x->z();");
MVCR("<?php "
"class A {}"
"class B extends A {"
" function meh() {"
" return $this;"
" }"
"}"
"class C extends B {"
" function work() {"
" echo \"WORK\n\";"
" }"
"}"
"if (false) {"
" class A {}"
" class B {}"
" class C {}"
"}"
"function test() {"
" $x = new C;"
" $x->meh()->work();"
"}"
"test();");
MVCR("<?php "
"if (isset($g)) {"
" class X {}"
"} else {"
" class X {"
" static function foo() {}"
" function bar() {"
" X::foo(1,2,3);"
" }"
" }"
"}");
MVCR("<?php "
"if (isset($g)) {"
" class X {}"
"} else {"
" class X {"
" public $a = 1;"
" function __destruct() { var_dump(__METHOD__); }"
" }"
"}"
"class X1 extends X {"
" public $t = 1;"
"}"
"function test() {"
" $x = new X1;"
" $x->t = 5;"
" $x->a = 3;"
" $y = clone $x;"
" var_dump($y->a,$y->t);"
"}"
"test();");
MVCR("<?php "
"if (true) {"
" class A {"
" private $a = 1;"
" }"
" class B extends A {"
" public $a;"
" function f() { $this->a = 2; }"
" }"
"} else {"
" class A {"
" protected $a = 1;"
" }"
" class B extends A {"
" public $a;"
" function f() { $this->a = 2; }"
" }"
"}"
"$obj = new B;"
"$obj->f();"
"var_dump($obj);");
MVCR("<?php "
"if (isset($g)) { class c{} } else { class c{} }"
"class d extends c {"
" private $b = 'b';"
" function t2() {"
" foreach ($this as $k => $v) {"
" var_dump($v);"
" }"
" }"
"}"
"$x = new d;"
"$x->t2();");
MVCR("<?php "
"if (!isset($h)) {"
" if (isset($g)) {"
" interface A { function foo(); }"
" } else {"
" interface A { function foo(); }"
" }"
"} else {"
" if (isset($g)) {"
" interface X { function foo(); }"
" } else {"
" interface X { function foo(); }"
" }"
"}"
"abstract class B implements A { function bar() {} }"
"var_dump(get_class_methods('A'));"
"var_dump(get_class_methods('B'));"
"var_dump(get_class_methods('X'));"
"var_dump(get_class_methods('Y'));");
MVCR("<?php "
"if (isset($g)) {"
" class X { function foo() { var_dump(__METHOD__); } }"
" class Y extends X {}"
"} else {"
" class X { function foo() { var_dump(__METHOD__); } }"
" class Y {}"
"}"
"class Z extends Y {"
" function foo() { var_dump(__METHOD__); }"
" function bar() { X::foo(); }"
"}"
"Z::bar();");
MVCR("<?php "
"if (isset($g)) {"
" class X {}"
"} else {"
" class X {"
" function __destruct() { var_dump(__METHOD__); }"
" protected $prot_over_prot = 1;"
" public $pub_over_pub = 2;"
" protected $pub_over_prot = 3;"
" }"
"}"
"class Y extends X {"
" function __destruct() { var_dump(__METHOD__,$this); }"
" protected $prot_over_prot = 4;"
" public $pub_over_pub = 5;"
" public $pub_over_prot = 6;"
" protected $prot_base = 7;"
" public $pub_base = 8;"
"}"
"class Z extends Y {"
" function __destruct() { var_dump(__METHOD__); }"
" public $prot_over_prot = 9;"
" public $pub_over_pub = 10;"
" public $pub_over_prot = 11;"
" public $prot_base = 12;"
" public $pub_base = 13;"
"}"
"function foo($x) {"
" $s = serialize($x);"
" var_dump($s);"
" $y = unserialize($s);"
" var_dump($y);"
" var_dump((array)$y);"
" if (function_exists('apc_store')) {"
" apc_store('foo', $y);"
" $z = apc_fetch('foo');"
" } else {"
" $z = clone $y;"
" }"
" var_dump($z);"
" unset($z, $y);"
" var_dump($x);"
"}"
"$y = new y;"
"foo($y);"
"$z = new z;"
"foo($z);"
"unset($z, $y);");
return true;
}
bool TestCodeRun::TestReassignThis() {
MVCRONW("<?php "
"class Foo {"
" function Bar() {"
" $__this = $this;"
" $this = null;"
" debug_backtrace();"
" $this = $__this;"
" } "
"}", "");
MVCRONW("<?php "
"function foo() {"
" $this = 2;"
" echo \"You should not see this\"; "
"} "
"foo();", "");
MVCRONW("<?php "
"$x = 5; "
"$this =& $x; "
"echo \"You should not see this\";", "");
MVCRONW("<?php "
"class Foo {"
" public $x; "
"} "
"$this = new Foo(); "
"echo \"You should not see this\";", "");
MVCRONW("<?php "
"class Foo {"
" public $x; "
"} "
"$this =& new Foo(); "
"echo \"You should not see this\";", "");
MVCRONW("<?php "
"$myarray = array(1 => 2, 2 => 3); "
"foreach ($myarray as $this => $wat) {"
" echo \"You should not see this\"; "
"}", "");
MVCRONW("<?php "
"$myarray = array(1 => 2, 2 => 3); "
"foreach ($myarray as $a => $this) {"
" echo \"You should not see this\"; "
"}", "");
return true;
}
bool TestCodeRun::TestClone() {
MVCR("<?php "
"class A {"
" public $foo = 0;"
" public $fooref = 1;"
" private $foopriv = 2;"
" function __clone() {"
" echo \"clone\n\";"
" }"
"}"
"$a1 = new A;"
"$p = 8;"
"$q = 9;"
"$a1->foo = 'foo';"
"$a1->fooref = &$p;"
"$a1->dyn = 'dyn';"
"$a1->dynref = &$q;"
"var_dump($a1);"
"$a2 = clone $a1;"
"var_dump($a1);"
"var_dump($a2);"
"$a2->foo = 'a2foo';"
"$a2->fooref = 'a2fooref';"
"$a2->dyn = 'a2dyn';"
"$a2->dynref = 'a2dynref';"
"$a2->dynref2 = 'dynref2';"
"var_dump($a1);"
"var_dump($a2);"
"var_dump($p);"
"var_dump($q);");
MVCR("<?php "
"class c {"
" protected $cm = 'get';"
" function x() {"
" var_dump($this->cm);"
" }"
"}"
"class c2 extends c {}"
"$y = new c;"
"$y->x();"
"$z = clone $y;"
"$z->x();"
"$y = new c2;"
"$y->x();"
"$z = clone $y;"
"$z->x();");
return true;
}
bool TestCodeRun::TestEvalOrder() {
MVCRO("<?php\n"
"set_error_handler('h');\n"
"foo(var_dump('123'));\n"
"var_dump('end');\n"
"function h() { var_dump('errored');}",
"string(7) \"errored\"\n");
MVCRO("<?php\n"
"set_error_handler('h');\n"
"class A {} $obj = new A; $obj->foo(var_dump('123'));\n"
"var_dump('end');\n"
"function h() { var_dump('errored');}",
"string(7) \"errored\"\n");
MVCR("<?php "
"$a = array(123); "
"foreach ($a as $x => $x) { "
" var_dump($x); "
"}");
MVCR("<?php\n"
"\n"
"class MyIterator implements Iterator{\n"
" private $var = array();\n"
" public function __construct($array) {\n"
" echo \"constructing\n\";\n"
" if (is_array($array)) {\n"
" $this->var = $array;\n"
" }\n"
" }\n"
" public function rewind() {\n"
" echo \"rewinding\n\";\n"
" reset($this->var);\n"
" }\n"
" public function current() {\n"
" $var = current($this->var);\n"
" echo \"current: $var\n\";\n"
" return $var;\n"
" }\n"
" public function key() {\n"
" $var = key($this->var);\n"
" echo \"key: $var\n\";\n"
" return $var;\n"
" }\n"
" public function next() {\n"
" $var = next($this->var);\n"
" echo \"next: $var\n\";\n"
" return $var;\n"
" }\n"
" public function valid() {\n"
" $var = $this->current() !== false;\n"
" echo \"valid: \",$var?'true':'false',\"\n\";\n"
" return $var;\n"
" }\n"
"}\n"
"\n"
"function f() { var_dump('f'); return 0; }\n"
"function g() { var_dump('g'); return 0; }\n"
"\n"
"$a = array(1, 2);\n"
"$values = array('a' => 1, 'b' => 2, 'c' => 3);\n"
"$it = new MyIterator($values);\n"
"foreach ($it as $a[f()] => $a[g()]) {\n"
" print \"$a[0]\n\";\n"
"}\n");
MVCR("<?php "
"class X {} "
"function foo() { var_dump('foo');} "
"$x = new X; "
"unset($x->a[foo()]->y); ");
MVCR("<?php "
"function foo($i) { "
" var_dump($i); "
" return 'a'; "
"} "
"${foo(1)}[foo(2)][foo(3)] = foo(4); "
);
MVCR("<?php "
"class A {"
" public $foo;"
" public $bar;"
" function q($a) {"
" echo $a;"
" $this->foo = 9;"
" $this->bar = '3';"
" return $this;"
" }"
"}"
"$a = new A();"
"var_dump($a->q('1')->foo + $a->q('2')->bar);"
"var_dump($a->q('1')->foo - $a->q('2')->bar);"
"var_dump($a->q('1')->foo / $a->q('2')->bar);"
"var_dump($a->q('1')->foo * $a->q('2')->bar);"
"var_dump($a->q('1')->foo % $a->q('2')->bar);"
"var_dump($a->q('1')->foo << $a->q('2')->bar);"
"var_dump($a->q('1')->foo >> $a->q('2')->bar);"
"var_dump($a->q('1')->foo && $a->q('2')->bar);"
"var_dump($a->q('1')->foo || $a->q('2')->bar);"
"var_dump($a->q('1')->foo and $a->q('2')->bar);"
"var_dump($a->q('1')->foo or $a->q('2')->bar);"
"var_dump($a->q('1')->foo xor $a->q('2')->bar);"
"var_dump($a->q('1')->foo . $a->q('2')->bar);"
"var_dump($a->q('1')->foo & $a->q('2')->bar);"
"var_dump($a->q('1')->foo | $a->q('2')->bar);"
"var_dump($a->q('1')->foo ^ $a->q('2')->bar);"
"var_dump($a->q('1')->foo == $a->q('2')->bar);"
"var_dump($a->q('1')->foo === $a->q('2')->bar);"
"var_dump($a->q('1')->foo != $a->q('2')->bar);"
"var_dump($a->q('1')->foo !== $a->q('2')->bar);"
"var_dump($a->q('1')->foo > $a->q('2')->bar);"
"var_dump($a->q('1')->foo >= $a->q('2')->bar);"
"var_dump($a->q('1')->foo < $a->q('2')->bar);"
"var_dump($a->q('1')->foo <= $a->q('2')->bar);"
);
MVCR("<?php "
"function x($a, $b, $c, $d) {}"
"function p($x) { echo $x . \"\n\"; return $x; }"
"class c {"
" function __construct($a, $b, $c, $d) {}"
" function f($a, $b, $c, $d) {}"
" static function g($a, $b, $c, $d) {}"
"}"
"function rt(&$a, $v) {"
" $a = $v;"
"}"
"function id($x) { return $x; }"
"function dump($a, $b) {"
" var_dump($a, $b);"
"}"
"echo \"sfc\n\";"
"x(p(1), p(2), p(3), 4);"
"$y = 'x';"
"echo \"dfc\n\";"
"$y(p(1), p(2), p(3), 4);"
"echo \"smc\n\";"
"c::g(p(1), p(2), p(3), 4);"
"$y = 'g';"
"echo \"dsmc\n\";"
"c::$y(p(1), p(2), p(3), 4);"
"echo \"occ\n\";"
"$q = new c(p(1), p(2), p(3), 4);"
"echo \"omc\n\";"
"$q->f(p(1), p(2), p(3), 4);"
"echo \"rsfc\n\";"
"rt($a, id(10));"
"var_dump($a);"
"dump($v++, $v++);"
"$v = 10;"
"dump($v, $v = 0);"
"echo \"nest\n\";"
"x(p(1), x(p(2), p(3), p(4), p(5)), p(6), x(p(7), p(8), p(9), p(10)));"
"echo \"arr\n\";"
"$z = array(p(1), p(2), x(p(3), p(4), p(5), p(6)), p(7));"
"$q = 1;"
"$z = array(1, 2, $q);"
);
MVCR("<?php "
"error_reporting(E_ALL & ~E_NOTICE);"
"function id($x,$y) { return $x; }"
"function id1($x) { return $x; }"
"function pid($x) { var_dump($x); return $x; }"
"class cls {"
" function __construct() { print 'ctor\n'; }"
" function f($x) { return $this; }"
" function ttest() {"
" return $this->f(pid('arg1'),pid('arg2'));"
" }"
"}"
"$d = id1(new cls())"
" ->f('arg1')"
" ->f('arg2')"
" ->f('arg3');"
"$d = id1(new cls())"
" ->f('arg1', 'argex1')"
" ->f('arg2', 'argex2')"
" ->f('arg3', 'argex3');"
"$d = id(new cls(), pid('idarg'))"
" ->f(pid('arg1'), pid('argex1'))"
" ->f(pid('arg2'), pid('argex2'))"
" ->f(pid('arg3'), pid('argex3'));"
"$d->ttest();");
MVCR("<?php "
"class a {"
" function r(&$x) {"
" $x = 20;"
" }"
"}"
"function id($x) { return $x; }"
"$a = new a();"
"id($a)->r($x);"
"var_dump($x);");
MVCR("<?php "
"class c {"
" function x($y) {"
" echo $y . \"\n\";"
" return $this;"
" }"
"}"
"function p($x) {"
" echo $x . \"\n\";"
" return $x;"
"}"
"$x = new c;"
"$x->x(3, p(1), p(2))->x(6, p(4), p(5));");
MVCR("<?php "
"class Q {"
" public $val;"
" function __construct($v) {"
" $this->val = $v;"
" }"
" public function blah() {"
" return $this;"
" }"
"}"
"class A {"
" public $v;"
" function set($v) {"
" $this->v = $v;"
" return $this;"
" }"
"}"
"function id($x) { return $x; }"
"$x = new Q(0);"
"$a = id(new A)->set($x);"
"$x = id(new Q(1))->blah();"
"var_dump($a);");
MVCR("<?php "
"$a = array(array($id = 1, $id), array($id = 2, $id));"
"var_dump($a);"
"$a = array(+($id = 1), $id, -($id = 2), $id, "
" !($id = 3), $id, ~($id = 4), $id, "
" isset($a[$id = 5]), $id);"
"var_dump($a);");
MVCR("<?php "
"function test($a)"
"{"
" echo \"$a\\n\";"
"}"
"test(1, test(2), test(3, test(4), test(5)));");
MVCR("<?php "
"$v = 1;"
"function foo($a, $b, $c) {"
" var_dump($a, $b, $c);"
"}"
"function bar($a) {"
" foo($a, $a++, $a);"
" $arr = array($a, $a++, $a);"
" var_dump($arr);"
"}"
"bar($v);");
MVCR("<?php "
"$GLOBALS['t'] = 0;"
"$GLOBALS['f'] = 0;"
"$GLOBALS['i'] = 0;"
"$GLOBALS['d'] = 0;"
"$GLOBALS['v'] = 'a';"
"function t() {"
" global $t;"
" $t++;"
" return true;"
"}"
"function f() {"
" global $f;"
" $f++;"
" return false;"
"}"
"function i() {"
" global $i;"
" $i++;"
" return 1;"
"}"
"function d() {"
" global $d;"
" $d++;"
" return 3.14;"
"}"
"function v() {"
" global $v;"
" $v++;"
" return $v;"
"}"
"function foo() {"
" var_dump(t() + t());"
" var_dump(t() + f());"
" var_dump(t() + i());"
" var_dump(t() + d());"
" var_dump(t() + v());"
" var_dump(f() + t());"
" var_dump(f() + f());"
" var_dump(f() + i());"
" var_dump(f() + d());"
" var_dump(f() + v());"
" var_dump(i() + t());"
" var_dump(i() + f());"
" var_dump(i() + i());"
" var_dump(i() + d());"
" var_dump(i() + v());"
" var_dump(d() + t());"
" var_dump(d() + f());"
" var_dump(d() + i());"
" var_dump(d() + d());"
" var_dump(d() + v());"
" var_dump(v() + t());"
" var_dump(v() + f());"
" var_dump(v() + i());"
" var_dump(v() + d());"
" var_dump(v() + v());"
" var_dump($GLOBALS['t'], $GLOBALS['f'],"
" $GLOBALS['i'], $GLOBALS['d'],"
" $GLOBALS['v']);"
" var_dump(t() - t());"
" var_dump(t() - f());"
" var_dump(t() - i());"
" var_dump(t() - d());"
" var_dump(t() - v());"
" var_dump(f() - t());"
" var_dump(f() - f());"
" var_dump(f() - i());"
" var_dump(f() - d());"
" var_dump(f() - v());"
" var_dump(i() - t());"
" var_dump(i() - f());"
" var_dump(i() - i());"
" var_dump(i() - d());"
" var_dump(i() - v());"
" var_dump(d() - t());"
" var_dump(d() - f());"
" var_dump(d() - i());"
" var_dump(d() - d());"
" var_dump(d() - v());"
" var_dump(v() - t());"
" var_dump(v() - f());"
" var_dump(v() - i());"
" var_dump(v() - d());"
" var_dump(v() - v());"
" var_dump($GLOBALS['t'], $GLOBALS['f'],"
" $GLOBALS['i'], $GLOBALS['d'],"
" $GLOBALS['v']);"
" var_dump(t() * t());"
" var_dump(t() * f());"
" var_dump(t() * i());"
" var_dump(t() * d());"
" var_dump(t() * v());"
" var_dump(f() * t());"
" var_dump(f() * f());"
" var_dump(f() * i());"
" var_dump(f() * d());"
" var_dump(f() * v());"
" var_dump(i() * t());"
" var_dump(i() * f());"
" var_dump(i() * i());"
" var_dump(i() * d());"
" var_dump(i() * v());"
" var_dump(d() * t());"
" var_dump(d() * f());"
" var_dump(d() * i());"
" var_dump(d() * d());"
" var_dump(d() * v());"
" var_dump(v() * t());"
" var_dump(v() * f());"
" var_dump(v() * i());"
" var_dump(v() * d());"
" var_dump(v() * v());"
" var_dump($GLOBALS['t'], $GLOBALS['f'],"
" $GLOBALS['i'], $GLOBALS['d'],"
" $GLOBALS['v']);"
"}"
"foo();");
MVCR("<?php "
"function f($a) { echo \"test$a\\n\"; return 1; }"
"function bug2($a, $b) {"
" return isset($b[f($a++)], $b[f($a++)], $b[f($a++)]);"
"}"
"bug2(0, array());");
MVCR("<?php var_dump($v++, $v++);");
MVCR("<?php var_dump($v, $v = 0);");
MVCR("<?php\n"
"function f(&$a, &$b) { $a = 1; $b = 2; return 3; }\n"
"class A { }\n"
"function test() {\n"
" $a = array(); f($a[0], $a[1]); var_dump($a);\n"
" $a = array(); $a[0] = f($a[1], $a[2]); var_dump($a);\n"
" $a = new A(); f($a->f, $a->g); var_dump($a);\n"
"}\n"
"test();\n");
MVCR("<?php "
"class C {"
" function __construct() {"
" echo \"class C\\n\";"
" }"
" public function __get( $what ) {"
" echo \"get C\\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C\\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"function f() {"
" echo \"f()\\n\";"
" return 1;"
"}"
"function foo() {"
" $obj = new C;"
" $obj->a = f();"
" $obj->b = new C;"
" $obj->b->a = f();"
"}"
"foo();");
MVCR("<?php "
"class C implements ArrayAccess {"
" private $data = array();"
" public function __construct() {"
" echo \"C\\n\";"
" }"
" public function offsetGet($name) {"
" echo \"offsetGet: $name\\n\";"
" return $this->data[$name];"
" }"
" public function offsetSet($name, $value) {"
" $a = serialize($value);"
" echo \"offsetSet: $name=$a\\n\";"
" $this->data[$name]=$value;"
" }"
" public function offsetExists($name) {"
" echo \"offsetExists: $name\\n\"; return true;"
" }"
" public function offsetUnset($name) {"
" echo \"offsetUnset: $name\\n\";"
" }"
"}"
"function f() {"
" echo \"f()\\n\";"
" return 1;"
"}"
"function f2() {"
" echo \"f2()\\n\";"
" return 'foo';"
"}"
"function foo($a) {"
" $a['foo'] = new C;"
" $a['foo']['bar'] = new C;"
" $a['foo']['bar']['goo'] = f();"
"}"
"foo(new C);");
MVCR("<?php "
"class X {"
" function __destruct() { var_dump('done'); }"
"}"
"function f() {"
" $x = new X;"
"}"
"function g() {"
" var_dump('start');"
" f();"
" var_dump('end');"
"}"
"g();");
MVCR("<?php "
"function foo($v) {"
" $a = array('key' => &$v);"
" return $a;"
"}"
"function goo($v) {"
" return $v . 1;"
"}"
"var_dump(foo('1.0'));"
"var_dump(foo(foo('1.0')));"
"var_dump(foo(goo('1.0')));");
MVCR("<?php "
"function f(&$a, $v = 5) {"
" $a = $v;"
" return 0;"
"}"
"$a = 2;"
"var_dump($a . f($a));"
"$a = 2;"
"var_dump(($a.'') . f($a));"
"$a = 2;"
"var_dump(($a.$a) . f($a));"
"f($a,2);"
"var_dump($a . f($a));"
"f($a,2);"
"var_dump(($a.'') . f($a));"
"f($a,2);"
"var_dump(($a.$a) . f($a));"
"class c {"
" public static $a;"
"}"
"c::$a = 2;"
"var_dump(c::$a . f(c::$a));"
"function g(&$a) {"
" $a[0] = 5;"
" return 0;"
"}"
"$a = array(2);"
"var_dump($a[0] . g($a));"
"$a = array(2);"
"var_dump(($a[0] . '') . g($a));"
"function h(&$a) {"
" $a = 5;"
" return 0;"
"}"
"$a = array(2);"
"var_dump($a[0] . h($a[0]));"
"$a = array(2);"
"var_dump(($a[0] . '') . h($a[0]));"
"function k($a) {"
" $a->prop = 5;"
" return 0;"
"}"
"$a = new stdclass;"
"$a->prop = 2;"
"var_dump($a->prop . k($a));"
"$a = new stdclass;"
"$a->prop = 2;"
"var_dump(($a->prop . '') . k($a));"
"$i = 0;"
"var_dump($i . ++$i);"
"$i = 0;"
"var_dump(($i . '') . ++$i);"
"function foo() {"
" return 'foo';"
"}"
"f($a, 'test');"
"var_dump(($a . 'x') . foo($a = ''));"
"$a = array(2);"
"var_dump($a[$a = 0]);"
"$a = new stdclass;"
"$a->foo = 42;"
"var_dump($a->{$a = 'foo'});"
"var_dump($a);"
"$b = new stdclass;"
"$a = null;"
"$a->{f($a,$b)} = 5;"
"var_dump($a, $b);"
"function dump($a, $b) {"
" var_dump($a, $b);"
"}"
"f($a, 'foo');"
"dump($a, $a = 'bar');"
"$a = 'foo';"
"dump($a, $a = 'bar');"
"f($a, 'foo');"
"dump($a.'', $a = 'bar');"
"f($a, 'foo');"
"dump($a.$a, $a = 'bar');");
MVCR("<?php "
"$a = Array(1,2,3); "
"$b = Array(4,5,6); "
"$i = 1; "
"$a[$i++] = $b[$i++]; "
"var_dump($a);");
MVCR("<?php "
"function f($x) {"
" global $a;"
" var_dump($x, $a);"
" return $x;"
"}"
"class X implements ArrayAccess {"
" function OffsetGet($n) {"
" echo 'get:'; var_dump($n);"
" return (string)(int)$n == (string)$n ? $this : $n;"
" }"
" function OffsetSet($n, $v) {"
" $this->{$n} = $v;"
" echo 'set:'; var_dump($n, $v);"
" }"
" function OffsetExists($n) { return $n == 'foo'; }"
" function OffsetUnset($n) {}"
" function __get($n) { return $this->OffsetGet($n); }"
" function __set($n,$v) { return $this->OffsetSet($n, $v); }"
"}"
"$a = new X;"
"function ref(&$a, &$b, &$c) {"
"}"
"function test() {"
" global $a;"
" $a[f(0)]->{f(1)}[f(2)] = $a[f(3)][f(4)][f(5)]->foo;"
" var_dump($a[f(6)]['fuz'] . f(7));"
" ref($a[f(10)][f(11)][f(12)],$a[f(20)][f(21)][f(22)],"
" $a[f(30)][f(31)][f(32)]);"
" $a->{f(0)}[f(1)]->{f(2)} = $a->{f(3)}->{f(4)}->bar;"
"}"
"test();");
MVCR("<?php "
"class X { function foo($a) { echo 'In foo:'; var_dump($a); } }"
"function y($y) { echo 'In y:'; var_dump($y); }"
"function test($x, $y) {"
" $x->foo($x = null);"
" $y($y = null);"
"}"
"test(new X, 'y');");
MVCR("<?php "
"function f() { global $a; return ++$a; }"
"var_dump(array($a,f(),$a));");
MVCR("<?php "
"function foo() {"
" global $a;"
" $a = 1;"
"}"
"$a = 'a'; $r = ++$a . $a; var_dump($r);"
"$a = 'a'; $r = $a++ . $a; var_dump($r);"
"$a = 'a'; $r = $a . ++$a; var_dump($r);"
"$a = 'a'; $r = $a . $a++; var_dump($r);"
"$a = 'a'; $r = ++$a . ++$a; var_dump($r);"
"$a = 'a'; $r = ++$a . $a++; var_dump($r);"
"$a = 'a'; $r = $a++ . ++$a; var_dump($r);"
"$a = 'a'; $r = $a++ . $a++; var_dump($r);"
"$a = 'a'; $b = 'b'; $r = $a . foo() . $b; var_dump($r);"
"$a = 'a'; $b = 'b'; $r = $a . (foo() . $b); var_dump($r);");
MVCR("<?php "
"function test($x) {"
" $a = array($a => $x[$a = 'foo']);"
" return $a;"
"}"
"var_dump(test(array('foo' => 5)));");
MVCR("<?php "
"interface I {}"
"function __autoload($c) {"
" var_dump($c);"
" class A implements I {}"
"}"
"var_dump(class_implements(\"A\", false));"
"var_dump(class_implements(\"A\"));"
"var_dump(class_exists(\"A\"));");
MVCR("<?php "
"class B {}"
"function __autoload($c) {"
" var_dump($c);"
" class A extends B {}"
"}"
"var_dump(class_parents(\"A\", false));"
"var_dump(class_parents(\"A\"));"
"var_dump(class_exists(\"A\"));");
MVCRO("<?php "
"trait T {}"
"function __autoload($c) {"
" var_dump($c);"
" class A { use T; }"
"}"
"var_dump(class_uses(\"A\", false));"
"var_dump(class_uses(\"A\"));"
"var_dump(class_exists(\"A\"));"
,
"bool(false)\n"
"string(1) \"A\"\n"
"array(1) {\n"
" [\"T\"]=>\n"
" string(1) \"T\"\n"
"}\n"
"bool(true)\n"
);
return true;
}
bool TestCodeRun::TestGetObjectVars() {
MVCR("<?php "
"class Base"
"{"
" public $aaa = 1;"
" protected $bbb = 2;"
" private $ccc = 3;"
"}"
"class Child extends Base"
"{"
" private $ddd = 4;"
"}"
"var_dump(get_object_vars(new Base()));"
"var_dump(get_object_vars(new Child()));"
);
MVCR("<?php "
"class Base"
"{"
" public $aaa = 1;"
" protected $bbb = 2;"
" private $ccc = 3;"
"}"
"class Child extends Base"
"{"
" public $ddd = 4;"
"}"
"class Unrelated"
"{"
" function foo($obj) {"
" var_dump(get_object_vars($obj));"
" }"
"}"
"$base_obj = new Base();"
"$child_obj = new Child();"
"$unrelated_obj = new Unrelated();"
"$unrelated_obj->foo($child_obj);"
"$unrelated_obj->foo($base_obj);"
);
MVCR("<?php "
"class Base"
"{"
" public $aaa = 1;"
" protected $bbb = 2;"
" private $ccc = 3;"
" function foo($obj) {"
" var_dump(get_class($obj));"
" var_dump(get_object_vars($obj));"
" }"
"}"
"class Child extends Base"
"{"
" public $ddd = 4;"
" protected $eee = 5;"
" private $fff = 6;"
"}"
""
"$base_obj = new Base();"
"$child_obj = new Child();"
"$base_obj->foo($child_obj);"
);
MVCR("<?php "
"class Base"
"{"
" public $aaa = 1;"
" protected $bbb = 2;"
" private $ccc = 3;"
" function foo($obj) {"
" var_dump(get_class($obj));"
" var_dump(get_object_vars($obj));"
" }"
"}"
"class Child extends Base"
"{"
" public $ddd = 5;"
" protected $eee = 6;"
" private $fff = 4;"
"}"
"$base_obj = new Base();"
"$base_obj->foo($base_obj);"
);
MVCR("<?php "
"class Base"
"{"
" public $aaa = 1;"
" protected $bbb = 2;"
" private $ccc = 3;"
"}"
""
"class Child extends Base"
"{"
" public $ddd = 4;"
" protected $eee = 5;"
" private $fff = 6;"
" function foo($obj) {"
" var_dump(get_class($obj));"
" var_dump(get_object_vars($obj));"
" }"
"}"
"$child_obj = new Child();"
"$base_obj = new Base();"
"$child_obj->foo($base_obj);"
);
MVCR("<?php "
"var_dump(get_object_vars(false));"
"var_dump(get_object_vars(true));"
"var_dump(get_object_vars('hello'));"
"var_dump(get_object_vars(5));");
return true;
}
bool TestCodeRun::TestSerialization() {
MVCR("<?php\n"
"class A implements Serializable {\n"
" public $__foo = true;\n"
" public function serialize() {\n"
" return null;\n"
" }\n"
" public function unserialize($serialized) {\n"
" }\n"
"} var_dump(unserialize(serialize(new A())));");
MVCR("<?php\n"
"class A implements Serializable {\n"
" public $__foo = true;\n"
" public function serialize() {\n"
" return serialize(array('a' => 'apple', 'b' => 'banana'));\n"
" }\n"
" public function unserialize($serialized) {\n"
" $props = unserialize($serialized);\n"
" $this->a = $props['a'];\n"
" $this->b = $props['b'];\n"
" }\n"
"} $obj = unserialize(serialize(new A())); var_dump($obj->b);");
MVCR("<?php "
"class Small {"
" private static $nc = 0;"
" public $name;"
" public $num;"
" function __construct() {"
" $n = self::$nc++;"
" $this->name = 'foo'.$n;"
" $this->num = 3*$n;"
" }"
"}"
"class Big {"
" public $groupAll = array();"
" public $group1 = array();"
" public $group2 = array();"
" public $wacky;"
" public $nothing;"
" public $unrelated = array();"
" function add() {"
" $s = new Small();"
" $this->groupAll[] = $s;"
" if ($s->num % 2 == 0) {"
" $this->group1[]=array($s->name, $s);"
" } else {"
" $this->group2[]=array($s->name, $s);"
" }"
" }"
" function finish() {"
" $x = 10;"
" $this->wacky = array(&$x, &$x);"
" $s = new Small();"
" $this->unrelated[] = $s;"
" $this->unrelated[] = $s;"
" $this->unrelated[] = $s;"
" }"
"}"
"function t() {"
" $b = new Big;"
" for ($i = 0; $i < 10; ++$i) {"
" $b->add();"
" }"
" $b->finish();"
" var_dump($b);"
" $s = serialize($b);"
" var_dump($s);"
" $us = unserialize($s);"
" var_dump($us);"
"}"
"t();"
);
MVCR("<?php "
"class t {"
" public $foo = 10;"
" protected $bar = 20;"
" private $derp = 30;"
"}"
"class t2 extends t {"
" private $derp2 = 40;"
" protected $bar2 = 50;"
"}"
"$x = new t;"
"print_r($x);"
"var_dump($x);"
"echo serialize($x) . '\n';"
""
"$x2 = new t2;"
"print_r($x2);"
"var_dump($x2);"
"echo serialize($x2) . '\n';");
MVCR("<?php "
"class b {"
" private $foo = 1;"
" private $bar = 2;"
"}"
"class b2 extends b {"
" public $bar = 3;"
"}"
"$x = new b2;"
"$x->foo = 100;"
"var_dump((array)$x);"
"var_dump(serialize($x));"
"var_dump($x);");
// Zend PHP 5.2 has a bug here, fixed in 5.3.
MVCR("<?php\n"
"$a = array(array());\n"
"$a[0][0] = &$a[0];\n"
"var_dump(serialize($a));\n");
MVCRO("<?php "
"var_dump(unserialize('a:1:{s:1:\"1\";s:3:\"foo\";}'));"
"var_dump(unserialize('a:1:{d:1;s:3:\"foo\";}'));"
"var_dump(unserialize('a:1:{a:1:{i:0;i:1;}}'));"
,
"array(1) {\n"
" [\"1\"]=>\n"
" string(3) \"foo\"\n"
"}\n"
"bool(false)\n"
"bool(false)\n");
MVCR("<?php "
"class X {"
" private $priv = 'priv';"
" protected $prot = 'prot';"
"}"
"$x = new X;"
"$s = serialize($x);"
"$s = str_replace('X', 'Y', $s);"
"$x = unserialize($s);"
"var_dump($x,$x->prot,$x->priv);");
MVCR("<?php "
"class Y {"
" private $priv = 'priv';"
" protected $prot = 'prot';"
"}"
"class Z extends Y {}"
"$x = new Z;"
"$s = serialize($x);"
"$x = unserialize($s);"
"var_dump($x);"
"var_dump(serialize($x));");
MVCR("<?php "
"class X {"
" private $priv;"
" protected $prot;"
" public $pub;"
" function __construct($a,$b,$c) {"
" $this->priv = $a;"
" $this->prot = $b;"
" $this->pub = $c;"
" }"
" function foo() { var_dump($this->priv, $this->prot, $this->pub); }"
"}"
"$x = new X(1,2,3);"
"$s = serialize($x);"
"$x = unserialize($s);"
"var_dump($x);"
"$x->foo();");
MVCR("<?php "
"class X {}"
"$a = new X;"
"$q = array(1,2,3);"
"$a->foo = &$q;"
"for ($i = 0; $i < 10; $i++) $a->{'x'.$i} = clone $a;"
"$a->bar = &$q;"
"$s = serialize($a);"
"var_dump($s);"
"$A = unserialize($s);"
"var_dump($A);"
"$r = &$A->bar;"
"var_dump(array_keys($r));");
MVCR("<?php "
"class X {"
" private $str;"
" private $arr;"
" private $obj;"
" function foo() {"
" $this->str = 'hello';"
" $this->arr = array(1,2,3);"
" $this->obj = $this;"
" }"
"}"
"function test() {"
" $x = new X;"
" $s = serialize($x);"
" $x = unserialize($s);"
" var_dump($x);"
"}"
"test();");
return true;
}
bool TestCodeRun::TestJson() {
MVCR("<?php "
"$a = array();"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode($a));");
MVCR("<?php "
"$a = array(1.23456789e+34, 1E666, 1E666/1E666);"
"$e = json_encode($a);"
"var_dump($a);");
MVCR("<?php "
"var_dump(json_decode(\"[\\\"a\\\",1,true,false,null]\", true));");
MVCR("<?php "
"class A {"
" public $a = 'foo';"
" protected $b = 'bar';"
" private $c = 'blah';"
" public function aaaa() {"
" var_dump(json_encode($this));"
" }"
"}"
"$obj = new A();"
"$obj->aaaa();");
// recursive object
MVCR("<?php\n"
"class Foo { }\n"
"$foo = new Foo(); $foo->foo = $foo;\n"
"var_dump(json_encode($foo));\n");
#if 0
MVCR("<?php "
"$a = array(1);"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\");"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(1, \"2\");"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>1, \"2\"=>2);"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>\"1\", \"2\"=>\"2\");"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>1, 2=>\"2\");"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(1);"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\");"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(1, \"2\");"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>1, \"2\"=>2);"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>\"1\", \"2\"=>\"2\");"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>1, 2=>\"2\");"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode($a));"
""
"$a = array(1);"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\");"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(1, \"2\");"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>1, \"2\"=>2);"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>\"1\", \"2\"=>\"2\");"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>1, 2=>\"2\");"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(1);"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\");"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(1, \"2\");"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>1, \"2\"=>2);"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>\"1\", \"2\"=>\"2\");"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(\"1\"=>1, 2=>\"2\");"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode($a));"
""
"$a = array(1);"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\");"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(1, \"2\");"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>1, \"2\"=>2);"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>\"1\", \"2\"=>\"2\");"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>1, 2=>\"2\");"
"$a[] = $a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(1);"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\");"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(1, \"2\");"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>1, \"2\"=>2);"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>\"1\", \"2\"=>\"2\");"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>1, 2=>\"2\");"
"$a[] = &$a;"
"var_dump($a);"
"var_dump(json_encode(&$a));"
""
"$a = array(1);"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\");"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(1, \"2\");"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>1, \"2\"=>2);"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>\"1\", \"2\"=>\"2\");"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>1, 2=>\"2\");"
"$a[] = $a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(1);"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\");"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(1, \"2\");"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>1, \"2\"=>2);"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>\"1\", \"2\"=>\"2\");"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));"
""
"$a = array(\"1\"=>1, 2=>\"2\");"
"$a[] = &$a;"
"var_dump(&$a);"
"var_dump(json_encode(&$a));");
#endif
return true;
}
bool TestCodeRun::TestThrift() {
MVCRO("<?php "
"class TType {"
" const STOP = 0;"
" const VOID = 1;"
" const BOOL = 2;"
" const BYTE = 3;"
" const I08 = 3;"
" const DOUBLE = 4;"
" const I16 = 6;"
" const I32 = 8;"
" const I64 = 10;"
" const STRING = 11;"
" const UTF7 = 11;"
" const STRUCT = 12;"
" const MAP = 13;"
" const SET = 14;"
" const LST = 15;"
" const UTF8 = 16;"
" const UTF16 = 17;"
"}"
"class DummyProtocol {"
" public $t;"
" function __construct() {"
" $this->t = new DummyTransport();"
" }"
" function getTransport() {"
" return $this->t;"
" }"
"}"
"class DummyTransport {"
" public $buff = '';"
" public $pos = 0;"
" function flush() { }"
" function write($buff) {"
" $this->buff .= $buff;"
" }"
" function read($n) {"
" $r = substr($this->buff, $this->pos, $n);"
" $this->pos += $n;"
" return $r;"
" }"
"}"
"class TestStruct {"
" static $_TSPEC;"
""
" public $aBool = null;"
" public $anInt = null;"
" public $aString = null;"
" public $aDouble = null;"
" public $anInt64 = null;"
" public $aList = null;"
" public $aMap = null;"
" public $aSet = null;"
" public $anByte = null;"
" public $anI16 = null;"
""
" public function __construct($vals=null) {"
" if (!isset(self::$_TSPEC)) {"
" self::$_TSPEC = array("
" -1 => array("
" 'var' => 'aBool',"
" 'type' => TType::BOOL,"
" ),"
" 1 => array("
" 'var' => 'anInt',"
" 'type' => TType::I32,"
" ),"
" 2 => array("
" 'var' => 'aString',"
" 'type' => TType::STRING,"
" ),"
" 3 => array("
" 'var' => 'aDouble',"
" 'type' => TType::DOUBLE,"
" ),"
" 4 => array("
" 'var' => 'anInt64',"
" 'type' => TType::I64,"
" ),"
" 5 => array("
" 'var' => 'aList',"
" 'type' => TType::LST,"
" 'etype' => TType::DOUBLE,"
" 'elem' => array("
" 'type' => TType::DOUBLE,"
" ),"
" ),"
" 6 => array("
" 'var' => 'aMap',"
" 'type' => TType::MAP,"
" 'ktype' => TType::I32,"
" 'vtype' => TType::DOUBLE,"
" 'key' => array("
" 'type' => TType::I32,"
" ),"
" 'val' => array("
" 'type' => TType::DOUBLE,"
" ),"
" ),"
" 7 => array("
" 'var' => 'aSet',"
" 'type' => TType::SET,"
" 'etype' => TType::I32,"
" 'elem' => array("
" 'type' => TType::I32,"
" ),"
" ),"
" 8 => array("
" 'var' => 'anByte',"
" 'type' => TType::BYTE,"
" ),"
" 9 => array("
" 'var' => 'anI16',"
" 'type' => TType::I16,"
" ),"
" );"
" }"
" }"
"}"
""
"function test() {"
" $p = new DummyProtocol();"
" $v1 = new TestStruct();"
" $v1->aBool = true;"
" $v1->anInt = 1234;"
" $v1->aString = 'abcdef';"
" $v1->aDouble = 1.2345;"
" $v1->anInt64 = 8589934592;"
" $v1->aList = array(13.3, 23.4, 3576.2);"
" $v1->aMap = array(10=>1.2, 43=>5.33);"
" $v1->aSet = array(10=>true, 11=>true);"
" $v1->anByte = 123;"
" $v1->anI16 = 1234;"
" var_dump($v1);"
" thrift_protocol_write_binary($p, 'foomethod', 1, $v1, 20, true);"
" var_dump(md5($p->getTransport()->buff));"
" var_dump(thrift_protocol_read_binary($p, 'TestStruct', true));"
"}"
"test();"
,
"object(TestStruct)#3 (10) {\n"
" [\"aBool\"]=>\n"
" bool(true)\n"
" [\"anInt\"]=>\n"
" int(1234)\n"
" [\"aString\"]=>\n"
" string(6) \"abcdef\"\n"
" [\"aDouble\"]=>\n"
" float(1.2345)\n"
" [\"anInt64\"]=>\n"
" int(8589934592)\n"
" [\"aList\"]=>\n"
" array(3) {\n"
" [0]=>\n"
" float(13.3)\n"
" [1]=>\n"
" float(23.4)\n"
" [2]=>\n"
" float(3576.2)\n"
" }\n"
" [\"aMap\"]=>\n"
" array(2) {\n"
" [10]=>\n"
" float(1.2)\n"
" [43]=>\n"
" float(5.33)\n"
" }\n"
" [\"aSet\"]=>\n"
" array(2) {\n"
" [10]=>\n"
" bool(true)\n"
" [11]=>\n"
" bool(true)\n"
" }\n"
" [\"anByte\"]=>\n"
" int(123)\n"
" [\"anI16\"]=>\n"
" int(1234)\n"
"}\n"
"string(32) \"6b4fbe9563551f3dee970a74b883f923\"\n"
"object(TestStruct)#4 (10) {\n"
" [\"aBool\"]=>\n"
" bool(true)\n"
" [\"anInt\"]=>\n"
" int(1234)\n"
" [\"aString\"]=>\n"
" string(6) \"abcdef\"\n"
" [\"aDouble\"]=>\n"
" float(1.2345)\n"
" [\"anInt64\"]=>\n"
" int(8589934592)\n"
" [\"aList\"]=>\n"
" array(3) {\n"
" [0]=>\n"
" float(13.3)\n"
" [1]=>\n"
" float(23.4)\n"
" [2]=>\n"
" float(3576.2)\n"
" }\n"
" [\"aMap\"]=>\n"
" array(2) {\n"
" [10]=>\n"
" float(1.2)\n"
" [43]=>\n"
" float(5.33)\n"
" }\n"
" [\"aSet\"]=>\n"
" array(2) {\n"
" [10]=>\n"
" bool(true)\n"
" [11]=>\n"
" bool(true)\n"
" }\n"
" [\"anByte\"]=>\n"
" int(123)\n"
" [\"anI16\"]=>\n"
" int(1234)\n"
"}\n");
MVCRO(
"<?php "
"class TType {"
" const STOP = 0;"
" const VOID = 1;"
" const BOOL = 2;"
" const BYTE = 3;"
" const I08 = 3;"
" const DOUBLE = 4;"
" const I16 = 6;"
" const I32 = 8;"
" const I64 = 10;"
" const STRING = 11;"
" const UTF7 = 11;"
" const STRUCT = 12;"
" const MAP = 13;"
" const SET = 14;"
" const LST = 15;"
" const UTF8 = 16;"
" const UTF16 = 17;"
"}"
"class DummyProtocol {"
" public $t;"
" function __construct() {"
" $this->t = new DummyTransport();"
" }"
" function getTransport() {"
" return $this->t;"
" }"
"}"
"class DummyTransport {"
" public $buff = '';"
" public $pos = 0;"
" function flush() { }"
" function write($buff) {"
" $this->buff .= $buff;"
" }"
" function read($n) {"
" $r = substr($this->buff, $this->pos, $n);"
" $this->pos += $n;"
" return $r;"
" }"
"}"
"class TestStruct {"
" static $_TSPEC;"
""
" public $aBool = null;"
" public $anInt = null;"
" public $aDouble = null;"
" public $anInt64 = null;"
" public $anByte = null;"
" public $anI16 = null;"
""
" public function __construct($vals=null) {"
" if (!isset(self::$_TSPEC)) {"
" self::$_TSPEC = array("
" -1 => array("
" 'var' => 'aBool',"
" 'type' => TType::BOOL,"
" ),"
" 1 => array("
" 'var' => 'anInt',"
" 'type' => TType::I32,"
" ),"
" 2 => array("
" 'var' => 'aDouble',"
" 'type' => TType::DOUBLE,"
" ),"
" 3 => array("
" 'var' => 'anInt64',"
" 'type' => TType::I64,"
" ),"
" 4 => array("
" 'var' => 'anByte',"
" 'type' => TType::BYTE,"
" ),"
" 5 => array("
" 'var' => 'anI16',"
" 'type' => TType::I16,"
" ),"
" );"
" }"
" }"
"}"
""
"function test() {"
" $p = new DummyProtocol();"
" $v1 = new TestStruct();"
" $v1->aBool = false;"
" $v1->anInt = -1234;"
" $v1->aDouble = -1.2345;"
" $v1->anInt64 = -1;"
" $v1->anByte = -12;"
" $v1->anI16 = -123;"
" thrift_protocol_write_binary($p, 'foomethod', 1, $v1, 20, true);"
" var_dump(thrift_protocol_read_binary($p, 'TestStruct', true));"
"}"
"test();",
"object(TestStruct)#4 (6) {\n"
" [\"aBool\"]=>\n"
" bool(false)\n"
" [\"anInt\"]=>\n"
" int(-1234)\n"
" [\"aDouble\"]=>\n"
" float(-1.2345)\n"
" [\"anInt64\"]=>\n"
" int(-1)\n"
" [\"anByte\"]=>\n"
" int(-12)\n"
" [\"anI16\"]=>\n"
" int(-123)\n"
"}\n");
MVCRO(
"<?php "
"class TType {"
" const STOP = 0;"
" const VOID = 1;"
" const BOOL = 2;"
" const BYTE = 3;"
" const I08 = 3;"
" const DOUBLE = 4;"
" const I16 = 6;"
" const I32 = 8;"
" const I64 = 10;"
" const STRING = 11;"
" const UTF7 = 11;"
" const STRUCT = 12;"
" const MAP = 13;"
" const SET = 14;"
" const LST = 15;"
" const UTF8 = 16;"
" const UTF16 = 17;"
"}"
"class DummyProtocol {"
" public $t;"
" function __construct() {"
" $this->t = new DummyTransport();"
" }"
" function getTransport() {"
" return $this->t;"
" }"
"} "
"class DummyTransport {"
" public $buff = '';"
" public $pos = 0;"
" function flush() { }"
" function write($buff) {"
" $this->buff .= $buff;"
" } "
" function read($n) {"
" $r = substr($this->buff, $this->pos, $n);"
" $this->pos += $n;"
" return $r;"
" } "
"} "
"class TestStruct {"
" static $_TSPEC;"
" "
" public $aBool = null;"
" public $anInt = null;"
" public $aString = null;"
" public $aDouble = null;"
" public $anInt64 = null;"
" public $aList = null;"
" public $aMap = null;"
" public $aSet = null;"
" public $anByte = null;"
" public $anI16 = null;"
" "
" public function __construct($vals=null) {"
" if (!isset(self::$_TSPEC)) {"
" self::$_TSPEC = array("
" -1 => array("
" 'var' => 'aBool',"
" 'type' => TType::BOOL,"
" ),"
" 1 => array("
" 'var' => 'anInt',"
" 'type' => TType::I32,"
" ),"
" 2 => array("
" 'var' => 'aString',"
" 'type' => TType::STRING,"
" ),"
" 3 => array("
" 'var' => 'aDouble',"
" 'type' => TType::DOUBLE,"
" ),"
" 4 => array("
" 'var' => 'anInt64',"
" 'type' => TType::I64,"
" ),"
" 5 => array("
" 'var' => 'aList',"
" 'type' => TType::LST,"
" 'etype' => TType::DOUBLE,"
" 'elem' => array("
" 'type' => TType::DOUBLE,"
" ),"
" ),"
" 6 => array("
" 'var' => 'aMap',"
" 'type' => TType::MAP,"
" 'ktype' => TType::I32,"
" 'vtype' => TType::DOUBLE,"
" 'key' => array("
" 'type' => TType::I32,"
" ),"
" 'val' => array("
" 'type' => TType::DOUBLE,"
" ),"
" ),"
" 7 => array("
" 'var' => 'aSet',"
" 'type' => TType::SET,"
" 'etype' => TType::I32,"
" 'elem' => array("
" 'type' => TType::I32,"
" ),"
" ),"
" 8 => array("
" 'var' => 'anByte',"
" 'type' => TType::BYTE,"
" ),"
" 9 => array("
" 'var' => 'anI16',"
" 'type' => TType::I16,"
" ),"
" );"
" }"
" }"
"}"
""
"function test() {"
" $p = new DummyProtocol();"
" $v1 = new TestStruct();"
" $v1->aBool = true;"
" $v1->anInt = 1234;"
" $v1->aString = 'abcdef';"
" $v1->aDouble = 1.2345;"
" $v1->anInt64 = 8589934592;"
" $v1->aList = array(13.3, 23.4, 3576.2);"
" $v1->aMap = array(10=>1.2, 43=>5.33);"
" $v1->aSet = array(10=>true, 11=>true);"
" $v1->anByte = 123;"
" $v1->anI16 = 1234;"
" thrift_protocol_write_compact($p, 'foomethod', 1, $v1, 20);"
" var_dump(md5($p->getTransport()->buff));"
"}"
"test();",
"string(32) \"cd0654ca200fe910204988f44f996a11\"\n");
MVCRO(
"<?php "
"class TType {"
" const STOP = 0;"
" const VOID = 1;"
" const BOOL = 2;"
" const BYTE = 3;"
" const I08 = 3;"
" const DOUBLE = 4;"
" const I16 = 6;"
" const I32 = 8;"
" const I64 = 10;"
" const STRING = 11;"
" const UTF7 = 11;"
" const STRUCT = 12;"
" const MAP = 13;"
" const SET = 14;"
" const LST = 15;"
" const UTF8 = 16;"
" const UTF16 = 17;"
"}"
"class DummyProtocol {"
" public $t;"
" function __construct() {"
" $this->t = new DummyTransport();"
" }"
" function getTransport() {"
" return $this->t;"
" }"
"} "
"class DummyTransport {"
" public $buff = '';"
" public $pos = 0;"
" function flush() { }"
" function write($buff) {"
" $this->buff .= $buff;"
" } "
" function read($n) {"
" $r = substr($this->buff, $this->pos, $n);"
" $this->pos += $n;"
" return $r;"
" } "
" function putBack($data) {"
" $this->buff = ($data . $this->buff);"
" } "
"} "
"class TestStruct {"
" static $_TSPEC;"
" "
" public $aBool = null;"
" public $anInt = null;"
" public $aString = null;"
" public $aDouble = null;"
" public $anInt64 = null;"
" public $aList = null;"
" public $aMap = null;"
" public $aSet = null;"
" public $anByte = null;"
" public $anI16 = null;"
" "
" public function __construct($vals=null) {"
" if (!isset(self::$_TSPEC)) {"
" self::$_TSPEC = array("
" -1 => array("
" 'var' => 'aBool',"
" 'type' => TType::BOOL,"
" ),"
" 1 => array("
" 'var' => 'anInt',"
" 'type' => TType::I32,"
" ),"
" 2 => array("
" 'var' => 'aString',"
" 'type' => TType::STRING,"
" ),"
" 3 => array("
" 'var' => 'aDouble',"
" 'type' => TType::DOUBLE,"
" ),"
" 4 => array("
" 'var' => 'anInt64',"
" 'type' => TType::I64,"
" ),"
" 5 => array("
" 'var' => 'aList',"
" 'type' => TType::LST,"
" 'etype' => TType::DOUBLE,"
" 'elem' => array("
" 'type' => TType::DOUBLE,"
" ),"
" ),"
" 6 => array("
" 'var' => 'aMap',"
" 'type' => TType::MAP,"
" 'ktype' => TType::I32,"
" 'vtype' => TType::DOUBLE,"
" 'key' => array("
" 'type' => TType::I32,"
" ),"
" 'val' => array("
" 'type' => TType::DOUBLE,"
" ),"
" ),"
" 7 => array("
" 'var' => 'aSet',"
" 'type' => TType::SET,"
" 'etype' => TType::I32,"
" 'elem' => array("
" 'type' => TType::I32,"
" ),"
" ),"
" 8 => array("
" 'var' => 'anByte',"
" 'type' => TType::BYTE,"
" ),"
" 9 => array("
" 'var' => 'anI16',"
" 'type' => TType::I16,"
" ),"
" );"
" }"
" }"
"}"
""
"function test() {"
" $p = new DummyProtocol();"
" $v1 = new TestStruct();"
" $v1->aBool = true;"
" $v1->anInt = 1234;"
" $v1->aString = 'abcdef';"
" $v1->aDouble = 1.2345;"
" $v1->anInt64 = 8589934592;"
" $v1->aList = array(13.3, 23.4, 3576.2);"
" $v1->aMap = array(10=>1.2, 43=>5.33);"
" $v1->aSet = array(10=>true, 11=>true);"
" $v1->anByte = 123;"
" $v1->anI16 = 1234;"
" thrift_protocol_write_compact($p, 'foomethod', 1, $v1, 20);"
// HACK: rewrite the version and call type from "version X, call" to
// "version 2, response" to appease deserializer
" $p->getTransport()->buff[1] = pack('C', 0x42);"
" var_dump(thrift_protocol_read_compact($p, 'TestStruct'));"
"}"
"test();",
"object(TestStruct)#4 (10) {\n"
" [\"aBool\"]=>\n"
" bool(true)\n"
" [\"anInt\"]=>\n"
" int(1234)\n"
" [\"aString\"]=>\n"
" string(6) \"abcdef\"\n"
" [\"aDouble\"]=>\n"
" float(1.2345)\n"
" [\"anInt64\"]=>\n"
" int(8589934592)\n"
" [\"aList\"]=>\n"
" array(3) {\n"
" [0]=>\n"
" float(13.3)\n"
" [1]=>\n"
" float(23.4)\n"
" [2]=>\n"
" float(3576.2)\n"
" }\n"
" [\"aMap\"]=>\n"
" array(2) {\n"
" [10]=>\n"
" float(1.2)\n"
" [43]=>\n"
" float(5.33)\n"
" }\n"
" [\"aSet\"]=>\n"
" array(2) {\n"
" [10]=>\n"
" bool(true)\n"
" [11]=>\n"
" bool(true)\n"
" }\n"
" [\"anByte\"]=>\n"
" int(123)\n"
" [\"anI16\"]=>\n"
" int(1234)\n"
"}\n");
return true;
}
bool TestCodeRun::TestExit() {
MVCR("<?php "
"function foo() { return false; }"
"foo() or die(\"foobar\");");
MVCR("<?php "
"function foo() { return false; }"
"foo() or exit(\"foobar\");");
MVCR("<?php "
"function callback($data) {"
" return \"callback: $data\";"
"}"
"ob_start();"
"echo \"from first level\\n\";"
"ob_start();"
"ob_start(\"callback\");"
"echo \"foobar!\\n\";"
"exit;");
MVCRONW("<?php "
"declare(ticks=1);"
"function foo() {"
" echo 'a';"
" exit(1);"
"}"
"function bar() {} "
"pcntl_signal(SIGUSR1, 'foo');"
"$pid = posix_getpid();"
"posix_kill($pid, SIGUSR1);"
"bar(); /* check for received signal upon function entry/exit */ "
"for ($i = 0; $i < 2; $i++) {"
" echo 'a';"
"}"
,
"a");
MVCR("<?php "
"$command = \"exit 2\";"
"system($command, $return);"
"print \"$return\\n\";");
MVCR("<?php "
"$command = \"exit 2\";"
"passthru($command, $return);"
"print \"$return\\n\";");
return true;
}
bool TestCodeRun::TestCreateFunction() {
MVCR("<?php var_dump(array_filter(array(1, 1003, 34, 5006), "
"create_function('$x', 'return $x > 1000;')));");
MVCR("<?php var_dump(array_filter(array(1, 1003, 34, 5006), "
"create_function('$x', 'return '.'$x > 1000;')));");
return true;
}
bool TestCodeRun::TestConstructorDestructor() {
MVCR("<?php "
"class parent_c {"
" public function __construct() {"
" echo \"parent__construct\";"
" }"
" public function __destruct() {"
" echo \"parent__destruct\";"
" }"
"}"
"class child_c extends parent_c {"
" public function __construct() {"
" echo \"child__construct\";"
" }"
" public function __destruct() {"
" echo \"child__destruct\";"
" }"
"}"
"$v = new child_c;unset($v);");
MVCR("<?php "
"class parent_c {"
" public function __construct() {"
" echo \"parent__construct\";"
" }"
" public function __destruct() {"
" echo \"parent__destruct\";"
" }"
"}"
"class child_c extends parent_c {"
" public function __construct() {"
" echo \"child__construct\";"
" parent::__construct();"
" }"
" public function __destruct() {"
" echo \"child__destruct\";"
" parent::__destruct();"
" }"
"}"
"$v = new child_c;unset($v);");
MVCR("<?php ;"
"class B1 {}"
"class C1 { function __construct() {} }"
"class D1 { function __destruct() { var_dump(__METHOD__); } }"
"class D2 extends C1 { function __destruct()"
"{ var_dump(__METHOD__); } }"
"class D3 extends D2 {}"
"class D4 extends B1 { function __destruct()"
"{ var_dump(__METHOD__); } }"
"class D5 extends D4 {}"
"class D6 extends D1 { function __construct($a) { if ($a) f(); } }"
"function f() { throw new Exception('throw'); }"
"function foo($a,$b) {"
" try {"
" $x = new D6($b?f():$a);"
" } catch (Exception $e) {"
" var_dump('caught');"
" }"
"}"
"function bar($x, $a, $b) {"
" try {"
" $x = new $x($b?f():$a);"
" } catch (Exception $e) {"
" var_dump('caught');"
" }"
"}"
"function n($x) { return new $x; }"
"function baz($d) {"
" $x = new D1;"
" $x = new D2;"
" $x = new D3;"
" $x = new D4;"
" $x = new D5;"
" $x = new D6;"
" $x = n($d.'1');"
" $x = n($d.'2');"
" $x = n($d.'3');"
" $x = n($d.'4');"
" $x = n($d.'5');"
" $x = n($d.'6');"
" $x = n('B1');"
"}"
"foo(false,false);"
"foo(false,true);"
"foo(true,true);"
"foo(true,false);"
"bar('D6',false,false);"
"bar('D6',false,true);"
"bar('D6',true,false);"
"bar('D6',true,true);"
"baz('D');");
return true;
}
bool TestCodeRun::TestConcat() {
MVCR("<?php\n"
"$str = '';\n"
"$arr1 = array('a', 'b');\n"
"$arr2 = $arr1;\n"
"foreach ($arr1 as $v1) {\n"
" $str .= $v1;\n"
" switch ($v1) {\n"
" default:\n"
" foreach ($arr2 as $v2) {\n"
" $str .= $v2;\n"
" }\n"
" }\n"
"}\n"
"var_dump($str);\n"
);
MVCR("<?php "
"function foo($where_clause)"
"{"
" $sql ="
" 'SELECT p.property_name, p.property_value, p.property_id, '."
" 'p.property_data_type, p.property_type, '."
" 't.tier_id, t.tier_parent_id, t.tier_version, t.tier_type, '."
" 't.tier_state, t.tier_name '."
" 'FROM tier t LEFT OUTER JOIN property p ON '."
" 'p.parent_id = t.tier_id AND '."
" 'p.property_type = \"tier\" '."
" $where_clause;"
" echo $sql . \"\\n\";"
"}"
"foo(\"where 1 = 1\");");
MVCR("<?php "
"echo \"a\" . \"b\" . \"c\" . \"d\" . \"e\";"
"echo 'a' . 'b' . 'c' . 'd' . 'e';"
"echo 'a' . \"b\" . \"c\" . \"d\" . 'e';"
"echo '\"a' . \"\\\"b\" . \"\\'c\" . \"\\'d\" . '\\\"e';"
"echo 1 . 2 . 3 . 4 . 5;"
"echo 1 . '2' . '3' . 4 . 5;"
"echo 1 . \"2\" . \"3\" . 4 . 5;");
MVCR("<?php "
"$v = \"c\";"
"echo \"a\" . \"b\" . $v . \"d\" . \"e\";"
"echo \"a\" . \"b\" . $v . \"d\" . \"e\" . $v . \"f\" . \"g\";");
MVCR("<?php "
"echo '\\\\' . \"\\n\";"
"echo '\\'' . \"\\n\";"
"echo '\\\\' . '\\'' . \"\\n\";"
"echo '\\\\' . \"'\" . \"\\n\";"
"echo \"\\\\\" . \"'\" . \"\\n\";"
"echo \"\\101\" . \"\\n\";"
"echo \"\\\\\" . \"101\" . \"\\n\";"
"echo \"\\1\" . \"101\" . \"\\n\";"
"echo \"\\01\" . \"01\" . \"\\n\";"
"echo \"\\01\" . \"g\" . \"\\n\";"
"echo \"\\1\" . \"g\" . \"\\n\";"
"echo \"\\011\" . \"01\" . \"\\n\";"
"echo \"\\0111\" . \"01\" . \"\\n\";"
"echo \"\\x\" . \"1\" . \"\\n\";"
"echo \"\\x1\" . \"1\" . \"\\n\";"
"echo \"\\x11\" . \"1\" . \"\\n\";"
"echo \"\\x111\" . \"1\" . \"\\n\";"
"echo \"\\x1111\" . \"1\" . \"\\n\";"
"echo \"\\x11111\" . \"1\" . \"\\n\";"
"echo \"\\777777\" . \"7\" . \"\\n\";"
"echo \"\\0777777\" . \"7\" . \"\\n\";"
"echo \"\\00777777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\\"7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\\\7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\a7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\b7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\f7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\n7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\r7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\t7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\v7777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\07777\" . \"7\" . \"\\n\";"
"echo \"\\0077\\'7777\" . \"7\" . \"\\n\";");
MVCR("<?php "
"echo '\\\\';"
"echo '\\'';"
"echo '\\\\';"
"echo '\\\\';"
"echo \"\\\\\";"
"echo \"\\101\";"
"echo \"\\\\\";"
"echo \"\\1\";"
"echo \"\\01\";"
"echo \"\\01\";"
"echo \"\\1\";"
"echo \"\\011\";"
"echo \"\\0111\";"
"echo \"\\x\";"
"echo \"\\x1\";"
"echo \"\\x11\";"
"echo \"\\x111\";"
"echo \"\\x1111\";"
"echo \"\\x11111\";"
"echo \"\\777777\";"
"echo \"\\0777777\";"
"echo \"\\00777777\";"
"echo \"\\0077\\\"7777\";"
"echo \"\\0077\\\\7777\";"
"echo \"\\0077\\a7777\";"
"echo \"\\0077\\b7777\";"
"echo \"\\0077\\f7777\";"
"echo \"\\0077\\n7777\";"
"echo \"\\0077\\r7777\";"
"echo \"\\0077\\t7777\";"
"echo \"\\0077\\v7777\";"
"echo \"\\0077\\07777\";"
"echo \"\\0077\\'7777\";");
MVCR("<?php "
"echo <<<EOT\n"
"\\t\n"
"\\r\n"
"\\a\n"
"\\b\n"
"\\f\n"
"\\v\n"
"\\\"\n"
"\\\\\n"
"'\\\\' . \\`\\n\\`;\n"
"'\\'' . \\`\\n\\`;\n"
"'\\\\' . '\\'' . \\`\\n\\`;\n"
"'\\\\' . \\`'\\` . \\`\\n\\`;\n"
"\\`\\\\\\` . \\`'\\` . \\`\\n\\`;\n"
"\\`\\101\\` . \\`\\n\\`;\n"
"\\`\\\\\\` . \\`101\\` . \\`\\n\\`;\n"
"\\`\\1\\` . \\`101\\` . \\`\\n\\`;\n"
"\\`\\01\\` . \\`01\\` . \\`\\n\\`;\n"
"\\`\\01\\` . \\`g\\` . \\`\\n\\`;\n"
"\\`\\1\\` . \\`g\\` . \\`\\n\\`;\n"
"\\`\\011\\` . \\`01\\` . \\`\\n\\`;\n"
"\\`\\0111\\` . \\`01\\` . \\`\\n\\`;\n"
"\\`\\x\\` . \\`1\\` . \\`\\n\\`;\n"
"\\`\\x1\\` . \\`1\\` . \\`\\n\\`;\n"
"\\`\\x11\\` . \\`1\\` . \\`\\n\\`;\n"
"\\`\\x111\\` . \\`1\\` . \\`\\n\\`;\n"
"\\`\\x1111\\` . \\`1\\` . \\`\\n\\`;\n"
"\\`\\x11111\\` . \\`1\\` . \\`\\n\\`;\n"
"\\`\\777777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0777777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\00777777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\\\`7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\\\7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\a7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\b7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\f7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\n7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\r7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\t7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\v7777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\07777\\` . \\`7\\` . \\`\\n\\`;\n"
"\\`\\0077\\'7777\\` . \\`7\\` . \\`\\n\\`;\n"
"EOT;\n");
MVCR("<?php "
"$v = 1;"
"echo $v . b'a' . b\"b\" . `ls \\055\\144 \\x2ftmp`;"
"echo b'a' . b\"b\" . `ls \\055\\144 \\x2ftmp` . $v;");
MVCR("<?php "
"function foo() {"
" $u = \"abc\";"
" $v = \"\\0\";"
" $w = \"def\\n\";"
" $x = $u . $v . $w;"
" echo $x;"
" echo \"abc\" . \"\\0\" . \"def\\n\";"
"}"
"foo();"
"$u = \"abc\";"
"$v = \"\\0\";"
"$w = \"def\\n\";"
"$x = $u . $v . $w;"
"echo $x;"
"echo \"abc\" . \"\\0\" . \"def\\n\";"
"echo \"ab\\0c\\n\";");
MVCR("<?php "
"function foo() { return \"hello\" . \"\\0\" . \"world\n\"; }"
"function bar() {"
" $s = foo();"
" echo $s;"
"}"
"bar();");
MVCR("<?php "
"define('FOO'.'BAR', 1);"
"echo FOOBAR;");
MVCR("<?php "
"$a = \"1\";"
"$a .= \"2\";"
"$a .= \"3\";"
"$a .= \"4\";"
"var_dump($a);"
"$a .= \"1\";"
"$a .= \"2\";"
"$a .= \"3\";"
"$a .= \"4\";"
"var_dump($a);");
MVCR("<?php "
"$a = array(1, array(1, array(1)));"
"$a[1][1][1] = 3;"
"var_dump($a);"
"$a[1][1][1] = \"1\";"
"$a[1][1][1] .= \"2\";"
"$a[1][1][1] .= \"3\";"
"$a[1][1][1] .= \"4\";"
"$a[1][1][1] .= \"5\";"
"var_dump($a);"
"$payload['pane_html'] = null;"
"$payload['pane_html'] = "
"'<div id=\"beacon_accepted_pane\" class=\"beacon_status_pane\" "
"style=\"display: none\">';"
"$payload['pane_html'] .= '<div class=\"beacon_status_message\">';");
MVCR("<?php "
"$a1 = a;"
"$a2 = b;"
"$a3 = c;"
"$a4 = d;"
"$a5 = e;"
"$a6 = f;"
"$a7 = g;"
"$a8 = h;"
"$a9 = i;"
"$a10 = j;"
"$a11 = k;"
"$a12 = l;"
"$a13 = m;"
"echo $a1.$a2.$a3.$a4.$a5.$a6;"
"echo $a1.$a2.$a3.$a4.$a5.$a6.$a7;"
"echo $a1.$a2.$a3.$a4.$a5.$a6.$a7.$a8;"
"echo $a1.$a2.$a3.$a4.$a5.$a6.$a7.$a8.$a9;"
"echo $a1.$a2.$a3.$a4.$a5.$a6.$a7.$a8.$a9.$a10;"
"echo $a1.$a2.$a3.$a4.$a5.$a6.$a7.$a8.$a9.$a10.$a11;"
"echo $a1.$a2.$a3.$a4.$a5.$a6.$a7.$a8.$a9.$a10.$a11.$a12;"
"echo $a1.$a2.$a3.$a4.$a5.$a6.$a7.$a8.$a9.$a10.$a11.$a12.$a13;");
MVCR("<?php "
"function n_() {"
" return \"\n\" ."
" str_repeat($GLOBALS['n_indent_tab'], $GLOBALS['n_indent_level']);"
"}"
"function n_indent() {"
" $GLOBALS['n_indent_level']++;"
" return n_();"
"}"
"function n_unindent() {"
" $GLOBALS['n_indent_level']--;"
" return n_();"
"}"
"function render($arg1, $arg2) {"
" return"
" '<div id=\"captcha\" class=\"'.$arg1.'\">'."
" n_indent()."
" $arg2 ."
" n_unindent()."
" '</div>';"
"}"
"$GLOBALS['n_indent_level'] = 0;"
"var_dump(render(\"foo\", \"bar\"));");
MVCR("<?php "
"$s = \" \";"
"$a = \"hello\";"
"$a .= $s;"
"$a .= \"world\";"
"var_dump($a);"
"$a = \"a\";"
"$a .= \"b\";"
"$a .= $a;"
"var_dump($a);"
"$a = 3;"
"echo 0 + \"1$a\";");
MVCR("<?php "
"function test($a)"
"{"
" if ($a > 0) {"
" $sql = 'foo';"
" } else {"
" $sql = 'bar';"
" }"
" $sql .= ' baz';"
" return $sql;"
"}"
"echo test(1),test(-1),\"\\n\";");
MVCR("<?php "
"function foo() {"
" echo \" FOO \";"
" return \" foo \";"
"}"
"function bar() {"
" echo \" hello \" . foo() . \"\n\";"
" echo \" hello \" , foo() , \"\n\";"
"}"
"bar();");
MVCR("<?php "
"function foo() {"
" print \" FOO \";"
" return \" foo \";"
"}"
"class A implements ArrayAccess {"
" private $data = array();"
" public function offsetUnset($index) {}"
""
" public function offsetGet($index) {"
" print \" GET \";"
" return \" get \";"
" }"
" public function offsetSet($index, $value) {"
" $data[$index] = $value;"
" }"
" public function offsetExists($index) { }"
"}"
"class C {"
" public function __get( $what ) {"
" echo \"get C\\n\";"
" return $this->_p[ $what ];"
" }"
" public function __set( $what, $value ) {"
" echo \"set C\\n\";"
" $this->_p[ $what ] = $value;"
" }"
" private $_p = array();"
"}"
"function bar() {"
" print \" hello \" . foo() . \"\\n\";"
" $a = new A;"
" $a[0] = 0;"
" $a[1] = 1;"
" echo \" hello $a[0]\";"
" echo \" hello $a[1]\\n\";"
" print \" hello $a[0]\";"
" print \" hello $a[1]\\n\";"
" $b = new C;"
" $b->a = 'aaaa';"
" $b->b = 'bbbb';"
" echo \" hello $b->a\";"
" echo \" hello $b->b\\n\";"
" print \" hello $b->a\";"
" print \" hello $b->b\\n\";"
" echo \" hello $b->a $b->b $b->a $b->b\";"
"}"
"bar();");
MVCR("<?php "
"function test($a, $b) {"
" return $a . \"\\0\" . $b . \"\\0\" . $a . $b . $a . $b;"
"}"
"var_dump(json_encode(test('x', 'y')));");
MVCR("<?php "
"$a = 1;"
"var_dump($a . '2' . '3');");
MVCR("<?php "
"$a= 'a';"
"$b = 'b';"
"$c = 0;"
"var_dump($a . $b == $c);");
MVCR("<?php "
"class C {"
" public function __toString() {"
" return 'bar';"
" }"
"}"
"function f($x) {"
" var_dump($x . '');"
"}"
"f(123);"
"f(new C);");
return true;
}
bool TestCodeRun::TestConstant() {
MVCR("<?php define('A', 'B'); define('A_'.A, 'B'); var_dump(A, A_B);");
MVCR("<?php "
"define('AAA', true);"
"define('BBB', false);"
"define('CCC', null);"
"if (AAA){"
" echo \"AAA\";"
"} else {"
" echo \"!AAA\";"
"}"
"if (BBB) {"
" echo \"BBB\";"
"} else {"
" echo \"!BBB\";"
"}"
"if (CCC) {"
" echo \"CCC\";"
"} else {"
" echo \"!CCC\";"
"}"
"$a = AAA ? \"AAA\" : \"!AAA\";"
"$b = BBB ? \"BBB\" : \"!BBB\";"
"$c = CCC ? \"CCC\" : \"!CCC\";"
"echo \"$a$b$c\\n\";");
MVCR("<?php "
"echo strlen(\"he\\0llo\");"
"echo php_uname();"
"echo md5('1f3870be274f6c49b3e31a0c6728957f');"
"echo sha1('1f3870be274f6c49b3e31a0c6728957f');"
"echo crc32('1f3870be274f6c49b3e31a0c6728957f');"
"echo pi();"
"echo getrandmax();"
"echo mt_getrandmax();"
"echo ord('abc');"
"echo chr(27);"
"echo strtoupper(\"Mary Had A \\0 Lamb\");"
"echo strtolower(\"Mary Had A \\0 Lamb\");"
"echo strcmp(\"Mary Had A \\0Lamb\", \"Mary Had A Lamb\") < 0;"
"echo strncmp(\"Mary Had A \\0 Lamb\", \"Mary Had A Lamb\", 5) == 0;"
"echo strcasecmp(\"Mary Had A \\0 Lamb\", \"Mary Had A Lamb\") < 0;"
"echo strncasecmp(\"Mary Had A \\0 Lamb\", \"Mary Had A Lamb\", 5) == 0;"
"echo addslashes(\"Is your name \\0O'reilly?\");"
"echo htmlspecialchars(\"<a ref='test'>Test</a>\", ENT_QUOTES);"
"echo htmlspecialchars_decode(\"\\0abc\");"
"echo htmlspecialchars_decode(\"abc\\0def\");"
"echo htmlentities(\"<a ref='test'>Test</a>\", ENT_QUOTES);"
"echo dirname(\"<a ref='test'>Test</a>\");"
"echo basename(\"<a ref='test'>Test</a>\");"
"echo version_compare(\"5.1.2\", \"5.1.3\");"
"echo dechex(10);"
"echo hexdec(\"See\");"
"echo decbin(12);"
"echo decbin('000110011');"
"echo decoct(264);"
"echo octdec('77');"
"echo octdec(decoct(45));"
"echo str_repeat(\"-=\", 10);"
"echo intval(42);"
"echo intval(4.2);"
"echo intval('42');"
"echo intval('+42');"
"echo intval('-42');"
"echo intval(042);"
"echo intval('042');"
"echo intval(1e10);"
"echo intval('1e10');"
"echo intval(0x1A);"
"echo intval(42000000);"
"echo intval(42, 8);"
"echo intval('42', 8);"
"echo substr(\"abcdef\", -1);"
"echo substr(\"abcdef\", -2);"
"echo substr(\"abcdef\", -3, 1);"
"echo substr(\"abcdef\", 0, -1);"
"echo substr(\"abcdef\", 2, -1);"
"echo substr(\"abcdef\", 4, -4);"
"echo substr(\"abcdef\", -3, -1);"
"echo substr(\"abcdef\", 1);"
"echo substr(\"abcdef\", 1, 3);"
"echo substr(\"abcdef\", 0, 4);"
"echo substr(\"abcdef\", 0, 8);"
"echo substr(\"abcdef\", -1, 1);"
"echo trim(\"\\t\\t\\0These are a few words :) ... \");"
"echo trim(\"\\t\\t\\0These are a few words :) ... \", \" \\t.\");"
"echo trim(\"\\x09Example string\\x0A\", \"\\x00..\\x1F\");"
"echo ltrim(\"\\t\\t\\0These are a few words :) ... \");"
"echo ltrim(\"\\t\\t\\0These are a few words :) ... \", \" \\t.\");"
"echo ltrim(\"\\x09Example string\\x0A\", \"\\x00..\\x1F\");"
"echo rtrim(\"\\t\\t\\0These are a few words :) ... \");"
"echo rtrim(\"\\t\\t\\0These are a few words :) ... \", \" \\t.\");"
"echo rtrim(\"\\x09Example string\\x0A\", \"\\x00..\\x1F\");"
"echo chop(\"\\t\\t\\0These are a few words :) ... \");"
"echo chop(\"\\t\\t\\0These are a few words :) ... \", \" \\t.\");"
"echo chop(\"\\x09Example string\\x0A\", \"\\x00..\\x1F\");"
"echo acos(0.5);"
"echo acosh(0.5);"
"echo asin(0.5);"
"echo asinh(0.5);"
"echo atan(0.5);"
"echo atan2(0.5, 0.5);"
"echo atanh(0.5);"
"echo cos(0.5);"
"echo cosh(0.5);"
"echo sin(0.5);"
"echo sinh(0.5);"
"echo tan(0.5);"
"echo tanh(0.5);"
"echo exp(5.7);"
"echo exp(12);"
"echo log10(12);"
"echo log(12);"
"echo sqrt(2);"
"echo ceil(7.9);"
"echo floor(7.9);"
"echo fmod(5.7, 1.3);"
"echo ip2long(\"127.0.0.1\");"
/*
5.2 accepts these, 5.3 does not.
php.net says it should
"echo ip2long(\"10.0.0\");"
"echo ip2long(\"10.0.256\");"
*/
"echo long2ip(pow(2,32) + 1024);"
"echo rad2deg(M_PI_4);"
"echo deg2rad(45);");
MVCR("<?php "
"var_dump(067);"
"var_dump(077);"
"var_dump(078);"
"var_dump(0x78);"
"var_dump(0x78f);"
"var_dump(0xef);"
"var_dump(-067);"
"var_dump(-077);"
"var_dump(-078);"
"var_dump(-0x78);"
"var_dump(-0x78f);"
"var_dump(-0xef);");
MVCR("<?php "
"define('FOO', \"\\n\");"
"define('BAR', \"\\r\");"
"var_dump(PHP_EOL);"
"var_dump(FOO);"
"var_dump(BAR);");
MVCR("<?php "
"var_dump(INF);"
"var_dump(NAN);");
MVCR("<?php "
"define('A_B', 555);"
"define('A_'. 'B', 'B');");
MVCR("<?php "
"var_dump(define('AF_UNIX', 5));"
"var_dump(AF_UNIX);");
// Arrays aren't allowed as constants
MVCR("<?php "
"var_dump(define('KONST', array('a', 'bc')));"
"var_dump(KONST);"
"var_dump(define('FLUB', 1230));"
"var_dump(define('FLUB', array(1,23)));"
"var_dump(FLUB);"
// defeat optimizations
"var_dump(define('BLAH', array_map('strlen', array('a', 'bc'))));"
"var_dump(BLAH);"
"define('FOO', array(1,2,3));");
MVCR("<?php "
"var_dump(define('foo', false));"
"var_dump(define('foo', true));");
return true;
}
bool TestCodeRun::TestClassConstant() {
MVCR("<?php "
"class parent_c {"
" const ZERO = 0;"
" const TWENTY = 20;"
" const FORTY = 40;"
"}"
"class child_c extends parent_c {"
" const FIFTY = 50;"
"}"
""
"function foo"
"($a = parent_c::ZERO, $b = child_c::FIFTY, $c = child_c::FORTY) {"
" echo $a;"
" echo $b;"
" echo $c;"
"}"
"foo();"
"print parent_c::ZERO;");
MVCR("<?php "
"class FooConstants {"
" const ZERO = 0;"
" const TWENTY_FOUR3 = FooConstants::TWENTY_FOUR2;"
" const TWENTY_FOUR2 = FooConstants::TWENTY_FOUR;"
" const TWENTY_FOUR = 24;"
" const FORTY_EIGHT = 48;"
"}"
"class BarConstants {"
" const ZERO = FooConstants::ZERO;"
" const TWENTY_FOUR = FooConstants::TWENTY_FOUR;"
" const FORTY_EIGHT = FooConstants::FORTY_EIGHT;"
"}"
"class GooConstants {"
" const ZERO = BarConstants::ZERO;"
" const TWENTY_FOUR = BarConstants::TWENTY_FOUR;"
" const FORTY_EIGHT = BarConstants::FORTY_EIGHT;"
"}"
"function a_better_pickle() {"
" return FooConstants::ZERO;"
"}"
"a_better_pickle();"
"print GooConstants::ZERO;"
"print FooConstants::TWENTY_FOUR2;"
"print FooConstants::TWENTY_FOUR3;");
MVCR("<?php "
"define('FOO', 3);"
"define('BAR', true);"
"define('GOO', FOO + 4);"
"define('HOO', FOO);"
"var_dump(FOO);"
"var_dump(BAR);"
"var_dump(GOO);"
"var_dump(HOO);"
"class A {"
" const C1 = 1;"
" const C2 = '2';"
" const C3 = FOO;"
" const C4 = BAR;"
" const C5 = GOO;"
" const C6 = HOO;"
"}"
"var_dump(a::C1);"
"var_dump(a::C2);"
"var_dump(a::C3);"
"var_dump(a::C4);"
"var_dump(a::C5);"
"var_dump(a::C6);");
MVCR("<?php "
"define('FOO', 3);"
"function foo($a = FOO) {"
" echo $a;"
"}"
"foo();");
MVCR("<?php "
"class c {"
" function foo($x = self::BLAH) {}"
"}");
MVCR("<?php "
"interface X {"
" const A=1;"
"}"
"class Y {"
" const B = 2;"
"}"
"class Z extends Y implements X {"
" function x() {"
" print self::A;"
" print self::B;"
" print Z::A;"
" print Z::B;"
" print X::A;"
" print Y::B;"
" }"
"}"
"$z = new Z;"
"$z->x();");
MVCR("<?php "
"class Dummy {}"
""
"class foo {"
" public static $v = array(Dummy::c => 'foo');"
"}"
""
"interface A {"
" const CONSTANT = 'CONSTANT';"
"}"
""
"class B implements A { }"
""
"class C {"
" static $A_CONSTANT = A::CONSTANT;"
" static $B_CONSTANT = B::CONSTANT;"
"}"
""
"var_dump(A::CONSTANT);"
"var_dump(B::CONSTANT);"
"var_dump(C::$A_CONSTANT);"
"var_dump(C::$B_CONSTANT);");
MVCR("<?php "
"abstract class TB {"
" const PARAM_A = 'aaa';"
" const PARAM_B = 'bbb';"
" const PARAM_C = 'ccc';"
" const PARAM_D = 'ddd';"
"}"
"abstract class ATB extends TB {"
"}"
"class ABCD extends ATB {"
" static public function foo() {"
" return array("
" 'a_ids' => array("
" ATB::PARAM_A => true,"
" ATB::PARAM_C => array("
" array('tcks', 'none'),"
" array('tcks', 'ids'),"
" ),"
" ATB::PARAM_B =>"
" 'aaaa',"
" ),"
" 'user_id' => array("
" ATB::PARAM_A => true,"
" ATB::PARAM_C => array("
" array('tcks', 'none'),"
" array('tcks', 'id'),"
" ),"
" ATB::PARAM_B =>"
" 'bbbb',"
" ),"
" );"
" }"
"}"
"var_dump(ABCD::foo());");
MVCR("<?php "
"function __autoload($x) { var_dump('AUTOLOAD:'.$x); }"
"class X {"
" public $foo = Y::FOO;"
" function foo() {"
" var_dump(__METHOD__, $this);"
" }"
"}"
"X::foo();");
MVCRO("<?php\n"
"class A { const A = 'a'; }\n"
"class B extends A { const B = 'b'; }\n"
"var_dump(get_class_constants('B'));\n"
,
"array(1) {\n"
" [\"B\"]=>\n"
" string(1) \"b\"\n"
"}\n");
MVCRO("<?php\n"
"interface I { const X = 'x'; }\n"
"class A implements I { }\n"
"var_dump(A::X);\n"
"var_dump(get_class_constants('A'));\n"
,
"string(1) \"x\"\n"
"array(0) {\n"
"}\n");
MVCRO("<?php\n"
"class B { const X = 'old'; }\n"
"class A extends B { const X = 'new'; }\n"
"var_dump(A::X);\n"
"var_dump(get_class_constants('A'));\n"
,
"string(3) \"new\"\n"
"array(1) {\n"
" [\"X\"]=>\n"
" string(3) \"new\"\n"
"}\n");
MVCRO("<?php\n"
"var_dump(get_class_constants('C'));\n"
,
"array(0) {\n"
"}\n");
MVCRO("<?php\n"
"class B { const X='xxx'; }\n"
"class C { const Y=B::X; }\n"
"var_dump(get_class_constants('C'));\n"
,
"array(1) {\n"
" [\"Y\"]=>\n"
" string(3) \"xxx\"\n"
"}\n");
MVCR("<?php "
"if (isset($g)) {"
" interface I { const FOO = 1; }"
" class C { const FOO = 3; }"
"} else {"
" interface I { const FOO = 2; }"
" class C { const FOO = 4; }"
"}"
"class X {"
" function foo($x = C::FOO, $y = I::FOO) {}"
"}"
"function test() {"
" $x = new ReflectionMethod('X', 'foo');"
" foreach ($x->getParameters() as $p) {"
" var_dump($p->getDefaultValue());"
" }"
"}"
"function fiz($c) {"
" var_dump($c::FOO);"
"}"
"fiz('I');"
"fiz('C');"
"test();");
MVCR("<?php "
"interface ITest {"
" const ITestConst = 42;"
"}"
"class Test implements ITest {"
" public function foo($y = 'Test', $x = self::ITestConst) {"
" var_dump($y::ITestConst);"
" var_dump(static::ITestConst);"
" var_dump(self::ITestConst);"
" var_dump($x);"
" }"
"}"
"$t = new Test();"
"$t->foo();"
"$rc = new ReflectionClass('Test');"
"$method = $rc->getMethod('foo');"
"foreach ($method->getParameters() as $param) {"
" var_dump($param->getDefaultValue());"
"}");
return true;
}
bool TestCodeRun::TestConstantFunction() {
MVCR("<?php "
"class JavaScriptPacker {"
" public function foo() {"
" $encode10 = $this->_getJSFunction('_encode10');"
" var_dump($encode10);"
" $encode36 = $this->_getJSFunction('_encode36');"
" var_dump($encode36);"
" }"
" private function _getJSFunction($aName) {"
" if (defined('self::JSFUNCTION'.$aName))"
" return constant('self::JSFUNCTION'.$aName);"
" else"
" return '';"
" }"
" const JSFUNCTION_encode10 ="
" 'function($charCode) {"
" return $charCode;"
"}';"
""
"}"
"$obj = new JavaScriptPacker;"
"$obj->foo(); ");
MVCR("<?php "
"var_dump(constant('M_PI'));"
"$a = 'M_PI';"
"var_dump(constant($a));"
"define('FOO', M_PI);"
"var_dump(constant('FOO'));"
"define('BAR', php_uname());"
"var_dump(constant('BAR'));"
"define(/*|Dynamic|*/'GOO', 1);"
"var_dump(constant('GOO'));"
"if (false) {"
" define('C', 1);"
"} else {"
" define('C', 2);"
"}"
"var_dump(constant('C'));");
return true;
}
bool TestCodeRun::TestDefined() {
MVCR("<?php "
"if (defined('FOO')) echo 'defined'; else echo 'undefined';");
MVCR("<?php "
"define('FOO', 1);"
"if (defined('FOO')) echo 'defined'; else echo 'undefined';");
MVCR("<?php "
"echo FOO;"
"if (defined('FOO')) echo 'defined'; else echo 'undefined';");
MVCR("<?php "
"define('THIRTEEN', 13);"
"define('ONE', 1);"
"class Foo {"
" const ZERO = 0;"
" function f() {"
" if (defined('self::ZERO')) {"
" var_dump(self::ZERO);"
" }"
" if (defined('THIRTEEN')) {"
" var_dump(THIRTEEN);"
" }"
" if (defined('ONE')) {"
" var_dump(ONE);"
" }"
" $a = 'self::ZERO';"
" if (defined($a)) {"
" var_dump(self::ZERO);"
" }"
" }"
"}"
"class Bar extends Foo {"
" function f() {"
" if (defined('self::ZERO')) {"
" var_dump(self::ZERO);"
" }"
" if (defined('parent::ZERO')) {"
" var_dump(parent::ZERO);"
" }"
" $a = 'parent::ZERO';"
" if (defined($a)) {"
" var_dump(parent::ZERO);"
" }"
" }"
"}"
"class Goo {"
" const ZERO = Bar::ZERO;"
"}"
"$a = 'Foo::ZERO';"
"if (defined($a)) {"
" var_dump(Foo::ZERO);"
"}"
"$a = 'Bar::ZERO';"
"if (defined($a)) {"
" var_dump(Bar::ZERO);"
"}"
"$a = 'Goo::ZERO';"
"if (defined($a)) {"
" var_dump(Goo::ZERO);"
"}"
"$obj = new Foo;"
"$obj->f();"
"$obj = new Bar;"
"$obj->f();");
MVCR("<?php "
"function handler($errno, $errstr) {"
" var_dump($errno);"
" return true;"
"}"
"set_error_handler('handler');"
"unserialize();"
"define();"
"define('u');"
"define('a','X');"
"define('b','Y',false);"
"define('c',1,2,3,4,foo());"
"var_dump(a,b,c);"
"var_dump(defined('a'),defined('b'),defined('c'));"
"function foo() {"
" var_dump('FOO');"
"}");
return true;
}
bool TestCodeRun::TestAssignment() {
MVCR("<?php "
"function f($a) {"
" var_dump($a);"
"}"
"class ClassA {"
" var $val;"
" function foo() { f($val = 1); }"
" function bar() { f($this->val = 1); }"
" function goo() { f($val = 'val'); f($this->$val = 2); }"
" function zoo() {"
" var_dump($val); var_dump($this->val);"
" }"
"}"
"function foo() {"
" f($val2 = 1);"
"}"
"$obj = new ClassA();"
"var_dump($obj);"
"$obj->foo();"
"var_dump($obj);"
"$obj->bar();"
"var_dump($obj);"
"$obj->goo();"
"var_dump($obj);"
"$obj->zoo();");
MVCR("<?php "
"function f($a) {"
" var_dump($a);"
"}"
"class ClassA {"
" static $val = 1;"
" function foo() { f($val = 'val'); f($this->$val = 2); }"
" function foo2() { f($this->val = 3); }"
" function bar() {"
" var_dump($val); var_dump($this->val);"
" }"
"}"
"$obj = new ClassA();"
"var_dump($obj);"
"$obj->foo();"
"var_dump($obj);"
"$obj->bar();"
"$obj->foo2();"
"var_dump($obj);"
"$obj->bar();");
MVCR("<?php "
"class X"
"{"
" function __destruct() { var_dump('destruct'); }"
"}"
"function foo() {"
" $x = new X;"
" var_dump('before');"
" $x = null;"
" var_dump('after');"
"}"
"foo();");
MVCR("<?php "
"function e() { return 'hello'; }"
"function foo() {"
" $expected = e();"
" $list_expected = \"[$expected,$expected]\";"
" var_dump($expected, $list_expected);"
"}"
"foo();");
MVCR("<?php\n"
"function g($key, $old, $new, $s = false) {\n"
" $diff = array();\n"
" if ($old !== $new) {\n"
" if ($s) {\n"
" $old = f($old, true);\n"
" $new = f($new, true);\n"
" }\n"
" $diff['old'][$key] = $old;\n"
" $diff['new'][$key] = $new;\n"
" }\n"
" return $diff;\n"
"}\n"
"function f($a0, $a1) {\n"
" return 'should_be_modified';\n"
"}\n"
"var_dump(g('key', 'old', 'new', true));\n");
MVCR("<?php\n"
"\n"
"class dom {\n"
" public $kid;\n"
" public function __destruct() {\n"
" echo \"dom destructing\n\";\n"
" $this->kid->check();\n"
" $this->kid->clear_unset();\n"
" }\n"
"}\n"
"\n"
"class node {\n"
" public $dom;\n"
"\n"
" public function __construct($dom) {\n"
" $this->dom = $dom;\n"
" $dom->kid = $this;\n"
" }\n"
" public function __destruct() {\n"
" echo \"node destructing\n\";\n"
" }\n"
" public function clear_unset() {\n"
" unset($this->dom);\n"
" }\n"
" public function clear_set() {\n"
" $this->dom = null;\n"
" }\n"
" public function check() {\n"
" var_dump(isset($this->dom));\n"
" }\n"
"}\n"
"\n"
"class node_arr {\n"
" public $doms = array();\n"
"\n"
" public function __construct($dom) {\n"
" $this->doms[0] = $dom;\n"
" $dom->kid = $this;\n"
" }\n"
" public function __destruct() {\n"
" echo \"node destructing\n\";\n"
" }\n"
" public function clear_unset() {\n"
" unset($this->doms[0]);\n"
" }\n"
" public function clear_set() {\n"
" $this->doms[0] = null;\n"
" }\n"
" public function check() {\n"
" var_dump(isset($this->doms[0]));\n"
" }\n"
"}\n"
"\n"
"echo \"\nProperty, SetM\n\";\n"
"$node = new node(new dom);\n"
"$node->clear_set();\n"
"unset($node);\n"
"\n"
"echo \"\nProperty, UnsetM\n\";\n"
"$node = new node(new dom);\n"
"$node->clear_unset();\n"
"unset($node);\n"
"\n"
"echo \"\nArray, SetM\n\";\n"
"$node = new node_arr(new dom);\n"
"$node->clear_set();\n"
"unset($node);\n"
"\n"
"echo \"\nArray, UnsetM\n\";\n"
"$node = new node_arr(new dom);\n"
"$node->clear_unset();\n"
"unset($node);\n");
return true;
}
bool TestCodeRun::TestSimpleXML() {
MVCR("<?php\n"
"function addChildNode(SimpleXMLElement $parent, "
"SimpleXMLElement $node) {\n"
" $newchild = $parent->addChild($node->getName(), (string)$node);\n"
" foreach ($node->attributes() as $name => $value) {\n"
" $newchild->addAttribute($name, $value);\n"
" }\n"
" foreach ($node->children() as $child) {\n"
" addChildNode($newchild, $child);\n"
" }\n"
"}\n"
"\n"
"$xmlreq = '<a><item><node><sub>1st</sub>"
"<sub>2nd</sub></node></item></a>';\n"
"$quote = simplexml_load_string($xmlreq);\n"
"$req = new SimpleXMLElement('<node/>');\n"
"foreach ($quote->attributes() as $name => $value) {\n"
" $req->addAttribute($name, $value);\n"
"}\n"
"foreach ($quote->children() as $child) {\n"
" addChildNode($req, $child);\n"
"}\n"
"\n"
"$vertex = new SimpleXMLElement('<root/>');\n"
"addChildNode($vertex, $req);\n"
"var_dump($vertex->asXML());\n"
);
MVCR("<?php $x = new SimpleXMLElement('<foo><bar>345.234</bar></foo>');"
"var_dump((double)$x->bar);");
MVCR("<?php $x = new SimpleXMLElement('<foo><bar></bar></foo>');"
"var_dump((bool)$x->bar);");
MVCR("<?php $x = new SimpleXMLElement('<foo><bar>0</bar></foo>');"
"var_dump((bool)$x->bar);");
MVCR("<?php "
"$x = new SimpleXMLElement('<foo/>'); "
"$x->addAttribute('attr', 'one'); "
"$x['attr'] = 'two'; "
"var_dump((string)$x['attr']); "
"var_dump($x->asXML());");
MVCR("<?php\n"
"$node = new SimpleXMLElement('<foo><bar>whoops</bar></foo>');\n"
"var_dump((array)$node->bar);");
MVCR("<?php\n"
"$node = new SimpleXMLElement('<foo><bar name=\"value\">"
"whoops</bar></foo>');\n"
"var_dump((array)$node->bar);");
MVCR("<?php\n"
"$node = new SimpleXMLElement('<foo><bar>whoops</bar></foo>');\n"
"var_dump((string)$node[0]);");
MVCR("<?php\n"
"$node = simplexml_load_string('<foo><bar>whoops</bar></foo>');"
"var_dump((string)$node);");
MVCR("<?php\n"
"$node = new SimpleXMLElement('<foo><bar>whoops</bar></foo>');"
"var_dump((string)$node);");
MVCR("<?php\n"
"$node = new SimpleXMLElement('<foo>whoops</foo>');"
"var_dump((string)$node);");
MVCR("<?php\n"
"$sxe = new SimpleXMLElement('<image-definition />');\n"
"$sxe->addChild('path', 'some/path/to/my.file');\n"
"$sxe->addChild('options');\n"
"$sxe->options->addChild('paddingbottom', 1);\n"
"var_dump((string)$sxe->path);\n"
"var_dump((string)$sxe->options->paddingbottom);\n"
);
MVCR("<?php\n"
"$x = new SimpleXMLElement('<foo/>');\n"
"$x->addChild('bar', 'whoops');\n"
"var_dump((string)$x);\n");
MVCR(
"<?php\n"
"function convert_simplexml_to_array($sxml) {\n"
" $arr = array();\n"
" if ($sxml) {\n"
" foreach ($sxml as $k => $v) {\n"
" if ($sxml['list']) {\n"
" if (isset($v['key'])) {\n"
" $arr[(string)$v['key']] = convert_simplexml_to_array($v);\n"
" } else {\n"
" $arr[] = convert_simplexml_to_array($v);\n"
" }\n"
" } else {\n"
" $arr[$k] = convert_simplexml_to_array($v);\n"
" }\n"
" }\n"
" }\n"
" if (sizeof($arr) > 0) {\n"
" return $arr;\n"
" } else {\n"
" return (string)$sxml;\n"
" }\n"
"}\n"
"\n"
"$xml = <<<EOM\n"
"<root list=\"true\">\n"
" <node key=\"key1\" list=\"true\">\n"
" <subnode key=\"subkey1\" list=\"true\">\n"
" <name>value1-1</name>\n"
" <name>value1-2</name>\n"
" </subnode>\n"
" <subnode key=\"subkey2\">value1</subnode>\n"
" </node>\n"
" <node key=\"key2\" list=\"true\">\n"
" <subnode>value2</subnode>\n"
" </node>\n"
"</root>\n"
"EOM;\n"
"\n"
"$sxml = simplexml_load_string($xml);\n"
"var_dump(convert_simplexml_to_array($sxml));\n"
);
MVCR("<?php\n"
"$xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?><response>test</response>';\n"
"$sxml = simplexml_load_string($xml);\n"
"foreach ($sxml as $k => $v) {\n"
" var_dump($k, (string)$v);\n"
"}\n");
MVCR("<?php\n"
"$xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?><response><t>6</t><t>7</t><t>8</t></response>';\n"
"$sxml = simplexml_load_string($xml);\n"
"foreach ($sxml as $k => $v) {\n"
" var_dump($k, (int)$v);\n"
"}\n");
MVCR("<?php\n"
"$xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?><response><t>6</t><t>7</t><t>8</t></response>';\n"
"$sxml = simplexml_load_string($xml);\n"
"foreach ($sxml as $k => $v) {\n"
" var_dump($k, (string)$v);\n"
"}\n");
MVCR("<?php\n"
"$xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>"
"<invalidations><invalidation id=\"12345\"/></invalidations></root>';\n"
"$dom = new SimpleXMLElement($xml);\n"
"$invalidations = $dom->invalidations;\n"
"var_dump((string)$invalidations->invalidation[\"id\"]);\n"
"foreach ($invalidations as $node) {\n"
" var_dump((string)$node->invalidation[\"id\"]);\n"
"}\n");
MVCR("<?php\n"
"\n"
"$file = <<<EOM\n"
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<wurfl-config>\n"
" <persistence>\n"
" <provider>memcache</provider>\n"
" <params></params>\n"
" </persistence>\n"
"\n"
" <cache>\n"
" <provider>memcache</provider>\n"
" <params></params>\n"
" </cache>\n"
"</wurfl-config>\n"
"EOM;\n"
"var_dump($file);\n"
"\n"
"$xml = simplexml_load_string($file);\n"
"foreach ($xml->children() as $parent_name => $xml_ele) {\n"
" var_dump($parent_name);\n"
"\n"
" foreach ($xml_ele->children() as $key => $value) {\n"
" var_dump((string)$key, (string)$value);\n"
" }\n"
"}\n"
);
MVCR("<?php\n"
"$xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?><response><t>6</t></response>';\n"
"$sxml = simplexml_load_string($xml);\n"
"function convert_simplexml_to_array($sxml) {\n"
" if ($sxml) {\n"
" foreach ($sxml as $k => $v) {\n"
" var_dump($k, (string)$v);\n"
" convert_simplexml_to_array($v);\n"
" }\n"
" }\n"
"}\n"
"convert_simplexml_to_array($sxml);");
MVCR("<?php $doc = new SimpleXMLElement('<?xml version=\"1.0\"?><root><node><option>1</option></node></root>'); $doc->node->option = false; var_dump($doc->asXML());");
MVCR("<?php $doc = new SimpleXMLElement('<?xml version=\"1.0\"?><root><node><option>1</option></node></root>'); $doc->node->option = 0; var_dump($doc->asXML());");
MVCR("<?php $doc = new SimpleXMLElement('<?xml version=\"1.0\"?><root><node><option>1</option></node></root>'); unset($doc->node->option); var_dump($doc->asXML());");
MVCR("<?php $doc = simplexml_load_String('<?xml version=\"1.0\"?><lists><list path=\"svn+ssh\"><entry kind=\"dir\"></entry><entry kind=\"file\"></entry></list></lists>'); foreach ($doc->list[0]->entry as $r) { var_dump((array)$r->attributes());}");
MVCR("<?php "
"$sxe = new SimpleXMLElement('<foo />');"
"$sxe->addChild('options');"
"$sxe->options->addChild('paddingtop', 0);"
"echo 'Success\n';");
MVCR("<?php $doc = simplexml_load_string('<?xml version=\"1.0\"?><root xmlns:foo=\"http://example.com\"><foo:b1>c1</foo:b1><foo:b2>c2</foo:b2><foo:b2>c3</foo:b2></root>'); $foo_ns_bar = $doc->children('http://example.com');"
"var_dump($doc->getName());"
"foreach ($foo_ns_bar as $v) var_dump((string)$v);"
"var_dump($foo_ns_bar->getName());"
"var_dump(count($foo_ns_bar->b1));"
"var_dump((string)$foo_ns_bar->b1);"
"var_dump((string)$foo_ns_bar->b1[0]);"
"foreach ($foo_ns_bar->b1 as $v) var_dump((string)$v);"
"var_dump(count($foo_ns_bar->b2));"
"var_dump((string)$foo_ns_bar->b2[0]);"
"var_dump((string)$foo_ns_bar->b2[1]);"
"foreach ($foo_ns_bar->b2 as $v) var_dump((string)$v);"
);
MVCR("<?php function printElement($el, $indent='') {"
" if (strlen($indent) > 10) {"
" var_dump('Recursed to deep, backing out');"
" return;"
" }"
" print $indent.$el->getName().\"\\n\";"
" foreach ($el->attributes() as $k => $v) {"
" print $indent.$k.' => '.$v.\"\\n\";"
" }"
" foreach ($el->children() as $child) {"
" printElement($child, $indent.' ');"
" }"
"}"
"$a = simplexml_load_string('<?xml version=\"1.0\" encoding=\"utf-8\"?><xx><yy><node a=\"b\">hi</node></yy><yy><node a=\"b\">hi</node></yy></xx>');"
"printElement($a);"
);
MVCR("<?php $a = simplexml_load_string('<?xml version=\"1.0\" encoding=\"utf-8\"?><node a=\"b\"><subnode attr1=\"value1\" attr2=\"value2\">test</subnode><subnode><subsubnode>test</subsubnode></subnode><test>v</test></node>');"
"var_dump((array)$a->attributes());"
"var_dump((string)$a->subnode[0]);"
"var_dump((string)$a->subnode[0]['attr1']);"
"var_dump((string)$a->subnode[1]['subsubnode']);"
"var_dump((string)$a->subnode[1]->subsubnode);"
"var_dump((string)$a->test);"
"var_dump((array)$a->subnode[0]->attributes());"
"var_dump((array)$a->subnode[1]->attributes());"
"var_dump($a->asxml());"
"var_dump((string)$a->addchild('newnode', 'newvalue'));"
"$a->addattribute('newattr', 'newattrvalue');"
"var_dump($a->asxml());"
"var_dump((array)$a->attributes());"
"var_dump((string)$a->newnode);"
"var_dump($a->getname());"
"var_dump((array)$a->children()->subnode[0]->subsubnode);"
"$nodes = $a->xpath('//node/subnode');"
"var_dump((string)$nodes[1]->subsubnode);"
"$nodes = $nodes[1]->xpath('subsubnode');"
"var_dump((string)$nodes[0]);"
);
MVCR("<?php $a = new SimpleXMLElement('<?xml version=\"1.0\" encoding=\"utf-8\"?><node><subnode><subsubnode>test</subsubnode></subnode></node>');"
"var_dump((array)($a->subnode->subsubnode));"
"var_dump((string)($a->subnode->subsubnode));"
);
MVCR("<?php $a = simplexml_load_string('<?xml version=\"1.0\" encoding=\"utf-8\"?><node><subnode><subsubnode>test</subsubnode></subnode></node>');"
"var_dump((array)($a->subnode->subsubnode));"
"var_dump((string)($a->subnode->subsubnode));"
);
MVCR("<?php $a = simplexml_load_string('<?xml version=\"1.0\" encoding=\"utf-8\"?><node><subnode><subsubnode>test</subsubnode></subnode></node>');"
"var_dump((string)($a->subnode->subsubnode['0']));"
"var_dump((string)($a->subnode->subsubnode[0]));"
);
MVCR("<?php $a = simplexml_load_string('<?xml version=\"1.0\" encoding=\"utf-8\"?><node><subnode attr1=\"value1\">test</subnode></node>');"
"var_dump((string)($a->subnode['attr1']));"
);
MVCR("<?php $a = simplexml_load_string('<?xml version=\"1.0\" encoding=\"utf-8\"?><node><subnode><subsubnode attr1=\"value1\">test</subsubnode></subnode></node>');"
"var_dump((string)($a->subnode->subsubnode['attr1']));"
);
MVCR("<?php $a = new SimpleXMLElement('<?xml version=\"1.0\" encoding=\"utf-8\"?><node><subnode><subsubnode><sssnode>test</sssnode></subsubnode></subnode></node>');"
"var_dump((string)($a->subnode->subsubnode->sssnode));"
);
MVCR("<?php "
"$post_xml = '<?xml version=\"1.0\" encoding=\"utf-8\"?><ScanResults version=\"1.0\"><scannedItem itemType=\"5\" itemSize=\"1079856\" "
"itemName=\"C:\\\\Program Files\\\\VMware\\\\VMware Tools\\\\VMwareUser.exe\" "
"IsScanned=\"1\" IsInfected=\"0\" ObjectSummary=\"0\" "
"ScanError=\"0\"/></ScanResults>';"
"$xml = new SimpleXMLElement($post_xml);"
"foreach ($xml->scannedItem as $item) {"
" echo $item['itemName'] . \"\\n\";"
"}");
MVCR("<?php $a = simplexml_load_string('<?xml version=\"1.0\" encoding=\"utf-8\"?><?mso-application progid=\"Excel.Sheet\"?><node><subnode><subsubnode>test</subsubnode></subnode></node>');"
"var_dump((string)($a->subnode->subsubnode[0]));"
);
MVCR("<?php\n"
"$xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?><response><t a=\"apple\" b=\"banana\">6</t><t>7</t><t>8</t></response>';\n"
"$sxml = simplexml_load_string($xml);\n"
"var_dump(count($sxml->t));\n"
"var_dump((string)$sxml->t[0]);\n"
"var_dump((string)$sxml->t[1]);\n"
"var_dump((string)$sxml->t[2]);\n"
"var_dump(count($sxml->t->bogus));\n"
"var_dump(count($sxml->t->attributes()));\n"
"foreach ($sxml->bogus as $v) {}");
return true;
}
bool TestCodeRun::TestXML() {
MVCR(
"<?php\n"
"class xml {\n"
" var $parser;\n"
" function xml() {\n"
" $this->parser = xml_parser_create();\n"
" xml_set_object($this->parser, $this);\n"
" xml_set_element_handler($this->parser, 'tag_open', 'tag_close');\n"
" xml_set_character_data_handler($this->parser, 'cdata');\n"
" }\n"
" function parse($data) { xml_parse($this->parser, $data);}\n"
" function tag_open($parser, $tag, $attributes) {\n"
" var_dump($tag, $attributes);\n"
" }\n"
" function cdata($parser, $cdata) { var_dump($cdata);}\n"
" function tag_close($parser, $tag){ var_dump($tag);}\n"
"}\n"
"\n"
"$xml_parser = new xml();\n"
"$xml_parser->parse('<A ID=\"hallo\">PHP</A>');\n"
);
MVCR("<?php\n"
"function parse_callback() {\n"
" var_dump(func_get_args());\n"
"}\n"
"function main() {\n"
" $p = xml_parser_create();\n"
" xml_set_element_handler($p, 'parse_callback', 'parse_callback');\n"
" xml_set_element_handler($p, false, 'parse_callback');\n"
" xml_parse($p, \"<tag><child/></tag>\", true);\n"
"\n"
" $p = xml_parser_create();\n"
" xml_set_element_handler($p, 'parse_callback', 'parse_callback');\n"
" xml_set_element_handler($p, 'parse_callback', '');\n"
" xml_parse($p, \"<tag><child/></tag>\", true);\n"
"}\n"
"main();\n");
return true;
}
bool TestCodeRun::TestDOMDocument() {
MVCR("<?php $obj = new DOMText(); var_dump($obj instanceof DOMNode);");
MVCR("<?php $xml = '<?xml version=\"1.0\"?><dependencies><dependency dependency_id=\"0\" dependent_id=\"1\"/><dependency dependency_id=\"4\" dependent_id=\"5\"/><dependency dependency_id=\"5\" dependent_id=\"6\"/><dependency dependency_id=\"9\" dependent_id=\"8\"/><dependency dependency_id=\"10\" dependent_id=\"8\"/><dependency dependency_id=\"12\" dependent_id=\"13\"/><dependency dependency_id=\"12\" dependent_id=\"14\"/></dependencies>';\n"
"$dom = new domDocument;\n"
"$dom->loadxml($xml);\n"
"$xpath = new DOMXPath($dom);\n"
"$node_list = $xpath->query('//dependencies/dependency[@dependency_id = 0 and @dependent_id = 1]');\n"
"$dependencies = $xpath->query('//dependencies')->item(0);\n"
"$dependencies->removeChild($node_list->item(0));\n"
);
MVCR("<?php $xml = '<?xml version=\"1.0\"?><dependencies><dependency dependency_id=\"0\" dependent_id=\"1\"/><dependency dependency_id=\"4\" dependent_id=\"5\"/><dependency dependency_id=\"5\" dependent_id=\"6\"/><dependency dependency_id=\"9\" dependent_id=\"8\"/><dependency dependency_id=\"10\" dependent_id=\"8\"/><dependency dependency_id=\"12\" dependent_id=\"13\"/><dependency dependency_id=\"12\" dependent_id=\"14\"/></dependencies>';\n"
"$dom = new domDocument;\n"
"$dom->loadxml($xml);\n"
"$xpath = new DOMXPath($dom);\n"
"$node_list = $xpath->query('//dependencies/dependency[@dependent_id = 8]');\n"
"foreach ($node_list as $node) {\n"
" var_dump($node->getAttribute($attribute));\n"
"}\n"
);
MVCR("<?php\n"
"$xmlstr = \"<?xml version='1.0' standalone='yes'?>\n"
"<!DOCTYPE chapter SYSTEM '/share/sgml/Norman_Walsh/"
"db3xml10/db3xml10.dtd'\n"
"[ <!ENTITY sp \\\"spanish\\\">\n"
"]>\n"
"<!-- lsfj -->\n"
"<chapter language='en'><title language='en'>Title</title>\n"
"<para language='ge'>\n"
"&sp;\n"
"<!-- comment -->\n"
"<informaltable language='&sp;kkk'>\n"
"<tgroup cols='3'>\n"
"<tbody>\n"
"<row><entry>a1</entry><entry morerows='1'>b1</entry>"
"<entry>c1</entry></row>\n"
"<row><entry>a2</entry><entry>c2</entry></row>\n"
"<row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>\n"
"</tbody>\n"
"</tgroup>\n"
"</informaltable>\n"
"</para>\n"
"</chapter> \";\n"
"\n"
"function print_node($node)\n"
"{\n"
" print \"Node Name: \" . $node->nodeName;\n"
" print \"\nNode Type: \" . $node->nodeType;\n"
" if ($node->nodeType != 3) {\n"
" $child_count = $node->childNodes->length;\n"
" } else {\n"
" $child_count = 0;\n"
" }\n"
" print \"\nNum Children: \" . $child_count;\n"
" if($child_count <= 1){\n"
" print \"\nNode Content: \" . $node->nodeValue;\n"
" }\n"
" print \"\n\n\";\n"
"}\n"
"\n"
"function print_node_list($nodelist)\n"
"{\n"
" foreach($nodelist as $node)\n"
" {\n"
" print_node($node);\n"
" }\n"
"}\n"
"\n"
"echo \"Test 1: accessing single nodes from php\n\";\n"
"$dom = new domDocument;\n"
"$dom->loadxml($xmlstr);\n"
"if(!$dom) {\n"
" echo \"Error while parsing the document\n\";\n"
" exit;\n"
"}\n"
"\n"
"// children() of of document would result in a memleak\n"
"//$children = $dom->children();\n"
"//print_node_list($children);\n"
"\n"
"echo \"--------- root\n\";\n"
"$rootnode = $dom->documentElement;\n"
"print_node($rootnode);\n"
"\n"
"echo \"--------- children of root\n\";\n"
"$children = $rootnode->childNodes;\n"
"print_node_list($children);\n"
"\n"
"// The last node should be identical with the last "
"entry in the children array\n"
"echo \"--------- last\n\";\n"
"$last = $rootnode->lastChild;\n"
"print_node($last);\n"
"\n"
"// The parent of this last node is the root again\n"
"echo \"--------- parent\n\";\n"
"$parent = $last->parentNode;\n"
"print_node($parent);\n"
"\n"
"// The children of this parent are the same children as one above\n"
"echo \"--------- children of parent\n\";\n"
"$children = $parent->childNodes;\n"
"print_node_list($children);\n"
"\n"
"echo \"--------- creating a new attribute\n\";\n"
"//This is worthless\n"
"//$attr = $dom->createAttribute(\"src\", \"picture.gif\");\n"
"//print_r($attr);\n"
"\n"
"//$rootnode->set_attributeNode($attr);\n"
"$attr = $rootnode->setAttribute(\"src\", \"picture.gif\");\n"
"$attr = $rootnode->getAttribute(\"src\");\n"
"print_r($attr);\n"
"print \"\n\";\n"
"\n"
"echo \"--------- Get Attribute Node\n\";\n"
"$attr = $rootnode->getAttributeNode(\"src\");\n"
"print_node($attr);\n"
"\n"
"echo \"--------- Remove Attribute Node\n\";\n"
"$attr = $rootnode->removeAttribute(\"src\");\n"
"print \"Removed \" . $attr . \" attributes.\n\";\n"
"\n"
"echo \"--------- attributes of rootnode\n\";\n"
"$attrs = $rootnode->attributes;\n"
"print_node_list($attrs);\n"
"\n"
"echo \"--------- children of an attribute\n\";\n"
"$children = $attrs->item(0)->childNodes;\n"
"print_node_list($children);\n"
"\n"
"echo \"--------- Add child to root\n\";\n"
"$myelement = new domElement(\"Silly\", \"Symphony\");\n"
"$newchild = $rootnode->appendChild($myelement);\n"
"print_node($newchild);\n"
"print $dom->saveXML();\n"
"print \"\n\";\n"
"\n"
"echo \"--------- Find element by tagname\n\";\n"
"echo \" Using dom\n\";\n"
"$children = $dom->getElementsByTagname(\"Silly\");\n"
"print_node_list($children);\n"
"\n"
"echo \" Using elem\n\";\n"
"$children = $rootnode->getElementsByTagName(\"Silly\");\n"
"print_node_list($children);\n"
"\n"
"echo \"--------- Unlink Node\n\";\n"
"print_node($children->item(0));\n"
"$rootnode->removeChild($children->item(0));\n"
"print_node_list($rootnode->childNodes);\n"
"print $dom->savexml();\n"
);
// dom002.phpt
MVCR("<?php\n"
"$xml = <<<HERE\n"
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
"<foo xmlns=\"http://www.example.com/ns/foo\"\n"
" xmlns:fubar=\"http://www.example.com/ns/fubar\">\n"
" <bar><test1 /></bar>\n"
" <bar><test2 /></bar>\n"
" <fubar:bar><test3 /></fubar:bar>\n"
" <fubar:bar><test4 /></fubar:bar>\n"
"</foo>\n"
"HERE;\n"
"\n"
"function dump($elems) {\n"
" foreach ($elems as $elem) {\n"
" var_dump($elem->nodeName);\n"
" dump($elem->childNodes);\n"
"}\n"
"}\n"
"\n"
"$dom = new DOMDocument();\n"
"$dom->loadXML($xml);\n"
"$doc = $dom->documentElement;\n"
"dump($dom->getElementsByTagName('bar'));\n"
"dump($doc->getElementsByTagName('bar'));\n"
"dump($dom->getElementsByTagNameNS('http://www.example.com/ns/fubar',"
" 'bar'));\n"
"dump($doc->getElementsByTagNameNS('http://www.example.com/ns/fubar',"
" 'bar'));\n"
);
// dom005.phpt
MVCR("<?php\n"
"$dom = new domdocument;\n"
"$html = <<<EOM\n"
"<html><head>\n"
"<title>Hello world</title>\n"
"</head>\n"
"<body>\n"
"This is a not well-formed<br>\n"
"html files with undeclared entities&nbsp;\n"
"</body>\n"
"</html>\n"
"EOM;\n"
"$dom->loadHTML($html);\n"
"print \"--- save as XML\n\";\n"
"\n"
"print adjustDoctype($dom->saveXML());\n"
"print \"--- save as HTML\n\";\n"
"\n"
"print adjustDoctype($dom->saveHTML());\n"
"\n"
"function adjustDoctype($xml) {\n"
" return str_replace("
"array(\">\n<\",\"DOCTYPE HTML\",'<p>','</p>'),"
"array(\"><\",\"DOCTYPE html\",'',''),$xml);\n"
"}\n"
);
// dom006.phpt
MVCR("<?php\n"
"class books extends domDocument {\n"
" function addBook($title, $author) {\n"
" $titleElement = $this->createElement('title');\n"
" $titleElement->appendChild($this->createTextNode($title));\n"
" $authorElement = $this->createElement('author');\n"
" $authorElement->appendChild($this->createTextNode($author));\n"
" $bookElement = $this->createElement('book');\n"
" $bookElement->appendChild($titleElement);\n"
" $bookElement->appendChild($authorElement);\n"
" $this->documentElement->appendChild($bookElement);\n"
" }\n"
"}\n"
"\n"
"$dom = new books;\n"
"\n"
"$xml = <<<EOM\n"
"<?xml version='1.0' ?>\n"
"<books>\n"
" <book>\n"
" <title>The Grapes of Wrath</title>\n"
" <author>John Steinbeck</author>\n"
" </book> <book>\n"
" <title>The Pearl</title> <author>John Steinbeck</author>\n"
" </book></books>\n"
"EOM;\n"
"\n"
"$dom->loadXML($xml);\n"
"$dom->addBook('PHP de Luxe', 'Richard Samar, Christian Stocker');\n"
"print $dom->saveXML();"
);
// dom007.phpt
MVCR("<?php\n"
"$xml = <<< EOXML\n"
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
"<!DOCTYPE courses [\n"
"<!ELEMENT courses (course+)>\n"
"<!ELEMENT course (title, description, temp*)>\n"
"<!ATTLIST course cid ID #REQUIRED>\n"
"<!ELEMENT title (#PCDATA)>\n"
"<!ELEMENT description (#PCDATA)>\n"
"<!ELEMENT temp (#PCDATA)>\n"
"<!ATTLIST temp vid ID #REQUIRED>\n"
"<!ENTITY test 'http://www.hpl.hp.com/semweb/2003/query_tester#'>\n"
"<!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n"
"<!NOTATION GIF PUBLIC \"-\" \"image/gif\">\n"
"<!ENTITY myimage PUBLIC \"-\" \"mypicture.gif\" NDATA GIF>\n"
"]>\n"
"<courses>\n"
" <course cid=\"c1\">\n"
" <title>Basic Languages</title>\n"
" <description>Introduction to Languages</description>\n"
" </course>\n"
" <course cid=\"c6\">\n"
" <title>French I</title>\n"
" <description>Introduction to French</description>\n"
" <temp vid=\"c7\">\n"
" </temp>\n"
" </course>\n"
"</courses>\n"
"EOXML;\n"
"\n"
"$dom = new DOMDocument();\n"
"$dom->loadXML($xml);\n"
"\n"
"$dtd = $dom->doctype;\n"
"\n"
"/* Notation Tests */\n"
"$nots = $dtd->notations;\n"
"\n"
"$length = $nots->length; var_dump($length);\n"
"echo \"Length: \".$length.\"\n\";\n"
"\n"
"foreach ($nots AS $key=>$node) {\n"
" echo \"Key $key: \".$node->nodeName.\" (\".\n"
"$node->systemId.\") (\".$node->publicId.\")\n\";\n"
"}\n"
"print \"\n\";\n"
"for($x=0; $x < $length; $x++) {\n"
" echo \"Index $x: \".$nots->item($x)->nodeName.\" (\".\n"
" $nots->item($x)->systemId.\") "
"(\".$nots->item($x)->publicId.\")\n\";\n"
"}\n"
"\n"
"echo \"\n\";\n"
"$node = $nots->getNamedItem('xxx');\n"
"var_dump($node);\n"
"\n"
"echo \"\n\";\n"
"/* Entity Decl Tests */\n"
"$ents = $dtd->entities;\n"
"$length = $ents->length;\n"
"echo \"Length: \".$length.\"\n\";\n"
"foreach ($ents AS $key=>$node) {\n"
" echo \"Key: $key Name: \".$node->nodeName.\"\n\";\n"
"}\n"
"echo \"\n\";\n"
"for($x=0; $x < $length; $x++) {\n"
" echo \"Index $x: \".$ents->item($x)->nodeName.\"\n\";\n"
"}\n"
"\n"
"echo \"\n\";\n"
"$node = $ents->item(3);\n"
"var_dump($node);\n"
"$node = $ents->getNamedItem('xxx');\n"
"var_dump($node);\n"
);
MVCR("<?php"
" function rerender($html, $frag = false) {"
" $doc = new DOMDocument();"
" if ($frag) {"
" $body = $doc->createDocumentFragment();"
" $body->appendXML($html);"
" } else {"
" $doc->loadHTML($html);"
" $body = $doc->documentElement;"
" }"
" return helper($body);"
" }"
""
" function helper($element) {"
" if ($element instanceof DOMText) {"
" return htmlspecialchars($element->nodeValue);"
" } else {"
" $body = '';"
" foreach ($element->childNodes as $child) {"
" $body .= helper($child);"
" }"
""
" if ($element instanceof DOMElement) {"
" $attrs = array();"
" foreach ($element->attributes as $attr) {"
" $attrs[] = htmlspecialchars($attr->name) . '=\"' . "
" htmlspecialchars($attr->value) . '\"';"
" }"
" if ($attrs) {"
" $attrs = ' ' . implode(' ', $attrs);"
" } else {"
" $attrs = '';"
" }"
" return '<' . $element->tagName . $attrs . '>' . $body . "
" '</' . $element->tagName . '>';"
" } else {"
" return $body;"
" }"
" }"
" }"
""
" $fragment = 'Hello, <b>world</b>.';"
" $document = '<html><body><div style=\"color:red\">"
" <p class=\"thing\">'.$fragment.'</p></div>';"
""
" echo rerender($fragment, true).\"\n\n\";"
" echo rerender($document, false).\"\n\n\";"
);
MVCR("<?php "
"$xml ="
" '<root>$1 - <template><title>SITENAME</title></template></root>';"
"$dom = new DOMDocument();"
"$dom->loadXML($xml);"
"new foo($dom->documentElement);"
"class foo {"
" function foo($a) {"
" var_dump($a);"
" }"
"}");
MVCR("<?php\n"
"$dom = new DOMDocument();\n"
"$dom->loadXML('<a><b><c /></b></a>');\n"
"$remove = array();\n"
"foreach ($dom->getElementsByTagName('b') as $data) {\n"
" foreach ($data->childNodes as $element) {\n"
" if ($element instanceof DOMElement) {\n"
" $remove[] = $element;\n"
" }\n"
" }\n"
"}\n"
"foreach ($remove as $r) {\n"
" $r->parentNode->removeChild($r);\n"
"}\n"
"echo $dom->saveXML();\n"
);
MVCRO("<?php\n"
"function foo() {\n"
" $html = '<b>Hello</b><i>World</i>';\n"
" $doc = new DOMDocument();\n"
" $element = $doc->createDocumentFragment();\n"
" $element->appendXML($html);\n"
" foreach ($element->childNodes->getIterator() as $child) {\n"
" $element = null;\n"
" $doc = null;\n"
" var_dump($child->nodeValue);\n"
" }\n"
"}\n"
"foo();\n",
"string(5) \"Hello\"\n"
"string(5) \"World\"\n"
);
/* github issue #556 */
MVCR( "<?php "
"class MyNode extends DOMNode {}"
"class MyElement extends DOMElement {}"
"$dom = new DOMDocument;"
"var_dump($dom->registerNodeClass('DOMNode', 'MyNode'));"
"var_dump($dom->registerNodeClass('DOMElement', 'MyElement'));"
);
return true;
}
bool TestCodeRun::TestFile() {
//MVCR("<?php "
// "$gif = imagecreatefromgif('http://www.php.net/images/php.gif');"
// "imagegif($gif);"
// "imagedestroy($gif);");
MVCR("<?php\n"
"function main() {\n"
" file_put_contents(\"/tmp/temp.txt\",\n"
" \"put this in the txt file\\n\");\n"
" $txt = file_get_contents(\"/tmp/temp.txt\");\n"
" echo $txt;\n"
" file_put_contents(\"compress.zlib:///tmp/temp.zip\",\n"
" \"put this in the zip file\\n\");\n"
" $zip = file_get_contents(\"compress.zlib:///tmp/temp.zip\");\n"
" echo $zip;\n"
" file_put_contents('php://stdout', \"file_put_contents\\n\");\n"
"}\n"
"main();\n");
MVCR("<?php "
"$fh = fopen('php://output', 'w');"
"if (!$fh) {"
" throw new Exception('foo');"
"}"
"fprintf($fh, \"hello\\n\");"
"var_dump(fflush($fh));"
"var_dump(fclose($fh));"
"$fh = fopen('php://output', 'a');"
"if (!$fh) {"
" throw new Exception('foo');"
"}"
"fprintf($fh, \"hello\\n\");"
"var_dump(fflush($fh));"
"var_dump(fclose($fh));"
"$fh = fopen('php://output', 'r');"
"if (!$fh) {"
" throw new Exception('foo');"
"}"
"fprintf($fh, \"hello\\n\");"
"var_dump(fflush($fh));"
"var_dump(fclose($fh));");
MVCR("<?php "
"var_dump(filetype('test/test_ext_file2.tmp'));"
"var_dump(is_link('test/test_ext_file2.tmp'));"
"$a = lstat('test/test_ext_file2.tmp');"
"var_dump($a['mtime']);");
MVCR("<?php "
"$f = fopen('php://stdout', 'w');"
"fprintf($f, 'stdout');");
MVCR("<?php "
"$input = fopen('/tmp/junk.txt', 'w+');"
"fwrite($input, 'hello world');"
""
"fseek($input, 0);"
"$output = fopen('php://memory', 'w+');"
"stream_copy_to_stream($input, $output);"
"fseek($output, 0);"
"$bytes = fread($output, 1024);"
"print \"From file, without Maxlen: <\".serialize($bytes).\">.\\n\";"
""
"fseek($input, 0);"
"$output = fopen('php://memory', 'w+');"
"stream_copy_to_stream($input, $output, null);"
"fseek($output, 0);"
"$bytes = fread($output, 1024);"
"print \"From file, using Maxlen null: <\".serialize($bytes).\">.\\n\";"
""
""
"fseek($input, 0);"
"$output = fopen('php://memory', 'w+');"
"stream_copy_to_stream($input, $output, -1);"
"fseek($output, 0);"
"$bytes = fread($output, 1024);"
"print \"From file, using Maxlen -1: <\".serialize($bytes).\">.\\n\";");
MVCR("<?php "
"$tmp_dir='/tmp/tcr_tmp_dir'.getmypid();"
"mkdir($tmp_dir);"
"print_r(glob($tmp_dir.'/*'));"
"rmdir($tmp_dir);");
MVCR("<?php "
"$src = tmpfile();"
"$dst = tmpfile();"
"fwrite($src, 'a');"
"fseek($src, 0);"
"stream_copy_to_stream($src, $dst);"
"fseek($dst, 0);"
"$str = stream_get_contents($dst);"
"fseek($src, 0);"
"stream_copy_to_stream($src, $dst);"
"fseek($dst, 0);"
"$str = stream_get_contents($dst);"
"echo $str;");
MVCR("<?php "
"define('FILENAME', '/tmp/flock_file.dat');"
"function flock_or_die($filename, $resource, $flock_op) {"
" $r = flock($resource, $flock_op);"
" var_dump($r); "
"}"
"$resource = fopen(FILENAME, 'w');"
"flock_or_die(FILENAME, $resource, LOCK_EX);"
"flock_or_die(FILENAME, $resource, LOCK_UN);"
"unlink(FILENAME);");
MVCR("<?php "
"$h = popen(\"echo foo; exit 2\", 'r');"
"$content = stream_get_contents($h);"
"$result = pclose($h);"
"echo trim($content).\"/\".$result.\"/\".gettype($result).\"\\n\";");
MVCR("<?php "
"$fp = fopen('test/test_ext_file.txt', 'r');"
"var_dump(pclose($fp));");
MVCR("<?php "
"$fp = fopen('test/nonexist.txt', 'r');"
"var_dump(pclose($fp));");
MVCR("<?php "
"fclose(STDOUT);"
"echo 'test';"
"ob_start();");
MVCR("<?php "
"define('BAR','Some Value');"
"var_dump(parse_ini_string('foo=BAR'));"
);
return true;
}
bool TestCodeRun::TestDirectory() {
MVCR("<?php "
"$d = dir(\"test/\");"
"echo \"Path: \" . $d->path . \"\\n\";"
"while (false !== ($entry = $d->read())) {"
" echo $entry.\"\\n\";"
"}"
"$d->rewind();"
"while (false !== ($entry = $d->read())) {"
" echo $entry.\"\\n\";"
"}"
"$d->close();");
return true;
}
bool TestCodeRun::TestBadFunctionCalls() {
// make sure no error
MVCR("<?php "
"error_reporting(E_ALL & ~E_NOTICE);"
"class A { function __construct() {}} $obj = new A(10);");
// make sure foo() is still called
MVCR("<?php "
"error_reporting(E_ALL & ~E_NOTICE);"
"function foo($a) { print $a;} "
"class A { function __construct() {}} $obj = new A(foo(10));");
// make sure 1st parameter is corrected passed in
MVCR("<?php "
"error_reporting(E_ALL & ~E_NOTICE);"
"function foo($a) { print $a;} function bar($a) { return $a;}"
" foo('ok', bar('bad'));");
// Too many args
MVCR("<?php "
"error_reporting(E_ALL & ~E_NOTICE);"
"function foo($x) {}"
"function z() {"
" $yay = 1;"
" $snarf = 2;"
" foo(1,foo(1), $yay,$snarf);"
"}"
"z();");
// Ensure all arguments are evaluated
MVCR("<?php\n"
"function f() {\n"
" $a = array();\n"
" array_push($a[] = 1);\n"
" var_dump($a);\n"
"}\n"
"f();\n");
MVCR("<?php\n"
"function f() {\n"
" $a = 0;\n"
" array_chunk($a = 1);\n"
" var_dump($a);\n"
"}\n"
"f();\n");
MVCR("<?php\n"
"function f() {\n"
" $a = 0;\n"
" $b = 0;\n"
" $c = 0;\n"
" $d = 0;\n"
" array_chunk($a = 1, $b = 2, $c = 3, $d = 4);\n"
" var_dump($a, $b, $c, $d);\n"
"}\n"
"f();\n");
MVCR("<?php\n"
"function f() {\n"
" $arr = array();\n"
" sort($arr[0]);\n"
" var_dump($arr);\n"
" unset($arr);\n"
" $arr = array();\n"
" sort($arr[0],0,0,0,0,0,0,0,0);\n"
" var_dump($arr);\n"
"}\n"
"f();\n");
// Test invoking method on non-objects
MVCRO("<?php\n"
"$vals = array(null, 0, false, array(), 'test');\n"
"foreach ($vals as $val) {\n"
" try {\n"
" $val->foo();\n"
" } catch (BadMethodCallException $e) {\n"
" echo \"BadMethodCallException thrown\\n\";\n"
" }\n"
"}\n",
"BadMethodCallException thrown\n"
"BadMethodCallException thrown\n"
"BadMethodCallException thrown\n"
"BadMethodCallException thrown\n"
"BadMethodCallException thrown\n");
// Make sure call_user_func() doesn't throw an exception
MVCRO("<?php\n"
"call_user_func(null, 'test');\n"
"echo \"test\\n\";",
"test\n");
return true;
}
bool TestCodeRun::TestConstructor() {
// class-name constructors should not be renamed
MVCR("<?php class A { function a() { echo \"A\n\"; }}"
"function test() { $obj = new A(); $obj->a(); }"
"test();");
// __construct takes priority
MVCR("<?php "
"class A {"
" function a() { echo \"A\n\"; }"
" function __construct() { echo \"cons\n\"; }"
"} "
"function test() { $obj = new A(); $obj->a(); } "
"test();");
MVCR("<?php "
"class A {"
" public function A() {"
" echo \"In A\\n\";"
" $this->__construct();"
" }"
" public function __construct() {"
" echo \"In A::__construct\\n\";"
" }"
"}"
"class B extends A {"
" public function B() {"
" echo \"In B\\n\";"
" $this->A();"
" }"
"}"
"$obj = new B();"
""
"class A2 {"
" public function __construct() {"
" echo \"In A2::__construct\\n\";"
" $this->B2();"
" }"
" public function B2() {"
" echo \"In B2\\n\";"
" }"
"}"
"class B2 extends A2 {"
" public function __construct() {"
" echo \"In B2::__construct\\n\";"
" parent::__construct();"
" }"
"}"
"$obj = new B2();"
"class C {"
" public function C() {}"
"}"
"class D extends C {"
" public function __construct() {"
" echo \"In D::__construct\\n\";"
" C::__construct();"
" }"
"}"
"$obj = new D;"
"$obj->c();"
"class E {"
" public function E() {"
" echo \"In E\\n\";"
" }"
" public function foo() {"
" $this->E();"
" E::__construct();"
" }"
"}"
"$obj = new E;"
"$obj->foo();");
MVCR("<?php "
"if (isset($g)) {"
" class X {}"
"} else {"
" class X {function X() {var_dump(__METHOD__);}}"
"}"
"class Y extends X {"
" function __construct($a, $b) {"
" var_dump(__METHOD__);"
" parent::__construct($a,$b);"
" }"
"}"
"$y = new Y(1,2);");
MVCR("<?php "
"if (true) {"
" class A {"
" public function __construct($i, $j, $k) {"
" $this->a = $i * $i;"
" $this->b = $j * $j;"
" $this->c = $k * $k;"
" }"
" public $a;"
" protected $b;"
" private $c;"
" public $aa = 'aa';"
" protected $bb = false;"
" private $cc = 1.22;"
" }"
"}"
"class B extends A {"
" public function __construct($i, $j, $k) {"
" $this->a = $i + $i;"
" $this->b = $j + $j;"
" $this->c = $k + $k;"
" }"
" public $a;"
" protected $b;"
" private $c;"
" public $aa = 'aaa';"
" protected $bb = 4;"
" private $cc = 1.222;"
"}"
"function foo() {"
" $obj = new B(1, 2, 3);"
" var_dump($obj);"
"}"
"foo();");
return true;
}
bool TestCodeRun::TestIntIsset() {
MVCR("<? "
"function f($p) { $i = strlen($p); if (isset($i)) {} }");
return true;
}
bool TestCodeRun::TestTernary() {
MVCR("<?php $t = true; $a = $t ? \"hello\" : \"world\"; var_dump($a);");
MVCR("<?php $f = false; $a = $f ? 5 : \"hello\"; var_dump($a);");
MVCR("<?php $t = true; $a = $t ? \"hello\" : null; var_dump($a);");
MVCR("<?php "
"function memcache_init_split_vars() {"
" global $_SERVER;"
" global $MEMCACHED_SPLIT_HASH;"
" $MEMCACHED_SPLIT_HASH ="
" crc32(empty($_SERVER['SERVER_ADDR']) ? php_uname('n')"
" : $_SERVER['SERVER_ADDR']);"
"}");
MVCR("<?php "
"function f() {} function g() {} "
"$t = true;"
"$a = $t ? f() : g();"
"var_dump($a);");
MVCR("<?php function test($a) { $b = $a + 1 == 5 ? 5 : 7; } test(4);");
MVCR("<?php $t = true; $f = false;"
"$a = $t ? null : ($f ? \"hello\" : \"world\");");
MVCR("<?php $t = true; $a = $t ? \"\" : \"a\" . $t . \"b\";");
MVCR("<?php "
"function add_cssclass($add, $class) {"
" $class = empty($class) ? $add : $class .= ' ' . $add;"
" return $class;"
"}"
"add_cssclass('test', $a);");
MVCR("<?php "
"$a = 123;"
"echo $a ? @mysql_data_seek(null, null) : false;");
MVCR("<?php "
"function foo($a) {"
" $x = $a ? 1 : 0;"
" return $x - 5;"
"}"
"var_dump(foo(1, 2, 3));"
"var_dump(foo(0, 2, 3));");
MVCR("<?php\n"
"class X {\n"
" public $exp_info;\n"
" public function __construct(array $exp_info = null) {\n"
" $this->exp_info = $exp_info ?: array();\n"
" }\n"
"}\n"
"$x = new X(array(0, 1, 2));\n"
"var_dump($x->exp_info);\n"
"$x1 = new X(null);\n"
"var_dump($x->exp_info);\n");
MVCR("<?php\n"
"class X {}\n"
"function f($a0,\n"
" $a1,\n"
" $a2,\n"
" $a3 = null,\n"
" $a4 = null,\n"
" $a5 = null) {\n"
" $r0 = $a0 ?: 0;\n"
" $r1 = $a1 ?: 0.0;\n"
" $r2 = $a2 ?: false;\n"
" $r3 = $a3 ?: ''; \n"
" $r4 = $a4 ?: array();\n"
" $r5 = $a5 ?: new X;\n"
" return array(\n"
" $r0, $r1, $r2,\n"
" $r3, $r4, $r5);\n"
"}\n"
"var_dump(f(0, 0.0, false, null, null, null));\n"
"var_dump(f(1, 1.0, true, 'hello', array(0, 1), new X));\n");
MVCR("<?php\n"
"function f($x, $y) {\n"
" return $x[0][$y++] ?: false;\n"
"}\n"
"var_dump(f(array(array(0, 1, 2)), 0));\n"
"var_dump(f(array(array(0, 1, 2)), 1));\n");
return true;
}
bool TestCodeRun::TestUselessAssignment() {
MVCR("<?php "
"class MyDestructableClass {"
" function __construct() {"
" print \"In constructor\\n\";"
" $this->name = \"MyDestructableClass\";"
" }"
""
" function __destruct() {"
" print \"Destroying \" . $this->name . \"\\n\";"
" }"
"}"
"function foo($a) {"
" if ($a) return new MyDestructableClass();"
" return false;"
"}"
"function bar($a) {"
" if ($a) {"
" $obj = foo(1);"
" $obj = 1;"
" var_dump(2);"
" }"
" var_dump(1);"
"}"
"bar(1);");
MVCR("<?php "
"class MyDestructableClass {"
" function __construct() {"
" print \"In constructor\\n\";"
" $this->name = \"MyDestructableClass\";"
" }"
""
" function __destruct() {"
" print \"Destroying \" . $this->name . \"\\n\";"
" }"
"}"
"function foo(&$a) {"
" $a = new MyDestructableClass();"
"}"
"function bar($a) {"
" if ($a) {"
" $b = array(1, 2, 3);"
" var_dump($b);"
" foo($dummy = array(1, 2, 3));"
" $c = array(1, 2, 3);"
" var_dump($c);"
" }"
"}"
"bar(1);");
MVCR("<?php "
"function out($a) {"
" echo $a,'\\n';"
"}"
"function test($a) {"
" $a ? out('?a') : out(':a');"
" $a ? out('+a') : 0;"
" $a ? 0 : out('-a');"
" $a && out('&&a');"
" $a || out('||a');"
" $a and out('and a');"
" $a or out('or a');"
" $b = $c = 0;"
" $a || (($b = 5) + ($c = 6));"
" out($b); out($c);"
"}"
"test(0);"
"test('foo');");
MVCR("<?php "
"class A {"
" function __destruct() {"
" var_dump('done');"
" }"
"}"
""
"function foo() {"
" $a = 10;"
" if ($a == 11) {"
" return null;"
" }"
" return new A();"
"}"
""
"function bar() {"
" $a = foo();"
" var_dump('doing');"
"}"
""
"bar();");
MVCR("<?php "
"function foo($p) {"
" global $b;"
" for ($i = 0; $i < 5; $i++) {"
" if ($i > $p) {"
" $a = 10;"
" } else {"
" $a = &$b;"
" }"
" }"
"}"
"function bar() {"
" $a = foo(2);"
" var_dump($GLOBALS['b']);"
"}"
"bar();");
MVCR("<?php "
"function bar() {}"
"function foo() {"
" $foo = bar();"
" unset($foo);"
"}"
"foo();");
MVCR("<?php "
"function bug( $flag ) {"
" $tag = '';"
" if ($flag) {"
" $tag .= 'x';"
" }"
" $tag='33';"
" if ( $flag ) ; else var_dump($tag);"
"}"
"bug(false);");
return true;
}
bool TestCodeRun::TestTypes() {
MVCR("<?php "
"function foo($m, $n) {"
" $offset_change = 10;"
" $offset_change -= strlen($m) - strlen($n);"
" var_dump($offset_change);"
"}"
"foo('abc', 'efg');");
MVCR("<?php "
"function p(array $i = null) {"
" var_dump($i);"
" $i = array();"
"}"
"p();"
"function q() {"
" p(null);"
"}");
MVCR("<?php "
"function foo($p) {"
" if ($p) {"
" $a = array();"
" }"
" var_dump((string)$a);"
"}"
"foo(false);");
MVCR("<?php "
"class X {};"
"function bug() {"
" if (!$GLOBALS['x']) {"
" return;"
" }"
" return new X;"
"}"
"var_dump(bug());");
MVCR("<?php "
"function foo($a) {"
" return (int)$a;"
"}"
"function test() {"
" var_dump(foo(false));"
"}"
"test();");
return true;
}
bool TestCodeRun::TestSwitchStatement() {
MVCR("<?php class A {} $a = new A();"
"switch ($a) { "
"case 'foo': "
"default:"
"}");
MVCR("<?php class A {};"
"switch (new A()) { "
"case 'foo': "
"default:"
"}");
MVCR("<?php "
"function test() {"
" $a = 2;"
" switch ($a) {"
" case ++$a: var_dump('ok'); break;"
" case 2: var_dump('broken'); break;"
" case 3: var_dump('really broken'); break;"
" default: var_dump('fail'); break;"
" }"
" $a = 'b';"
" $b = 2;"
" switch ($$a) {"
" case ++$$a: var_dump('broken'); break;"
" case 2: var_dump('ok'); break;"
" case 3: var_dump('really broken'); break;"
" default: var_dump('fail'); break;"
" }"
"}"
"$a = 2;"
"switch ($a) {"
" case ++$a: var_dump('ok'); break;"
" case 2: var_dump('broken'); break;"
" case 3: var_dump('really broken'); break;"
" default: var_dump('fail'); break;"
"}"
"$a = 'b';"
"$b = 2;"
"switch ($$a) {"
" case ++$$a: var_dump('broken'); break;"
" case 2: var_dump('ok'); break;"
" case 3: var_dump('really broken'); break;"
" default: var_dump('fail'); break;"
"}"
"test();");
MVCR("<?php\n"
"function f_str($x) {\n"
" var_dump($x);\n"
" print ' goes to: ';\n"
" switch ($x) {\n"
" case -1:\n"
" print '-1';\n"
" break;\n"
" case 3:\n"
" print '3';\n"
" break;\n"
" case 0:\n"
" print '0';\n"
" break;\n"
" default:\n"
" print 'default';\n"
" break;\n"
" }\n"
"}\n"
"function f_bool($x) {\n"
" var_dump($x);\n"
" print ' goes to: ';\n"
" switch ($x) {\n"
" case -10:\n"
" print '-10';\n"
" break;\n"
" case 3:\n"
" print '3';\n"
" break;\n"
" case 0:\n"
" print '0';\n"
" break;\n"
" default:\n"
" print 'default';\n"
" break;\n"
" }\n"
"}\n"
"function f_dbl($x) {\n"
" var_dump($x);\n"
" print ' goes to: ';\n"
" switch ($x) {\n"
" case 5000000:\n"
" print '5000000';\n"
" break;\n"
" case 30:\n"
" print '30';\n"
" break;\n"
" case 0:\n"
" print '0';\n"
" break;\n"
" default:\n"
" print 'default';\n"
" break;\n"
" }\n"
"}\n"
"function f_dbl_notpe($x) {\n"
" var_dump($x);\n"
" print ' goes to: ';\n"
" switch ($x) {\n"
" case 5000000:\n"
" print '5000000';\n"
" break;\n"
" case 30:\n"
" print '30';\n"
" break;\n"
" case 0:\n"
" print '0';\n"
" break;\n"
" default:\n"
" print 'default';\n"
" break;\n"
" }\n"
"}\n"
"function f_int($x) {\n"
" var_dump($x);\n"
" print ' goes to: ';\n"
" switch ($x) {\n"
" case 5:\n"
" print '5';\n"
" break;\n"
" case 1:\n"
" print '1';\n"
" break;\n"
" case 0:\n"
" print '0';\n"
" break;\n"
" case 300:\n"
" print '300';\n"
" break;\n"
" default:\n"
" print 'default';\n"
" break;\n"
" }\n"
"}\n"
"function f($x) {\n"
" var_dump($x);\n"
" print ' goes to: ';\n"
" switch ($x) {\n"
" case 5:\n"
" print '5';\n"
" break;\n"
" case 1:\n"
" print '1';\n"
" break;\n"
" case 0:\n"
" print '0';\n"
" break;\n"
" default:\n"
" print 'default';\n"
" break;\n"
" }\n"
"}\n"
"function fcn($x) { if ($x) return 5; return 'bar'; }\n"
"function st($x) {\n"
" switch ($y = $x) {\n"
" case 0:\n"
" print '0';\n"
" }\n"
" switch (fcn(true)) {\n"
" case 3:\n"
" print '3';\n"
" break;\n"
" case 7:\n"
" case 5:\n"
" print '5 or 7';\n"
" break;\n"
" }\n"
" switch (++$x) {\n"
" case 1:\n"
" print '1';\n"
" }\n"
" switch ($x + $y + f(true)) {\n"
" case -30:\n"
" print '-30';\n"
" break;\n"
" default:\n"
" print 'default';\n"
" }\n"
" switch($x){}\n"
" switch($x){\n"
" default:\n"
" print 'default';\n"
" }\n"
"}\n"
"f(0);\n"
"f(-1);\n"
"f(1);\n"
"f(2);\n"
"f(true);\n"
"f(false);\n"
"f(null);\n"
"f(array());\n"
"f(1.0);\n"
"f('1abc');\n"
"f('3');\n"
"f('foo');\n"
"class M{}\n"
"f(new M());\n"
"f_str('0');\n"
"f_str('');\n"
"f_str('jazz');\n"
"f_str('-1');\n"
"f_str('1');\n"
"f_bool(true);\n"
"f_bool(false);\n"
"f_dbl(5000000.3920);\n"
"f_dbl(5000000.5);\n"
"f_dbl(5000000.5001);\n"
"f_dbl(5000000.0);\n"
"f_dbl(log(0));\n"
"f_dbl_notpe('5000000.3920');\n"
"f_dbl_notpe('5000000.5');\n"
"f_dbl_notpe('5000000.5001');\n"
"f_dbl_notpe('5000000.0');\n"
"f_int(0x7fffffffffffffff);\n"
"f_int(-120);\n"
"f_int(0);\n"
"st(10);\n");
MVCR("<?php\n"
"class Evil {\n"
" private $x;\n"
" public function __construct() { $this->x = 0; }\n"
" public function __toString() {\n"
" return sprintf(\"Evil%d\", $this->x++);\n"
" }\n"
"}\n"
"function f_1($x) {\n"
" switch ($x) {\n"
" case \"123\": print '\"123\"' . \"\n\"; break;\n"
" case \"4abc\": print '\"4abc\"' . \"\n\"; break;\n"
" default: print \"default\n\"; break;\n"
" case \"0\": print '\"0\"' . \"\n\"; break;\n"
" case \"\": print '\"\"' . \"\n\"; break; \n"
" case \"Evil4\": print '\"Evil4\"' . \"\n\"; break;\n"
" }\n"
"}\n"
"function f_2($x) {\n"
" var_dump($x); print \" goes to:\";\n"
" switch ($x) {\n"
" case \"foo\": print \"foo\n\"; break;\n"
" case \"1\": print \"1\n\"; break;\n"
" case \"2.0\": print \"2.0\n\"; break;\n"
" case \"2ab\": print \"2ab\n\"; break;\n"
" case \"3.212\": print \"3.212\n\"; break;\n"
" case \"0\": print \"0\n\"; break;\n"
" case \"\": print \"{empty str}\n\"; break;\n"
" default: print \"default\n\"; break;\n"
" }\n"
"}\n"
"function g_2($x) {\n"
" var_dump($x); print \" goes to:\";\n"
" switch ($x) {\n"
" case \"\": print \"{empty str}\n\"; break;\n"
" case \"0\": print \"0\n\"; break;\n"
" default: print \"default\n\"; break;\n"
" }\n"
"}\n"
"function h_2($x) {\n"
" var_dump($x); print \" goes to:\";\n"
" switch ($x) {\n"
" case \"3.0\": print \"3.0\n\"; break;\n"
" case \"3.0abc\": print \"3.0abc\n\"; break;\n"
" case \"3\": print \"3\n\"; break;\n"
" default: print \"\n\";\n"
" }\n"
"}\n"
"function f_3($x) {\n"
" switch ($x) {\n"
" default: print \"default\n\";\n"
" case \"bar\": print \"bar\n\";\n"
" case \"foo\": print \"foo\n\";\n"
" case \"baz\": print \"baz\n\";\n"
" }\n"
"}\n"
"f_1(\"\");\n"
"f_1(null);\n"
"f_1(false);\n"
"f_1(\"0\");\n"
"f_1(\"0eab\");\n"
"f_1(\"0.0\");\n"
"f_1(0.0);\n"
"f_1(0);\n"
"f_1(true);\n"
"f_1(false);\n"
"f_1(\"4abc\");\n"
"f_1(4);\n"
"f_1(\"4.0\");\n"
"f_1(new Evil());\n"
"f_2(1);\n"
"f_2(2);\n"
"f_2(2.0);\n"
"f_2(true);\n"
"f_2(false);\n"
"f_2(null);\n"
"f_2((object) null);\n"
"f_2(array());\n"
"f_2(3.21200);\n"
"g_2(0);\n"
"g_2(null);\n"
"g_2(false);\n"
"g_2(true);\n"
"h_2(\"3\");\n"
"h_2(\"3abc\");\n"
"h_2(\"3a\");\n"
"h_2(3);\n"
"h_2(3.0);\n"
"f_3(\"foo\");\n"
"f_3(\"bar\");\n"
"f_3(\"baz\");\n"
"f_3(\"def\");\n");
MVCR("<?php\n"
"function f($x) {\n"
" switch ($x) {\n"
" default:\n"
" print \"default-0\";\n"
" case \"foo\":\n"
" print \"foo-0\";\n"
" case \"3\":\n"
" print \"3-0\";\n"
" default:\n"
" print \"default-1\";\n"
" case \"3\":\n"
" print \"3-1\";\n"
" case \"foo\":\n"
" print \"foo-1\";\n"
" default:\n"
" print \"default-2\";\n"
" case \"bar\":\n"
" print \"bar\";\n"
" }\n"
"}\n"
"function g($x) {\n"
" switch ($x) {\n"
" case 'x': print 'x'; break;\n"
" case '0': print '0'; break;\n"
" }\n"
"}\n"
"f(\"foo\");\n"
"f(\"3\");\n"
"f(\"bar\");\n"
"f(null);\n"
"f(3);\n"
"f(0);\n"
"f(0.0);\n"
"f(3.0);\n"
"f(true);\n"
"f(false);\n"
"f(array());\n"
"f(new stdClass());\n"
"g(0);\n"
"g(0.0);\n");
{
HipHopSyntax w(this);
MVCRO("<?php\n"
"class X {\n"
" function foo() {\n"
" switch ($this) {\n"
" case 'foo': echo 'foo'; break;\n"
" case 'bar': echo 'bar'; break;\n"
" default: echo 'def';\n"
" }\n"
" }\n"
" function bar($arg) {\n"
" switch ($this) {\n"
" case $arg: echo 'arg'; break;\n"
" default: echo 'def';\n"
" }\n"
" }\n"
" function baz($arg) {\n"
" switch ($this) {\n"
" case $arg: echo 'arg'; break;\n"
" default: echo 'def';\n"
" }\n"
" yield $arg;\n"
" }\n"
"}\n"
"$x = new X;\n"
"$x->foo();\n"
"$x->bar(new stdClass);\n"
"$x->bar($x);\n"
"foreach ($x->baz($x) as $v) {\n"
" var_dump($v);\n"
"}\n",
"defdefargargobject(X)#1 (0) {\n"
"}\n");
}
MVCR("<?php\n"
"switch ($_POST) {\n"
"case array(): echo 'empty array'; break;\n"
"case $_GET: echo 'get'; break;\n"
"default: echo 'default';\n"
"}\n"
"switch ($GLOBALS) {\n"
"case array(): echo 'empty array'; break;\n"
"default: echo 'default';\n"
"}\n"
"function ret_true($x) { return true; }\n"
"switch ($GLOBALS) {\n"
"case ret_true($GLOBALS['foo'] = 10): echo '1'; break;\n"
"case array(); echo '2'; break;\n"
"default: echo '3';\n"
"}\n"
"var_dump($foo);\n");
MVCR("<?php\n"
"function id($x) { return $x; }\n"
"function ret_false($x) { return false; }\n"
"function f($x) {\n"
" switch ($x) {\n"
" case ret_false($x = 32); echo 'fail'; break;\n"
" case id($x = 5): echo 'here'; break;\n"
" default: echo 'default';\n"
" }\n"
"}\n"
"f(32);\n");
return true;
}
bool TestCodeRun::TestExtString() {
MVCR("<?php "
"var_dump(strtr(\"\", \"ll\", \"a\"));"
"var_dump(strtr(\"hello\", \"\", \"a\"));"
"var_dump(strtr(\"hello\", \"ll\", \"a\"));"
"var_dump(strtr(\"hello\", array(\"\" => \"a\")));"
"var_dump(strtr(\"hello\", array(\"ll\" => \"a\")));");
MVCR("<?php "
"var_dump(explode('', ''));"
"$str = 'Hello Friend';"
"var_dump(str_split($str, -3));"
"var_dump(chunk_split('-=blender=-', -3, '-=blender=-')); "
"var_dump(strpbrk('hello', ''));"
"var_dump(substr_count('hello', ''));"
"var_dump(substr_count('hello', 'o', -1));"
"var_dump(substr_count('hello', 'o', 2, -1));"
"var_dump(substr_count('hello', 'o', 2, 100));"
"var_dump(count_chars('hello', 100));"
"var_dump(str_word_count('hello', 100));"
"var_dump(strtr('hello', 100));"
"var_dump(implode('abcd', 'abcd'));");
MVCR("<?php "
"error_reporting(0);"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', array(0)));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', array(0), 3));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', array(0), 1.0));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', array(0), null));"
"$obj = new stdClass();"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', 0, $obj));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', '0', '1.0'));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', '0.0', 1.0));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', '0.0', 1));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob', 0.0, '1'));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', 'bob',"
" array(0), array(1)));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', array('bob'),"
" array(0), array(3,4)));"
"var_dump(substr_replace('ABCDEFGH:/MNRPQR/', array('bob'),"
" array(0), array(3)));"
"var_dump(substr_replace(array('ABCDEFGH:/MNRPQR/'), array(),"
" array(0,1), array(3, 4)));"
"var_dump(substr_replace(array('ABCDEFGH:/MNRPQR/'), array('bob'),"
" array(0,1), array(3)));"
"var_dump(substr_replace(array('ABCDEFGH:/MNRPQR/'),"
" array('bob', 'cat'), 0));"
"var_dump(substr_replace(array('ABCDEFGH:/MNRPQR/'),"
" array('bob'), array(0,1)));"
"var_dump(substr_replace('abc', 'xyz', 3, 0));"
"var_dump(sscanf(\"SN/2350001\", \"SN/%d\"));"
"var_dump(sscanf(\"SN/2350001\", \"SN/%d\", $out));"
"var_dump($out);"
"var_dump(sscanf(\"SN/abc\", \"SN/%d\", $out));"
"var_dump($out);"
"var_dump(sscanf(\"30\", \"%da\", $out));"
"var_dump($out);"
"var_dump(sscanf(\"-\", \"%da\", $out));"
"var_dump($out);");
MVCR("<?php\n"
"preg_replace(\"/(..)/e\", 'var_dump(\"$1\")', '\"\"');\n");
MVCR("<?php\n"
"var_dump(str_replace(array(65), array('a'), 'axAX'));\n"
"var_dump(str_ireplace(array(65), array('a'), 'axAX'));\n"
"echo \"**************************\\n\";\n"
"var_dump(strpos('aA', 65));\n"
"var_dump(strpos('aA', 'A'));\n"
"var_dump(strpos('aAaXA', 'A', 0));\n"
"var_dump(strpos('aAaXA', 'A', 1));\n"
"var_dump(strpos('aAaXA', 'A', 2));\n"
"var_dump(strpos('aAaXA', 'A', 3));\n"
"var_dump(strpos('aAaXA', 'A', 4));\n"
"var_dump(strpos('aAaXA', 'A', 5));\n"
"var_dump(strpos('aAaXA', 'A', 6));\n"
"var_dump(strpos('aAaXA', 'A', -1));\n"
"var_dump(strpos('aAaXA', 'A', -2));\n"
"var_dump(strpos('aAaXA', 'A', -3));\n"
"var_dump(strpos('aAaXA', 'A', -4));\n"
"var_dump(strpos('aAaXA', 'A', -5));\n"
"var_dump(strpos('aAaXA', 'A', -6));\n"
"echo \"**************************\\n\";\n"
"var_dump(strrpos('aA', 65));\n"
"var_dump(strrpos('aA', 'A'));\n"
"var_dump(strrpos('aAaXA', 'A', 0));\n"
"var_dump(strrpos('aAaXA', 'A', 1));\n"
"var_dump(strrpos('aAaXA', 'A', 2));\n"
"var_dump(strrpos('aAaXA', 'A', 3));\n"
"var_dump(strrpos('aAaXA', 'A', 4));\n"
"var_dump(strrpos('aAaXA', 'A', 5));\n"
"var_dump(strrpos('aAaXA', 'A', 6));\n"
"var_dump(strrpos('aAaXA', 'A', -1));\n"
"var_dump(strrpos('aAaXA', 'A', -2));\n"
"var_dump(strrpos('aAaXA', 'A', -3));\n"
"var_dump(strrpos('aAaXA', 'A', -4));\n"
"var_dump(strrpos('aAaXA', 'A', -5));\n"
"var_dump(strrpos('aAaXA', 'A', -6));\n"
"echo \"**************************\\n\";\n"
"var_dump(stripos('aA', 65));\n"
"var_dump(stripos('aA', 'A'));\n"
"var_dump(stripos('aAaXA', 'A', 0));\n"
"var_dump(stripos('aAaXA', 'A', 1));\n"
"var_dump(stripos('aAaXA', 'A', 2));\n"
"var_dump(stripos('aAaXA', 'A', 3));\n"
"var_dump(stripos('aAaXA', 'A', 4));\n"
"var_dump(stripos('aAaXA', 'A', 5));\n"
"var_dump(stripos('aAaXA', 'A', 6));\n"
"var_dump(stripos('aAaXA', 'A', -1));\n"
"var_dump(stripos('aAaXA', 'A', -2));\n"
"var_dump(stripos('aAaXA', 'A', -3));\n"
"var_dump(stripos('aAaXA', 'A', -4));\n"
"var_dump(stripos('aAaXA', 'A', -5));\n"
"var_dump(stripos('aAaXA', 'A', -6));\n"
"echo \"**************************\\n\";\n"
"var_dump(strripos('aA', 65));\n"
"var_dump(strripos('aA', 'A'));\n"
"var_dump(strripos('aAaXA', 'A', 0));\n"
"var_dump(strripos('aAaXA', 'A', 1));\n"
"var_dump(strripos('aAaXA', 'A', 2));\n"
"var_dump(strripos('aAaXA', 'A', 3));\n"
"var_dump(strripos('aAaXA', 'A', 4));\n"
"var_dump(strripos('aAaXA', 'A', 5));\n"
"var_dump(strripos('aAaXA', 'A', 6));\n"
"var_dump(strripos('aAaXA', 'A', -1));\n"
"var_dump(strripos('aAaXA', 'A', -2));\n"
"var_dump(strripos('aAaXA', 'A', -3));\n"
"var_dump(strripos('aAaXA', 'A', -4));\n"
"var_dump(strripos('aAaXA', 'A', -5));\n"
"var_dump(strripos('aAaXA', 'A', -6));\n");
return true;
}
bool TestCodeRun::TestExtArray() {
MVCR("<?php "
"error_reporting(0);"
"var_dump(range('', '', 1));"
"var_dump(range('', '', -1));"
"var_dump(range('9', '10', -1));"
"var_dump(range(9, 10, -1));"
"var_dump(range(9, 10, -1.5));"
"var_dump(range(9, 10, 33333333.33));"
"var_dump(range(9, 10, -33333333.33));"
"var_dump(range(9223372036854775807, 9223372036854775805, -1));"
"var_dump(range(9223372036854775807, 9223372036854775805,"
" 9223372036854775807));"
"var_dump(range(9223372036854775807, 9223372036854775805,"
" -9223372036854775807));"
"var_dump(range(9223372036854775807, 9223372036854775805,"
" 2147483648));"
"var_dump(range(9223372036854775807, 9223372036854775805,"
" -2147483648));"
"var_dump(range('9', '10', '-1'));"
"var_dump(range('9', '10', '-1.5'));"
"var_dump(range('9', '10', '33333333.33'));"
"var_dump(range('9', '10', '-33333333.33'));"
"var_dump(range('9223372036854775807', '9223372036854775805', '-1'));"
"var_dump(range('9223372036854775807', '9223372036854775805',"
" '9223372036854775807'));"
"var_dump(range('9223372036854775807', '9223372036854775805',"
" '-9223372036854775807'));"
"var_dump(range(null, null, -2.5));"
"var_dump(range(null, null, 3.5));"
"var_dump(range(null, null, null));"
"var_dump(range(3.5, -4.5, null));");
MVCR("<?php "
"var_dump(array_fill(-2, -2, 'pear'));"
"var_dump(array_combine(array(1, 2), array(3)));"
"var_dump(array_combine(array(), array()));"
"var_dump(array_chunk(1));"
"var_dump(array_chunk(array()));"
"$a = array(1, 2);"
"var_dump(asort($a, 100000));");
MVCR("<?php\n"
"function f(&$val,$key) {\n"
" echo \"k=$key v=$val\\n\";\n"
" $val = $val + 1;\n"
"}\n"
"$arr = array(0,1,2);\n"
"array_walk($arr,'f');\n"
"var_dump($arr);\n");
MVCR("<?php\n"
"function f($val,$key) {\n"
" echo \"k=$key v=$val\\n\";\n"
"}\n"
"$arr = array(0,1,2);\n"
"array_walk($arr,'f');\n");
MVCR("<?php\n"
"$arr = array(0,1,2);\n"
"function f($val,$key) {\n"
" global $arr;\n"
" echo \"k=$key v=$val\\n\";\n"
" if ($key == 0) {\n"
" unset($arr[1]);\n"
" }\n"
"}\n"
"array_walk($arr,'f');\n"
"var_dump($arr);\n");
MVCR("<?php\n"
"$a = array('foo'=>array('bar'=>1));\n"
"function fix(&$v, $k) { $v *= 2; }\n"
"array_walk_recursive($a, 'fix');\n"
"var_dump($a['foo']);\n");
MVCR("<?php "
"function xsort(&$a) {"
" $b = null;"
" $b->foo =& $a;"
" var_dump(is_object($b));"
" $b = false;"
" $b[0] =& $a;"
" uksort($a, function ($i, $j) use(&$b) {"
" if ($b[0][$i] == $b[0][$j]) return 0;"
" return $b[0][$i] < $b[0][$j] ? -1 : 1;"
" });"
"}"
"function test($x) {"
" $a = array(220,250,240,$x);"
" xsort($a);"
" var_dump($a);"
"}"
"test(230);");
MVCR("<?php "
"function cmp($a, $b) {"
" throw new Exception('Surprise!');"
"}"
"function test() {"
" $a = array(1,2,3);"
" try {"
" usort($a, 'cmp');"
" var_dump('unreached');"
" } catch (Exception $e) {"
" var_dump($e->getMessage());"
" }"
"}"
"test();");
return true;
}
bool TestCodeRun::TestExtFile() {
MVCR("<?php "
"error_reporting(0);"
"$fp = fopen('/tmp/lock.txt', 'w');"
"fclose($fp);"
"$fp = fopen('/tmp/lock.txt', 'r+');"
"var_dump(flock($fp, 0xf0));"
"fclose($fp);");
return true;
}
bool TestCodeRun::TestExtDate() {
MVCR("<?php "
"error_reporting(0);"
"var_dump(idate('@@'));"
"var_dump(idate('@'));"
"var_dump(date(''));"
"var_dump(date('@'));"
"var_dump(strftime(''));"
"setlocale(LC_ALL, 'nl_NL');"
"var_dump(strftime('%p'));");
return true;
}
bool TestCodeRun::TestExtImage() {
MVCR("<?php "
"$data = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'"
" . 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'"
" . 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'"
" . '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';"
"$data = base64_decode($data);"
""
"$im = imagecreatefromstring($data);"
"if ($im !== false) {"
" header('Content-Type: image/png');"
" imagepng($im);"
" imagedestroy($im);"
"}"
"else {"
" echo 'An error occurred.';"
"}");
MVCR("<?php "
"header ('Content-type: image/png');"
"$im = imagecreatetruecolor(120, 20);"
"$text_color = imagecolorallocate($im, 233, 14, 91);"
"imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);"
"imagepng($im);"
"imagedestroy($im);");
MVCR("<?php "
"// Create a 55x30 image"
"$im = imagecreatetruecolor(55, 30);"
"$red = imagecolorallocate($im, 255, 0, 0);"
"$black = imagecolorallocate($im, 0, 0, 0);"
""
"// Make the background transparent"
"imagecolortransparent($im, $black);"
""
"// Draw a red rectangle"
"imagefilledrectangle($im, 4, 4, 50, 25, $red);"
""
"// Save the image"
"imagepng($im, './imagecolortransparent.png');"
"imagedestroy($im);");
MVCR("<?php "
"$image = imagecreatefromgif('test/images/php.gif');"
""
"$emboss = array(array(2, 0, 0), array(0, -1, 0), array(0, 0, -1));"
"imageconvolution($image, $emboss, 1, 127);"
""
"header('Content-Type: image/png');"
"ob_start();imagepng($image, null, 9);"
"var_dump(substr(ob_get_clean(),0,10));");
MVCR("<?php "
"$image = imagecreatetruecolor(180,40);"
""
"// Writes the text and apply a gaussian blur on the image"
"imagestring($image, 5, 10, 8, 'Gaussian Blur Text', 0x00ff00);"
"$gaussian = array(array(1.0, 2.0, 1.0),"
" array(2.0, 4.0, 2.0),"
" array(1.0, 2.0, 1.0));"
"imageconvolution($image, $gaussian, 16, 0);"
""
"// Rewrites the text for comparison"
"imagestring($image, 5, 10, 18, 'Gaussian Blur Text', 0x00ff00);"
""
"header('Content-Type: image/png');"
"imagepng($image, null, 9);");
MVCR("<?php "
"// File and new size"
"$filename = 'test/images/simpletext.jpg';"
"$percent = 0.5;"
"// Content type"
"header('Content-type: image/jpeg');"
"// Get new sizes"
"list($width, $height) = getimagesize($filename, $nfo);"
"var_dump($nfo);"
"$newwidth = $width * $percent;"
"$newheight = $height * $percent;"
"// Load"
"$thumb = imagecreatetruecolor($newwidth, $newheight);"
"$source = imagecreatefromjpeg($filename);"
"// Resize"
"imagecopyresized($thumb, $source, 0, 0, 0, 0,"
" $newwidth, $newheight, $width, $height);"
"// Output"
"imagejpeg($thumb);");
MVCR("<?php "
"// create image"
"$image = imagecreatetruecolor(100, 100);"
""
"// allocate some solors"
"$white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);"
"$gray = imagecolorallocate($image, 0xC0, 0xC0, 0xC0);"
"$darkgray = imagecolorallocate($image, 0x90, 0x90, 0x90);"
"$navy = imagecolorallocate($image, 0x00, 0x00, 0x80);"
"$darknavy = imagecolorallocate($image, 0x00, 0x00, 0x50);"
"$red = imagecolorallocate($image, 0xFF, 0x00, 0x00);"
"$darkred = imagecolorallocate($image, 0x90, 0x00, 0x00);"
""
"// make the 3D effect"
"for ($i = 60; $i > 50; $i--) {"
" imagefilledarc($image, 50, $i, 100, 50, 0, 45,"
" $darknavy, IMG_ARC_PIE);"
" imagefilledarc($image, 50, $i, 100, 50, 45, 75,"
" $darkgray, IMG_ARC_PIE);"
" imagefilledarc($image, 50, $i, 100, 50, 75, 360,"
" $darkred, IMG_ARC_PIE);"
"}"
""
"imagefilledarc($image, 50, 50, 100, 50, 0, 45, $navy, IMG_ARC_PIE);"
"imagefilledarc($image, 50, 50, 100, 50, 45, 75 , $gray, IMG_ARC_PIE);"
"imagefilledarc($image, 50, 50, 100, 50, 75, 360 , $red, IMG_ARC_PIE);"
""
""
"// flush image"
"header('Content-type: image/png');"
"imagepng($image);"
"imagedestroy($image);");
MVCR("<?php "
"// Create a new image instance"
"$im = imagecreatetruecolor(100, 100);"
""
"// Make the background white"
"imagefilledrectangle($im, 0, 0, 99, 99, 0xFFFFFF);"
""
"// Draw a text string on the image"
"imagestring($im, 3, 40, 20, 'GD Library', 0xFFBA00);"
""
"// Output the image to browser"
"header('Content-type: image/gif');"
""
"imagegif($im);"
"imagedestroy($im);");
MVCR("<?php "
"$png = imagecreatefrompng('test/images/smile.happy.png');"
""
"// Save the image as a GIF"
"imagegif($png, '/tmp/php.gif');"
""
"// Free from memory"
"imagedestroy($png);");
MVCR("<?php "
"// Create an image instance"
"$im = imagecreatefromgif('test/images/php.gif');"
""
"// Enable interlancing"
"imageinterlace($im, true);"
""
"// Save the interfaced image"
"imagegif($im, './php_interlaced.gif');"
"imagedestroy($im);");
MVCR("<?php "
"// Create a blank image and add some text"
"$im = imagecreatetruecolor(120, 20);"
"$text_color = imagecolorallocate($im, 233, 14, 91);"
"imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);"
""
"// Save the image as 'simpletext.jpg'"
"imagejpeg($im, 'simpletext.jpg');"
""
"// Free up memory"
"imagedestroy($im);");
MVCR("<?php "
"// Create a blank image and add some text"
"$im = imagecreatetruecolor(120, 20);"
"$text_color = imagecolorallocate($im, 233, 14, 91);"
"imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);"
""
"// Set the content type header - in this case image/jpeg"
"header('Content-type: image/jpeg');"
""
"// Skip the filename parameter using NULL, then set the quality to 75%"
"imagejpeg($im, NULL, 75);"
""
"// Free up memory"
"imagedestroy($im);");
MVCR("<?php "
"// Create a blank image and add some text"
"$im = imagecreatetruecolor(120, 20);"
"$text_color = imagecolorallocate($im, 233, 14, 91);"
"imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);"
""
"// Set the content type header - in this case image/jpeg"
"header('Content-type: image/jpeg');"
""
"// Output the image"
"imagejpeg($im);"
""
"// Free up memory"
"imagedestroy($im);");
MVCR("<?php "
"// Create a 100*30 image"
"$im = imagecreate(100, 30);"
""
"// White background and blue text"
"$bg = imagecolorallocate($im, 255, 255, 255);"
"$textcolor = imagecolorallocate($im, 0, 0, 255);"
""
"// Write the string at the top left"
"imagestring($im, 5, 0, 0, 'Hello world!', $textcolor);"
""
"// Output the image"
"header('Content-type: image/png');"
""
"imagepng($im);"
"imagedestroy($im);");
MVCR("<?php "
"var_dump(image_type_to_mime_type(IMAGETYPE_GIF));"
"var_dump(image_type_to_mime_type(IMAGETYPE_JPEG));"
"var_dump(image_type_to_mime_type(IMAGETYPE_PNG));"
"var_dump(image_type_to_mime_type(IMAGETYPE_SWF));"
"var_dump(image_type_to_mime_type(IMAGETYPE_PSD));"
"var_dump(image_type_to_mime_type(IMAGETYPE_BMP));"
"var_dump(image_type_to_mime_type(IMAGETYPE_TIFF_II));"
"var_dump(image_type_to_mime_type(IMAGETYPE_TIFF_MM));"
"var_dump(image_type_to_mime_type(IMAGETYPE_JPC));"
"var_dump(image_type_to_mime_type(IMAGETYPE_JP2));"
"var_dump(image_type_to_mime_type(IMAGETYPE_JPX));"
"var_dump(image_type_to_mime_type(IMAGETYPE_JB2));"
"var_dump(image_type_to_mime_type(IMAGETYPE_SWC));"
"var_dump(image_type_to_mime_type(IMAGETYPE_IFF));"
"var_dump(image_type_to_mime_type(IMAGETYPE_WBMP));"
"var_dump(image_type_to_mime_type(IMAGETYPE_XBM));"
"var_dump(image_type_to_mime_type(IMAGETYPE_ICO));");
// The system libpng is a different version than what may be
// available in other externals trees (and can therefore produce
// different images). Since a local version of PHP (which uses
// system libs) will be used to generate a comparison point,
// only run this test if HPHP is built against a native externals
// tree. This also applies to the gated libjpeg test below.
#ifdef EXTERNALS_NATIVE
MVCR("<?php "
"function foo($text, $fsize) {"
""
" $font = 'test/tahoma.ttf';"
" $font_angle = 0;"
" $background1 = 125;"
" $background2 = 125;"
" $background3 = 125;"
" $font1 = 60;"
" $font2 = 60;"
" $font3 = 60;"
""
" $bbox = imagettfbbox($fsize, $font_angle, $font, $text);"
" $text_width = abs(max($bbox[2],"
" $bbox[4]) - min($bbox[0], $bbox[6]));"
" $text_height = abs(max($bbox[7],"
" $bbox[5]) - min($bbox[1], $bbox[3]));"
" $image_width = $text_width + 2;"
""
" $image_height = max($text_height, $fsize) + 2;"
""
" $image = imagecreate($image_width, $image_height);"
""
" imagecolorallocate($image,"
" $background1,"
" $background2,"
" $background3);"
""
" $black = imagecolorallocate($image,"
" $font1,"
" $font2,"
" $font3);"
""
" $y = $fsize + 1;"
" imagettftext($image, $fsize, $font_angle, 0,"
" $y, $black, $font, $text);"
" ob_start();imagepng($image, null, 9);"
" var_dump(substr(ob_get_clean(),0,10));"
" imagedestroy($image);"
"}"
""
"$text = 'foobar@yahoo.com';"
"$fsize = '9.8';"
"foo($text, $fsize);");
#endif
MVCR("<?php "
"for ($i = 0; $i < 100000; $i++) {"
" $str = exif_tagname($i);"
" if ($str) {"
" echo \"$i: $str\\n\";"
" }"
"}");
MVCR("<?php "
"$filename = 'test/images/test1pix.jpg';"
"$image = exif_thumbnail($filename, $width, $height, $type);"
"if ($image!==false) {"
" header('Content-type: ' .image_type_to_mime_type($type));"
" var_dump($width, $height, $type);"
"} else {"
" echo 'No thumbnail available';"
"}");
#ifdef EXTERNALS_NATIVE
MVCR("<?php "
"$filename = 'test/images/simpletext.jpg';"
"$degrees = 90;"
"header('Content-type: image/jpeg');"
"$source = imagecreatefromjpeg($filename);"
"$rotate = imagerotate($source, $degrees, 0);"
"imagejpeg($rotate);");
#endif
MVCR("<?php "
"$exif = exif_read_data('test/images/246x247.png');"
"print_r($exif);"
"$exif = exif_read_data('test/images/php.gif');"
"print_r($exif);"
"$exif = exif_read_data('test/images/simpletext.jpg');"
"print_r($exif);"
"$exif = exif_read_data('test/images/smile.happy.png');"
"print_r($exif);"
"$exif = exif_read_data('test/images/test1pix.jpg');"
"print_r($exif);"
"$exif = exif_read_data('test/images/test2.jpg');"
"print_r($exif);");
return true;
}
bool TestCodeRun::TestExtSplFile() {
MVCR("<?php "
"$info = new SplFileInfo('test');"
"if (!$info->isFile()) {"
" echo $info->getRealPath();"
"}"
"$info = new SplFileInfo('test/test_code_run.cpp');"
"var_dump($info->getbaseName());"
"var_dump($info->getbaseName('.cpp'));"
"echo 'Last changed at ' . date('g:i a', $info->getCTime());"
"var_dump($info->getGroup());"
"var_dump($info->getInode());"
"var_dump($info->getMTime());"
"var_dump($info->getOwner());"
"var_dump($info->getPerms());"
"var_dump($info->getSize());"
"var_dump($info->getType());"
"var_dump($info->isDir());"
"var_dump($info->isFile());"
"var_dump($info->isLink());"
"var_dump($info->isReadable());"
"var_dump($info->isWritable());");
MVCR("<?php "
"$info = new SplFileInfo('test');"
"var_dump($info->getRealPath());"
"var_dump($info->getPath());"
"var_dump($info->getPathName());"
"$info = new SplFileInfo('test/');"
"var_dump($info->getRealPath());"
"var_dump($info->getPath());"
"var_dump($info->getPathName());"
"$info = new SplFileInfo('test//../test');"
"var_dump($info->getRealPath());"
"var_dump($info->getPath());"
"var_dump($info->getPathName());"
"$p=realpath('test/..');"
"$info = new SplFileInfo($p.'/test_link');"
"var_dump($info->getLinkTarget());"
"var_dump($info->getRealPath());"
"var_dump($info->getPath());"
"var_dump($info->getPathName());");
MVCR("<?php "
"$info = new SplFileInfo('does-not-exist-will-fail-on-getLinkTarget');"
"//readlink('does-not-throw-but-warns');"
"try{"
" $info->getLinkTarget();"
"}"
"catch (Exception $e) {"
" echo 'Caught exception: ', $e->getMessage(), \"\\n\";"
" return;"
"}"
"echo \"failed to throw\\n\";"
" return true;"
"}");
return true;
}
bool TestCodeRun::TestExtIterator() {
MVCR("<?php "
"$files = array();"
"foreach (new DirectoryIterator('test/') as $file) {"
" $files[] = $file;"
"}"
"var_dump(count($files));"
"$dir = new DirectoryIterator(dirname('test/'));"
"foreach ($dir as $fileinfo) {"
" if (!$fileinfo->isDot()) {"
" var_dump($fileinfo->getFilename());"
" }"
"}"
"$iterator = new DirectoryIterator(\"test\");"
"foreach ($iterator as $fileinfo) {"
" if ($fileinfo->isFile()) {"
" echo \"BEGIN: \" . $fileinfo->getFilename() . \"\\n\";"
" echo $fileinfo->getCTime() . \"\\n\";"
" echo $fileinfo->getBasename() . \"\\n\";"
" echo $fileinfo->getBasename('.cpp') . \"\\n\";"
" echo $fileinfo->getGroup() . \"\\n\";"
" echo $fileinfo->getInode() . \"\\n\";"
" echo $fileinfo->getMTime() . \"\\n\";"
" echo $fileinfo->getOwner() . \"\\n\";"
" echo $fileinfo->getPerms() . \"\\n\";"
" echo $fileinfo->getSize() . \"\\n\";"
" echo $fileinfo->getType() . \"\\n\";"
" echo $fileinfo->isDir() . \"\\n\";"
" echo $fileinfo->isDot() . \"\\n\";"
" echo $fileinfo->isExecutable() . \"\\n\";"
" echo $fileinfo->isLink() . \"\\n\";"
" echo $fileinfo->isReadable() . \"\\n\";"
" echo $fileinfo->isWritable() . \"\\n\";"
" echo \"END\" . \"\\n\";"
" }"
"}"
"$iterator = new RecursiveDirectoryIterator(\"test\");"
"foreach ($iterator as $fileinfo) {"
" if ($fileinfo->isFile()) {"
" echo $fileinfo->getFilename() . \"\\n\";"
" echo $fileinfo->getCTime() . \"\\n\";"
" echo $fileinfo->getBasename() . \"\\n\";"
" echo $fileinfo->getBasename('.cpp') . \"\\n\";"
" echo $fileinfo->getFilename() . \"\\n\";"
" echo $fileinfo->getGroup() . \"\\n\";"
" echo $fileinfo->getInode() . \"\\n\";"
" echo $fileinfo->getMTime() . \"\\n\";"
" echo $fileinfo->getOwner() . \"\\n\";"
" echo $fileinfo->getPerms() . \"\\n\";"
" echo $fileinfo->getSize() . \"\\n\";"
" echo $fileinfo->getType() . \"\\n\";"
" echo $fileinfo->isDir() . \"\\n\";"
" echo $fileinfo->isExecutable() . \"\\n\";"
" echo $fileinfo->isLink() . \"\\n\";"
" echo $fileinfo->isReadable() . \"\\n\";"
" echo $fileinfo->isWritable() . \"\\n\";"
" }"
"}");
MVCR("<?php "
"$dir = new DirectoryIterator('test');"
"while($dir->valid()) {"
" if(!$dir->isDot()) {"
" print $dir->current().\"\\n\";"
" }"
" $dir->next();"
"}");
MVCR("<?php "
"$ite=new RecursiveDirectoryIterator('test/');"
"$bytestotal=0;"
"$nbfiles=0;"
"foreach ($ite as $filename=>$cur) {"
" $filesize=$cur->getSize();"
" $bytestotal+=$filesize;"
" $nbfiles++;"
" echo \"$filename => $filesize\\n\";"
"}"
"$bytestotal=number_format($bytestotal);"
"echo \"Total: $nbfiles files, $bytestotal bytes\\n\";");
MVCR("<?php "
"$ite=new RecursiveDirectoryIterator('test/');"
"$bytestotal=0;"
"$nbfiles=0;"
"foreach (new RecursiveIteratorIterator($ite) as $filename=>$cur) {"
" if (substr($filename,-1)=='.') continue;"
" $filesize=$cur->getSize();"
" $bytestotal+=$filesize;"
" $nbfiles++;"
" echo \"$filename => $filesize\\n\";"
"}"
"$bytestotal=number_format($bytestotal);"
"echo \"Total: $nbfiles files, $bytestotal bytes\\n\";");
MVCR("<?php "
"$path = \"test/\";"
"foreach (new RecursiveIteratorIterator("
" new RecursiveDirectoryIterator($path,"
" RecursiveDirectoryIterator::KEY_AS_PATHNAME),"
" RecursiveIteratorIterator::CHILD_FIRST) as $file => $info) {"
" if ($info->isDir() && substr($file,-1)!='.') {"
" echo $file.\"\\n\";"
" }"
"}");
MVCR("<?php "
"$directory = \"test\";"
"$fileSPLObjects = new RecursiveIteratorIterator("
" new RecursiveDirectoryIterator($directory),"
" RecursiveIteratorIterator::SELF_FIRST);"
"foreach( $fileSPLObjects as $fullFileName => $fileSPLObject ) {"
" if (substr($fullFileName,-1)=='.') continue;"
" print $fullFileName . \" \" .$fileSPLObject->getFilename(). \"\\n\";"
"}"
"$fileSPLObjects = new RecursiveIteratorIterator("
" new RecursiveDirectoryIterator($directory),"
" RecursiveIteratorIterator::CHILD_FIRST);"
"foreach( $fileSPLObjects as $fullFileName => $fileSPLObject ) {"
" if (substr($fullFileName,-1)=='.') continue;"
" print $fullFileName . \" \" .$fileSPLObject->getFilename(). \"\\n\";"
"}"
"$fileSPLObjects = new RecursiveIteratorIterator("
" new RecursiveDirectoryIterator($directory),"
" RecursiveIteratorIterator::LEAVES_ONLY);"
"foreach( $fileSPLObjects as $fullFileName => $fileSPLObject ) {"
" if (substr($fullFileName,-1)=='.') continue;"
" print $fullFileName . \" \" .$fileSPLObject->getFilename(). \"\\n\";"
"}"
"// invalid mode -100"
"$fileSPLObjects = new RecursiveIteratorIterator("
" new RecursiveDirectoryIterator($directory), -100);"
"foreach( $fileSPLObjects as $fullFileName => $fileSPLObject ) {"
" if (substr($fullFileName,-1)=='.') continue;"
" print $fullFileName . \" \" .$fileSPLObject->getFilename(). \"\\n\";"
"}");
MVCR("<?php "
"function getFiles(&$rdi,$depth=0) {"
" if (!is_object($rdi)) return;"
" for ($rdi->rewind();$rdi->valid();$rdi->next()) {"
" if ($rdi->isDot()) continue;"
" if ($rdi->isDir() || $rdi->isFile()) {"
" for ($i = 0; $i<=$depth;++$i) echo \" \";"
" echo $rdi->current().\"\\n\";"
" if ($rdi->hasChildren()) getFiles($rdi->getChildren(),1+$depth);"
" }"
" }"
"}"
"getFiles(new RecursiveDirectoryIterator('test'));");
MVCR("<?php "
"try {"
" $y = new RecursiveDirectoryIterator('/fake_path');"
" $z = new RecursiveIteratorIterator($y);"
" $z->next();"
"} catch (UnexpectedValueException $e) {"
"}"
"var_dump('ok');");
MVCR("<?php\n"
"class EvensOnly extends FilterIterator {\n"
" function __construct($it) {\n"
" parent::__construct($it);\n"
" }\n"
" public function accept() {\n"
" return $this->getInnerIterator()->current() % 2 == 0;\n"
" }\n"
"}\n"
"$i = new EvensOnly(new ArrayIterator(range(0, 10)));\n"
"foreach ($i as $v) {\n"
" var_dump($v);\n"
"}\n");
MVCR("<?php\n"
"class Proxy extends IteratorIterator {\n"
" function __construct($i) {\n"
" parent::__construct($i);\n"
" }\n"
"}\n"
"$i = new Proxy(new ArrayIterator(range(0, 5)));\n"
"foreach ($i as $v) { var_dump($v); }\n");
return true;
}
bool TestCodeRun::TestExtSoap() {
MVCR("<?php "
"function add($a, $b) { return $a + $b; }"
"$server = new SoapServer(NULL, array('uri' => 'http://test-uri'));"
"$str = '<?xml version=\"1.0\" '."
" 'encoding=\"ISO-8859-1\"?>'."
" '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle='."
" '\"http://schemas.xmlsoap.org/soap/encoding/\"'."
" ' xmlns:SOAP-ENV='."
" '\"http://schemas.xmlsoap.org/soap/envelope/\"'."
" ' xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"'."
" ' xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"'."
" ' xmlns:si=\"http://soapinterop.org/xsd\"><SOAP-ENV:Body>'."
" '<ns1:Add xmlns:ns1=\"http://testuri.org\">'."
" '<x xsi:type=\"xsd:hexBinary\">16</x>'."
" '<y xsi:type=\"xsd:hexBinary\">21</y>'."
" '</ns1:Add> </SOAP-ENV:Body></SOAP-ENV:Envelope>';"
"$server->addFunction('Add');"
"$server->handle($str);");
MVCR("<?php "
"class MySoap extends SoapClient {"
" public $pub = 1;"
" public function __doRequest("
" $request, $location, $action, $version, $one_way=0) {"
" $rp = parent::__doRequest($request, $location,"
" $action, $version, $one_way);"
" return $rp;"
" }"
"}"
"function test($options) {"
" return new MySoap('test/test.wsdl', $options);"
"}"
"var_dump(test(array('foo' => 'bar'))->pub);");
return true;
}
bool TestCodeRun::TestExtCollator() {
MVCR("<?php "
"function ut_run($mainFunc) {\n"
" $GLOBALS['oo-mode'] = true;\n"
" $oo_result = $mainFunc();\n"
" $GLOBALS['oo-mode'] = false;\n"
" $proc_result = $mainFunc();\n"
" if($proc_result !== $oo_result) {\n"
" echo \"ERROR: OO- and procedural APIs produce different results!\\n\";\n"
" echo \"OO API output:\\n\";\n"
" echo str_repeat( '=', 78 ) . \"\\n\";\n"
" echo $oo_result;\n"
" echo str_repeat( '=', 78 ) . \"\\n\";\n"
" echo \"procedural API output:\\n\";\n"
" echo str_repeat( '=', 78 ) . \"\\n\";\n"
" echo $proc_result;\n"
" echo str_repeat( '=', 78 ) . \"\\n\";\n"
" return;\n"
" }\n"
" echo $oo_result;\n"
"}\n"
"function dump($val) {\n"
" return var_export( $val, true );\n"
"}\n"
"function ut_coll_create( $locale )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? Collator::create( $locale ) : collator_create( $locale );\n"
"}\n"
"function ut_coll_compare( $coll, $str1, $str2 )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? \n"
" $coll->compare( $str1, $str2 ) : collator_compare( $coll, $str1, $str2 );\n"
"}\n"
"function ut_coll_sort_with_sort_keys( $coll, &$arr )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? \n"
" $coll->sortWithSortKeys( $arr ) : collator_sort_with_sort_keys( $coll, $arr );\n"
"}\n"
"function ut_coll_sort( $coll, &$arr, $sort_flag = Collator::SORT_REGULAR )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? \n"
" $coll->sort( $arr, $sort_flag ) : collator_sort( $coll, $arr, $sort_flag );\n"
"}\n"
"function ut_coll_asort( $coll, &$arr, $sort_flag = Collator::SORT_REGULAR )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? \n"
" $coll->asort( $arr, $sort_flag ) : collator_asort( $coll, $arr, $sort_flag );\n"
"}\n"
"function ut_coll_get_locale( $coll, $type )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? \n"
" $coll->getLocale( $type ) : collator_get_locale( $coll, $type );\n"
"}\n"
"function ut_coll_set_strength( $coll, $strength )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? \n"
" $coll->setStrength( $strength ) : collator_set_strength( $coll, $strength );\n"
"}\n"
"function ut_coll_set_attribute( $coll, $attr, $val )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? \n"
" $coll->setAttribute( $attr, $val ) : collator_set_attribute( $coll, $attr, $val );\n"
"}\n"
"function ut_coll_set_default( $coll )\n"
"{\n"
" return $GLOBALS['oo-mode'] ? Collator::setDefault( $coll ) : collator_set_default( $coll );\n"
"}\n"
"$test_num = 1;\n"
"function sort_arrays( $locale, $arrays, $sort_flag = Collator::SORT_REGULAR )\n"
"{\n"
" $res_str = '';\n"
" $coll = ut_coll_create( $locale );\n"
" foreach( $arrays as $array )\n"
" {\n"
" // Sort array values\n"
" $res_val = ut_coll_sort( $coll, $array, $sort_flag );\n"
" // Concatenate the sorted array and function result\n"
" // with output string.\n"
" $res_dump = \"\\n\" . dump( $array ) .\n"
" \"\\n Result: \" . dump( $res_val );\n"
" // Preppend test signature to output string\n"
" $md5 = md5( $res_dump );\n"
" global $test_num;\n"
" \n"
" $res_str .= \"\\n\\n\".\n"
" \"Test $test_num.$md5:\" .\n"
" $res_dump;\n"
" ++$test_num;\n"
" }\n"
" return $res_str;\n"
"}\n"
"function ut_main1()\n"
"{\n"
" global $test_num;\n"
" $test_num = 1;\n"
" $res_str = '';\n"
" // Sort an array in SORT_REGULAR mode using en_US locale.\n"
" $test_params = array(\n"
" array( 'abc', 'abd', 'aaa' ),\n"
" array( 'm' , '1' , '_' ),\n"
" array( 'a' , 'aaa', 'aa' ),\n"
" array( 'ba' , 'b' , 'ab' ),\n"
" array( 'e' , 'c' , 'a' ),\n"
" array( '100', '25' , '36' ), // test 6\n"
" array( 5 , '30' , 2 ),\n"
" array( 'd' , '' , ' a' ),\n"
" array( 'd ' , 'f ' , ' a' ),\n"
" array( 'a' , null , '3' ),\n"
" array( 'y' , 'k' , 'i' )\n"
" );\n"
" $res_str .= sort_arrays( 'en_US', $test_params );\n"
" $test_params = array(\n"
" array( '100', '25' , '36' ),\n"
" array( 5 , '30' , 2 ), // test 13\n"
" array( 'd' , '' , ' a' ),\n"
" array( 'y' , 'k' , 'i' )\n"
" );\n"
" // Sort in en_US locale with SORT_STRING flag\n"
" $res_str .= sort_arrays( 'en_US', $test_params, Collator::SORT_STRING );\n"
" // Sort a non-ASCII array using ru_RU locale.\n"
" $test_params = array(\n"
" array( '\xd0\xb0\xd0\xb1\xd0\xb3', "
" '\xd0\xb0\xd0\xb1\xd0\xb2', "
" '\xd0\xb0\xd0\xb0\xd0\xb0', "
" '\xd0\xb0\xd0\xb1\xd0\xb2' ),\n"
" array( '\xd0\xb0\xd0\xb0', '\xd0\xb0\xd0\xb0\xd0\xb0',"
" '\xd0\xb0' )\n"
" );\n"
" $res_str .= sort_arrays( 'ru_RU', $test_params );\n"
" // Sort an array using Lithuanian locale.\n"
" $test_params = array(\n"
" array( 'y' , 'k' , 'i' )\n"
" );\n"
" $res_str .= sort_arrays( 'lt_LT', $test_params );\n"
" return $res_str;\n"
"}\n"
"ut_run('ut_main1');\n"
"function ut_main2() {\n"
" $obj = ut_coll_create('en_US');\n"
" $arr0 = array( 100, 25, 36, '30.2', '30.12' ); // test 6\n"
" $arr1 = array( '100', '25', '36' ); // test 6\n"
" $arr2 = array( 11, 5, '2', 64, 17, '30', 10, 2, '54' );\n"
" // strcmp 17 and 30, ret = 1\n"
" // Comparing values 17 and 30, ret = 1\n"
" $arr3 = array( 11, 5, 2, 64, 17, 30, 10, 2, 54 );\n"
" $arrA = $arr0;\n"
" $arrB = $arr0;\n"
" $arrC = $arr0;\n"
" ut_coll_sort($obj, $arrA, Collator::SORT_REGULAR);\n"
" ut_coll_sort($obj, $arrB, Collator::SORT_STRING);\n"
" ut_coll_sort($obj, $arrC, Collator::SORT_NUMERIC);\n"
" var_dump($arrA, $arrB, $arrC);\n"
" $arrA = $arr1;\n"
" $arrB = $arr1;\n"
" $arrC = $arr1;\n"
" ut_coll_sort($obj, $arrA, Collator::SORT_REGULAR);\n"
" ut_coll_sort($obj, $arrB, Collator::SORT_STRING);\n"
" ut_coll_sort($obj, $arrC, Collator::SORT_NUMERIC);\n"
" var_dump($arrA, $arrB, $arrC);\n"
" $arrA = $arr2;\n"
" $arrB = $arr2;\n"
" $arrC = $arr2;\n"
" ut_coll_sort($obj, $arrA, Collator::SORT_REGULAR);\n"
" ut_coll_sort($obj, $arrB, Collator::SORT_STRING);\n"
" ut_coll_sort($obj, $arrC, Collator::SORT_NUMERIC);\n"
" var_dump($arrA, $arrB, $arrC);\n"
" $arrA = $arr3;\n"
" $arrB = $arr3;\n"
" $arrC = $arr3;\n"
" ut_coll_sort($obj, $arrA, Collator::SORT_REGULAR);\n"
" ut_coll_sort($obj, $arrB, Collator::SORT_STRING);\n"
" ut_coll_sort($obj, $arrC, Collator::SORT_NUMERIC);\n"
" var_dump($arrA, $arrB, $arrC);\n"
"}\n"
"ut_run('ut_main2');\n"
"function ut_main3()\n"
"{\n"
" $res_str = '';\n"
" $locales = array(\n"
" 'EN-US-ODESSA',\n"
" 'UK_UA_ODESSA',\n"
" 'uk-ua_CALIFORNIA@currency=;currency=GRN',\n"
" '',\n"
" 'root',\n"
" 'uk@currency=EURO'\n"
" );\n"
" foreach( $locales as $locale )\n"
" {\n"
" // Create Collator with the current locale.\n"
" $coll = ut_coll_create( $locale );\n"
" if( !is_object($coll) )\n"
" {\n"
" $res_str .= \"Error creating collator with '$locale' locale: \" .\n"
" intl_get_error_message() . \"\\n\";\n"
" continue;\n"
" }\n"
" // Get the requested, valid and actual locales.\n"
" $vloc = ut_coll_get_locale( $coll, Locale::VALID_LOCALE );\n"
" // Show them.\n"
" $res_str .= \"Locale: '$locale'\\n\" .\n"
" \" ULOC_VALID_LOCALE = '$vloc'\\n\";\n"
" }\n"
" return $res_str;\n"
"}\n"
"ut_run('ut_main3');\n"
"function test_COW( $locale, $test_array )\n"
"{\n"
" $res_str = '';\n"
" $coll = ut_coll_create( $locale );\n"
" // Create two copies of the given array.\n"
" $copy1 = $test_array;\n"
" $copy2 = $test_array;\n"
" // Sort given array and the first copy of it.\n"
" ut_coll_sort( $coll, $test_array );\n"
" ut_coll_sort( $coll, $copy1 );\n"
" // Return contents of all the arrays.\n"
" // The second copy should remain unsorted.\n"
" $res_str .= dump( $test_array ) . \"\\n\";\n"
" $res_str .= dump( $copy1 ) . \"\\n\";\n"
" $res_str .= dump( $copy2 ) . \"\\n\";\n"
" return $res_str;\n"
"}\n"
"function ut_main4()\n"
"{\n"
" $res_str = '';\n"
" $a1 = array( 'b', 'a', 'c' );\n"
" $a2 = array( '\xd0\xb1', '\xd0\xb0', '\xd0\xb2' );\n"
" $res_str .= test_COW( 'en_US', $a1 );\n"
" $res_str .= test_COW( 'ru_RU', $a2 );\n"
" return $res_str;\n"
"}\n"
"ut_run('ut_main4');\n"
"function cmp_array( &$coll, $a )\n"
"{\n"
" $res = '';\n"
" $prev = null;\n"
" foreach( $a as $i )\n"
" {\n"
" if( is_null( $prev ) )\n"
" $res .= \"$i\";\n"
" else\n"
" {\n"
" $eqrc = ut_coll_compare( $coll, $prev, $i );\n"
" $eq = $eqrc < 0 ? \"<\" : ( $eqrc > 0 ? \">\" : \"=\" );\n"
" $res .= \" $eq $i\";\n"
" }\n"
" $prev = $i;\n"
" }\n"
" $res .= \"\\n\";\n"
" return $res;\n"
"}\n"
"function check_alternate_handling( &$coll )\n"
"{\n"
" $res = '';\n"
" ut_coll_set_strength( $coll, Collator::TERTIARY );\n"
" ut_coll_set_attribute( $coll, Collator::ALTERNATE_HANDLING, Collator::NON_IGNORABLE );\n"
" $res .= cmp_array( $coll, array( 'di Silva', 'Di Silva', 'diSilva', 'U.S.A.', 'USA' ) );\n"
" ut_coll_set_attribute( $coll, Collator::ALTERNATE_HANDLING, Collator::SHIFTED );\n"
" $res .= cmp_array( $coll, array( 'di Silva', 'diSilva', 'Di Silva', 'U.S.A.', 'USA' ) );\n"
" ut_coll_set_strength( $coll, Collator::QUATERNARY );\n"
" $res .= cmp_array( $coll, array( 'di Silva', 'diSilva', 'Di Silva', 'U.S.A.', 'USA' ) );\n"
" $res .= \"\\n\";\n"
" return $res;\n"
"}\n"
"function ut_main5()\n"
"{\n"
" $coll = ut_coll_create( 'en_US' );\n"
" return\n"
" check_alternate_handling( $coll );\n"
"}\n"
"ut_run('ut_main5');\n"
"function sort_arrays_with_sort_keys( $locale, $arrays )\n"
"{\n"
" $res_str = '';\n"
" $coll = ut_coll_create( $locale );\n"
" foreach( $arrays as $array )\n"
" {\n"
" // Sort array values\n"
" $res_val = ut_coll_sort_with_sort_keys( $coll, $array );\n"
" // Concatenate the sorted array and function result\n"
" // with output string.\n"
" $res_dump = \"\\n\" . dump( $array ) .\n"
" \"\\n Result: \" . dump( $res_val );\n"
" \n"
" \n"
" // Preppend test signature to output string\n"
" $md5 = md5( $res_dump );\n"
" global $test_num;\n"
" $res_str .= \"\\n\\n\".\n"
" \"Test $test_num.$md5:\" .\n"
" $res_dump;\n"
" ++$test_num;\n"
" }\n"
" return $res_str;\n"
"}\n"
"function ut_main6()\n"
"{\n"
" global $test_num;\n"
" $test_num = 1;\n"
" $res_str = '';\n"
" // Sort an array in SORT_REGULAR mode using en_US locale.\n"
" $test_params = array(\n"
" array( 'abc', 'abd', 'aaa' ),\n"
" array( 'm' , '1' , '_' ),\n"
" array( 'a' , 'aaa', 'aa' ),\n"
" array( 'ba' , 'b' , 'ab' ),\n"
" array( 'e' , 'c' , 'a' ),\n"
" array( 'd' , '' , ' a' ),\n"
" array( 'd ' , 'f ' , ' a' ),\n"
" array( 'a' , null , '3' ),\n"
" array( 'y' , 'i' , 'k' )\n"
" );\n"
" $res_str .= sort_arrays_with_sort_keys( 'en_US', $test_params );\n"
" // Sort a non-ASCII array using ru_RU locale.\n"
" $test_params = array(\n"
" array( '\xd0\xb0\xd0\xb1\xd0\xb3', "
" '\xd0\xb0\xd0\xb1\xd0\xb2', "
" '\xd0\xb0\xd0\xb0\xd0\xb0', "
" '\xd0\xb0\xd0\xb1\xd0\xb2' ),\n"
" array( '\xd0\xb0\xd0\xb0', '\xd0\xb0\xd0\xb0\xd0\xb0',"
" '\xd0\xb0' )\n"
" );\n"
" $res_str .= sort_arrays_with_sort_keys( 'ru_RU', $test_params );\n"
" // Array with data for sorting.\n"
" $test_params = array(\n"
" array( 'y' , 'i' , 'k' )\n"
" );\n"
" // Sort an array using Lithuanian locale.\n"
" $res_str .= sort_arrays_with_sort_keys( 'lt_LT', $test_params );\n"
" return $res_str . \"\\n\";\n"
"}\n"
"ut_run('ut_main6');\n"
);
return true;
}
bool TestCodeRun::TestExtSocket() {
MVCR("<?php "
"$r = socket_create(AF_INET, SOCK_RAW, 0);"
"var_dump(socket_last_error());");
return true;
}
bool TestCodeRun::TestAPC() {
MVCR("<?php "
"$a = array();\n"
"$a[] =& $a;\n"
"print_r($a);\n"
"apc_store('table', $a);\n"
);
// PHP doesn't have APC for CLI mode, so have to use MVCRO
MVCRO("<?php "
"$a = array(1);\n"
"$a[] =& $a[0];\n"
"$a[0] = 2;\n"
"print_r($a);\n"
"\n"
"apc_store('table', $a);\n"
"$b = apc_fetch('table', $b);\n"
"print_r($b);\n"
"$b[0] = 3;\n"
"print_r($b);\n",
"Array\n"
"(\n"
" [0] => 2\n"
" [1] => 2\n"
")\n"
"Array\n"
"(\n"
" [0] => 2\n"
" [1] => 2\n"
")\n"
"Array\n"
"(\n"
" [0] => 3\n"
" [1] => 3\n"
")\n"
);
MVCRO("<?php\n"
"class A { var $v = 10; function f() { $this->v = 100; } }\n"
"$a = array(array(1, 2, 3), new A());\n"
"apc_store('0', $a);\n"
"$b = apc_fetch(0);\n"
"var_dump($b[1]->v);\n"
"$b[1]->f();\n" // SharedMap::get() needs caching
"var_dump($b[1]->v);\n"
"$b[2] = 1;\n" // SharedMap::escalate() needs caching
"var_dump($b[1]->v);\n",
"int(10)\n"
"int(100)\n"
"int(100)\n"
);
MVCRO("<?php\n"
"class A { private $b = 10; }\n"
"class B extends A { private $b = 100; }\n"
"apc_store('key', new B());\n"
"var_dump(apc_fetch('key'));\n",
"object(B)#1 (2) {\n"
" [\"b\":\"B\":private]=>\n"
" int(100)\n"
" [\"b\":\"A\":private]=>\n"
" int(10)\n"
"}\n"
);
MVCRO("<?php\n"
"class A { var $a, $b; }\n"
"$a = new A(); $a->a = 5; $a->b = &$a->a;\n"
"apc_store('key', $a);\n"
"var_dump(apc_fetch('key'));\n",
"object(A)#2 (2) {\n"
" [\"a\"]=>\n"
" &int(5)\n"
" [\"b\"]=>\n"
" &int(5)\n"
"}\n"
);
MVCRO("<?php\n"
"class a {"
" protected $foo = 10;"
"}"
"$x = new a;"
"apc_store('x', array($x));"
"$x = apc_fetch('x');"
"var_dump($x[0]);",
"object(a)#1 (1) {\n"
" [\"foo\":protected]=>\n"
" int(10)\n"
"}\n"
);
// objects in an apc array can be changed without escalating the array
MVCRO("<?php\n"
"class A { var $i = 10; }\n"
"$a = array(new A);\n"
"apc_store('key1', $a);\n"
"$b = apc_fetch('key1');\n"
"$c = $b[0];\n"
"$c->i = 100;\n"
"apc_store('key2', $b);\n"
"$t = apc_fetch('key2');\n"
"var_dump($t[0]->i);\n",
"int(100)\n");
// Serializable object in APC
MVCRO("<?php\n"
"class A implements Serializable {\n"
" var $a = 123;\n"
" function serialize() { return serialize($this->a); }\n"
" function unserialize($s) { $this->a = unserialize($s); }\n"
"}\n"
"$o = new A;\n"
"apc_store('key', $o);\n"
"$r = apc_fetch('key');\n"
"var_dump($r);\n",
"object(A)#2 (1) {\n"
" [\"a\"]=>\n"
" int(123)\n"
"}\n");
for (int i = 0; i < 2; i++) {
string cfg = "-vServer.APC.AllowObject=" + boost::lexical_cast<string>(i);
OptionSetter w(this, OptionSetter::RunTime, cfg.c_str());
// apc_fetch twice to trigger immutable object
MVCRO("<?php "
"class A {"
" public function __construct($i, $j, $k) {"
" $this->a = $i * $i;"
" $this->b = $j * $j;"
" $this->c = $k * $k;"
" }"
" public $a;"
" protected $b;"
" private $c;"
" public $aa = 'aa';"
" protected $bb = false;"
" private $cc = 1.22;"
"}"
"class B extends A {"
" public function __construct($i, $j, $k) {"
" $this->a = $i + $i;"
" $this->b = $j + $j;"
" $this->c = $k + $k;"
" }"
" public $a;"
" protected $b;"
" private $c;"
" public $aa = 'aaa';"
" protected $bb = 4;"
" private $cc = 1.222;"
"}"
"class C extends B {"
" public function __construct($i, $j, $k) {"
" $this->a = $i + $i + $i;"
" $this->b = $j + $j + $j;"
" $this->c = $k + $k + $k;"
" }"
" public $a;"
" protected $b;"
" private $c;"
" public $aa = 'aaaa';"
" protected $bb = 40;"
" private $cc = 1.333;"
"}"
"class D extends C {"
" public function __construct($i, $j, $k) {"
" $this->a = $i + $i + $i;"
" $this->b = $j + $j + $j;"
" $this->c = $k + $k + $k;"
" }"
" public $a;"
" public $b;"
" private $c;"
" public $aa = 'aaaaa';"
" public $bb = 400;"
" private $cc = 1.3333;"
"}"
"function foo() {"
" $obj = new A(111, 222, 333);"
" apc_store('foobar', $obj);"
" $obj = apc_fetch('foobar');"
" $obj = apc_fetch('foobar');"
" var_dump($obj);"
" $obj = new B(111, 222, 333);"
" apc_store('foobar', $obj);"
" $obj = apc_fetch('foobar');"
" $obj = apc_fetch('foobar');"
" var_dump($obj);"
" $obj = new C(111, 222, 333);"
" apc_store('foobar', $obj);"
" $obj = apc_fetch('foobar');"
" $obj = apc_fetch('foobar');"
" var_dump($obj);"
" $obj = new D(111, 222, 333);"
" apc_store('foobar', $obj);"
" $obj = apc_fetch('foobar');"
" $obj = apc_fetch('foobar');"
" var_dump($obj);"
"}"
"foo();",
"object(A)#3 (6) {\n"
" [\"a\"]=>\n"
" int(12321)\n"
" [\"b\":protected]=>\n"
" int(49284)\n"
" [\"c\":\"A\":private]=>\n"
" int(110889)\n"
" [\"aa\"]=>\n"
" string(2) \"aa\"\n"
" [\"bb\":protected]=>\n"
" bool(false)\n"
" [\"cc\":\"A\":private]=>\n"
" float(1.22)\n"
"}\n"
"object(B)#6 (8) {\n"
" [\"a\"]=>\n"
" int(222)\n"
" [\"b\":protected]=>\n"
" int(444)\n"
" [\"c\":\"B\":private]=>\n"
" int(666)\n"
" [\"aa\"]=>\n"
" string(3) \"aaa\"\n"
" [\"bb\":protected]=>\n"
" int(4)\n"
" [\"cc\":\"B\":private]=>\n"
" float(1.222)\n"
" [\"c\":\"A\":private]=>\n"
" NULL\n"
" [\"cc\":\"A\":private]=>\n"
" float(1.22)\n"
"}\n"
"object(C)#9 (10) {\n"
" [\"a\"]=>\n"
" int(333)\n"
" [\"b\":protected]=>\n"
" int(666)\n"
" [\"c\":\"C\":private]=>\n"
" int(999)\n"
" [\"aa\"]=>\n"
" string(4) \"aaaa\"\n"
" [\"bb\":protected]=>\n"
" int(40)\n"
" [\"cc\":\"C\":private]=>\n"
" float(1.333)\n"
" [\"c\":\"B\":private]=>\n"
" NULL\n"
" [\"cc\":\"B\":private]=>\n"
" float(1.222)\n"
" [\"c\":\"A\":private]=>\n"
" NULL\n"
" [\"cc\":\"A\":private]=>\n"
" float(1.22)\n"
"}\n"
"object(D)#12 (12) {\n"
" [\"a\"]=>\n"
" int(333)\n"
" [\"b\"]=>\n"
" int(666)\n"
" [\"c\":\"D\":private]=>\n"
" int(999)\n"
" [\"aa\"]=>\n"
" string(5) \"aaaaa\"\n"
" [\"bb\"]=>\n"
" int(400)\n"
" [\"cc\":\"D\":private]=>\n"
" float(1.3333)\n"
" [\"c\":\"C\":private]=>\n"
" NULL\n"
" [\"cc\":\"C\":private]=>\n"
" float(1.333)\n"
" [\"c\":\"B\":private]=>\n"
" NULL\n"
" [\"cc\":\"B\":private]=>\n"
" float(1.222)\n"
" [\"c\":\"A\":private]=>\n"
" NULL\n"
" [\"cc\":\"A\":private]=>\n"
" float(1.22)\n"
"}\n");
}
MVCRO("<?php\n"
"class C {}\n"
"class D {\n"
" public function __construct($f) {\n"
" $this->map = $f;\n"
" }\n"
"}\n"
"class E {\n"
" protected $map;\n"
" public function __construct($f) {\n"
" $this->map = $f;\n"
" }\n"
" public function getMap() {\n"
" return $this->map;\n"
" }\n"
"}\n"
"$f = new stdclass();\n"
"$arr = array(new E($f), new D($f));\n"
"apc_store('ggg', $arr);\n"
"$arr2 = apc_fetch('ggg');\n"
"var_dump($arr[0]->getMap());\n"
"var_dump($arr[1]->map);\n"
"var_dump($arr2[0]->getMap());\n"
"var_dump($arr2[1]->map);\n"
,
"object(stdClass)#1 (0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"object(stdClass)#5 (0) {\n"
"}\n"
"object(stdClass)#5 (0) {\n"
"}\n"
);
MVCRO("<?php\n"
"$v = 42;\n"
"$o1 = new stdclass;\n"
"$o2 = new stdclass;\n"
"$o1->p = &$v;\n"
"$o2->p = &$v;\n"
"$arr1 = array($o1, $o2);\n"
"apc_store('foo', $arr1);\n"
"$arr2 = apc_fetch('foo');\n"
"var_dump($arr1);\n"
"var_dump($arr2);\n"
,
"array(2) {\n"
" [0]=>\n"
" object(stdClass)#1 (1) {\n"
" [\"p\"]=>\n"
" &int(42)\n"
" }\n"
" [1]=>\n"
" object(stdClass)#2 (1) {\n"
" [\"p\"]=>\n"
" &int(42)\n"
" }\n"
"}\n"
"array(2) {\n"
" [0]=>\n"
" object(stdClass)#3 (1) {\n"
" [\"p\"]=>\n"
" &int(42)\n"
" }\n"
" [1]=>\n"
" object(stdClass)#4 (1) {\n"
" [\"p\"]=>\n"
" &int(42)\n"
" }\n"
"}\n"
);
{
HipHopSyntax w(this);
MVCRO("<?php\n"
"class A {"
" public function gen($a, $b) { yield $a; yield $b; }"
"}\n"
"$x = new A; "
"$x->cache_gen = $x->gen('a', 'b'); "
"foreach ($x->cache_gen as $v) { var_dump($v); } "
"apc_store('key', $x); "
"$y = apc_fetch('key'); "
"print_r($y->cache_gen);",
"string(1) \"a\"\n"
"string(1) \"b\"\n"
"DummyContinuation Object\n"
"(\n"
")\n"
);
MVCRO("<?php\n"
"$f = function($a) { return $a; }; "
"var_dump($f('x')); "
"apc_store('key', $f); "
"$g = apc_fetch('key'); "
"print_r($g); ",
"string(1) \"x\"\n"
"DummyClosure Object\n"
"(\n"
")\n"
);
}
MVCRO("<?php "
"function test($x) {"
" apc_store('foo', array('a'.$x, array($x)));"
" $a = apc_fetch('foo');"
" $x = array_intersect($a, $a);"
" var_dump($x);"
"}"
"test('foo');",
"array(2) {\n"
" [0]=>\n"
" string(4) \"afoo\"\n"
" [1]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" }\n"
"}\n");
MVCRO("<?php "
"class X implements Serializable {"
" public function serialize() {"
" return 'true';"
" }"
" public function unserialize($serialized ) {"
" }"
"}"
"function test() {"
" $a[] = $x = new X;"
" $a[] = $x;"
" $a[] = $x;"
" apc_store('foo', $a);"
" $a = apc_fetch('foo');"
" var_dump($a);"
" $a = apc_fetch('foo');"
" var_dump($a);"
"}"
"test();",
"array(3) {\n"
" [0]=>\n"
" object(X)#2 (0) {\n"
" }\n"
" [1]=>\n"
" object(X)#2 (0) {\n"
" }\n"
" [2]=>\n"
" object(X)#2 (0) {\n"
" }\n"
"}\n"
"array(3) {\n"
" [0]=>\n"
" object(X)#3 (0) {\n"
" }\n"
" [1]=>\n"
" object(X)#3 (0) {\n"
" }\n"
" [2]=>\n"
" object(X)#3 (0) {\n"
" }\n"
"}\n");
return true;
}
bool TestCodeRun::TestInlining() {
OptionSetter w(this, OptionSetter::CompileTime,
"-vAutoInline=5");
MVCR("<?php "
"function id($x) {"
" return $x;"
" }"
"class X {"
" public function f() { return 'hello'; }"
"}"
"function test($a, $b) {"
" return $a ? $b : id(new X)->f();"
"}"
"var_dump(test());");
MVCR("<?php "
"function foo($e='e') {"
" return '<a name=\"'.$e.'\" id=\"'.$e.'\"></a>';"
"}"
"function test() {"
" echo foo();"
"}"
"test();");
MVCR("<?php "
"function foo($e, $m) {"
" $_REQUEST['_foo'] = $e;"
" $_REQUEST['_bar'] = $m;"
" return $e;"
"}"
"function test($x) {"
" return foo('a', $x);"
"}"
"var_dump(test('b'));");
MVCR("<?php "
"function h() { class X{}; }"
"function f($a, $b, $c) { return h(); }"
"function g($a, $b, $c) {"
" return f($a++, $b++ + $a++, $c);"
"}");
MVCR("<?php "
"function f($name, $unique_id=false, $id=null) {"
" $id = $id ? $id : ($unique_id ? uniqid($name) : $name);"
" return $id;"
" }"
"function test($a, $b, $c) {"
" return f($name = 'status', $unique_id = true, $id = 'status_active');"
" }"
"var_dump(test(1,2,3));");
MVCR("<?php "
"function g($a) { function t(){}; return $a ? array(1,2,3) : 'foo'; }"
"function f($a) { return g($a); }"
"function test($a) {"
" return reset((f($a)));"
" }"
"var_dump(test(1));"
"function &h(&$a) { return $a['foo']; }"
"function i($a) { $x = &h($a); $x = 'hello'; return $a; }"
"var_dump(i(false));");
MVCR("<?php "
"function bar($name) {"
" $name = trim($name);"
" var_dump($name);"
"}"
"function f($x, $y) { if ($x) return $x; return $y; }"
"function foo() {"
" $name = 'ab.' . f('x', 'y');"
" bar($name);"
" bar($name);"
"}"
"foo();");
MVCR("<?php "
"function id($x) { return $x; }"
"class B { function __construct($x) { $this->x = $x; } }"
"class X extends B {"
" function __construct() { parent::__construct(array()); }"
" function foo() { echo \"foo\n\"; }"
"}"
"function bar($x=0) { if ($x) return 1; return ''; }"
"function test($foo) {"
" id(new X(bar()))->foo();"
" id(new $foo(bar()))->foo();"
"}"
"test('X');");
MVCR("<?php "
"function id($a) { return $a; }"
"class X {}"
"if (0) {"
" class X {}"
"}"
"class Y extends X { function t() {} }"
"function test() {"
" id(new Y)->t();"
"}");
MVCR("<?php "
"/* Compile only: verify no c++ compilation errors */"
"function foo($a) {"
" return $a[1];"
"}"
"function baz(&$x) { if ($x) $x++; }"
"function bar($a) {"
" baz(foo($a)[1]);"
" foo($a)->bar = 1;"
"}");
MVCR("<?php\n"
"/* Compile only: verify no c++ compilation errors */"
"function f($x) {\n"
" return function () use ($x) {\n"
" return $x;\n"
" };\n"
"}\n"
"function g($x) {\n"
" $c = f($x);\n"
" return $c();\n"
"}\n");
{
HipHopSyntax w(this);
MVCRO("<?php\n"
"function inline_me($x, $y, &$z) { return ($z = ($x + $y)); }\n"
"function gen($x, $y) {\n"
" yield inline_me($x, $y, $arg);\n"
" yield $arg;\n"
"}\n"
"foreach (gen(10, 20) as $x) { var_dump($x); }\n",
"int(30)\n"
"int(30)\n");
}
MVCR("<?php "
"function &test(&$x,$y) {"
" $GLOBALS['x'] = &$y;"
" return $x[0];"
"}"
"$x = array((object)1);"
"$y = &test($x,0);"
"$y++;"
"var_dump($x, $y);");
MVCR("<?php "
"function &test(&$x) {"
" $x = 1;"
" return $x;"
"}"
"$x = 0;"
"$y = &test($x);"
"$y++;"
"var_dump($x, $y);");
if (!hhvm) {
MVCRNW("<?php "
"function foo($u, $v, $w) {"
" $u = 10;"
" $v = 20;"
" $w = 20;"
"}"
"$u = 1;"
"$v = 2;"
"$w = 3;"
"foo(&$u, &$v, $w);"
"var_dump($u, $v, $w);");
}
MVCR("<?php "
"function foo() { return $GLOBALS['g']; }"
"$g = 0;"
"$a =& foo();"
"$a++;"
"var_dump($a, $g);");
MVCR("<?php "
"function pid($x) {"
" var_dump($x);"
" return $x;"
"}"
"function f($x) {"
" return $x;"
"}"
"function ttest() {"
" return f(pid('arg1'),pid('arg2'));"
"}"
"ttest();");
MVCR("<?php "
"class X {"
" function __destruct() { var_dump('done'); }"
"}"
"function f() { $x = new X; }"
"function g() {"
" var_dump('start');"
" f();"
" var_dump('end');"
"}"
"g();");
return true;
}
bool TestCodeRun::TestCopyProp() {
OptionSetter w1(this, OptionSetter::CompileTime, "-vCopyProp=1");
HipHopSyntax w2(this);
MVCR("<?php "
"function test($tr_data) {"
" $temp_tr = null;"
" foreach ($tr_data as $tr_id => $tr_row) {"
" if ($tr_row == 45) $temp_tr = $tr_id;"
" if ($tr_id == 0) {"
" continue;"
" } else {"
" return $tr_row;"
" }"
" }"
" if ($temp_tr) {"
" return $temp_tr;"
" }"
" return null;"
"}"
"var_dump(test(array('a' => 1, 'b' => 45)));");
MVCR("<?php "
"/* Compile only test. Used to crash hphp */ "
"class X {"
" protected $map;"
" protected $parents;"
" public function __construct(array $map, array $parents) {"
" $this->map = $map;"
" $this->parents = $parents;"
" }"
"}");
MVCR("<?php\n"
"function f($x, $y) {\n"
" $z = 32;\n"
" return $x && $y ?: $z;\n"
"}\n"
"var_dump(f(false, false));\n"
"var_dump(f(true, true));\n");
MVCRO("<?php"
"function foo() {"
" $a = &$b;"
" $b = 1;"
" yield $a;"
" $a = 3;"
" $b = 2;"
" yield $a;"
"}"
"foreach (foo() as $x) var_dump($x);",
"int(1)\n"
"int(2)\n");
return true;
}
bool TestCodeRun::TestSerialize() {
MVCR("<?php\n"
"function f() {\n"
" $a = array(123);\n"
" $b = $a;\n"
" $c = &$b;\n"
" $d = new stdClass();\n"
" $v = array(&$a, &$b, &$c, $d, $d);\n"
" $s = serialize($v);\n"
" echo $s;\n"
"}\n"
"f();\n");
MVCR("<?php "
"class X {"
" private $o, $a, $o2;"
" function foo() {"
" $this->o = $this;"
" $this->a = array(1,2,3);"
" $this->o2 = $this;"
" }"
"}"
"function test() {"
" $x = new X;"
" $x->foo();"
" $s = serialize($x);"
" var_dump($s);"
" $y = unserialize($s);"
" var_dump($y);"
"}"
"test();");
return true;
}
bool TestCodeRun::TestHoisting() {
MVCR("<?php\n"
"var_dump(class_exists('C'));\n"
"class C implements Countable { function count() { return 0; } }\n");
MVCR("<?php\n"
"class C implements Countable { function count() { return 0; } }\n"
"var_dump(class_exists('C'));\n");
MVCRO("<?php\n"
"var_dump(class_exists('C'));\n"
"trait t { }\n"
"class C { use t; }\n",
"bool(false)\n");
MVCRO("<?php\n"
"trait t { }\n"
"class C { use t; }\n"
"var_dump(class_exists('C'));\n",
"bool(true)\n");
return true;
}
bool TestCodeRun::TestVariableClassName() {
MVCR(
"<?php\n"
"class A {\n"
" const C = 123;\n"
" static public $foo = 456;\n"
" public function bar() {\n"
" return 789;\n"
" }\n"
"}\n"
"$cls = 'a';\n"
"\n"
"var_dump($cls::C); // ClassConstant\n"
"\n"
"var_dump($cls::$foo); // StaticMember\n"
"$cls::$foo = 'test';\n"
"var_dump($cls::$foo); // l-value\n"
"\n"
"var_dump($cls::bar()); // SimpleFunctionCall\n"
"\n"
"$func = 'bar';\n"
"var_dump($cls::$func()); // DynamicFunctionCall\n");
MVCR(
"<?php\n"
"class B {\n"
" function f4($arguments) {\n"
" var_dump($arguments);\n"
" }\n"
"}\n"
"class G extends B {\n"
" function f4($a) {\n"
" $b='B';\n"
" $b::f4(5); // __call\n"
" }\n"
"}\n"
"$g = new G(5);\n"
"$g->f4(3);\n");
MVCR("<?php\n"
"class B {\n"
" function __call($name, $arguments) {\n"
" echo \"Calling B object method '$name' \" . "
"implode(', ', $arguments). \"\n\";\n"
" }\n"
"}\n"
"class G extends B {\n"
" function __call($name, $arguments) {\n"
" echo \"Calling G object method '$name' \" . "
"implode(', ', $arguments). \"\n\";\n"
" }\n"
" function f4missing($a) {\n"
" $b=\"B\";\n"
" echo \"Calling G object method 'f4missing' 5 == \", "
"$b::f4missing(5);\n"
" }\n"
"}\n"
"\n"
"$g = new G();\n"
"$g->f4missing(3);\n"
"echo \"finish\n\";\n");
MVCR("<?php\n"
"function func() { return 'B';}\n"
"class B {\n"
" function foo() { var_dump(__CLASS__);}\n"
" function f4missing() { $this->foo();}\n"
"}\n"
"class G extends B {\n"
" function foo() { var_dump(__CLASS__);}\n"
" function f4missing() { $b = func(); $b::f4missing();}\n"
"}\n"
"$g = new G; $g->f4missing();\n");
return true;
}
bool TestCodeRun::TestLateStaticBinding() {
MVCR(
"<?php\n"
"class B {\n"
" public static $a = 100;\n"
" static function f() {\n"
" var_dump(static::$a);\n"
" }\n"
"}\n"
"class C extends B {\n"
" public static $a = 1000;\n"
"}\n"
"call_user_func(array('C', 'f'));\n"
);
MVCR(
"<?php\n"
"class A {\n"
" const NAME = 'A';\n"
" public static function test() {\n"
" $args = func_get_args();\n"
" echo static::NAME, \" \".join(',', $args).\" \\n\";\n"
" }\n"
"}\n"
"class B extends A {\n"
" const NAME = 'B';\n"
" public static function test() {\n"
" echo self::NAME, \"\\n\";\n"
" forward_static_call(array('A', 'test'), 'more', 'args');\n"
" forward_static_call( 'test', 'other', 'args');\n"
" }\n"
"}\n"
"B::test('foo');\n"
"function test() {\n"
" $args = func_get_args();\n"
" echo \"C \".join(',', $args).\" \\n\";\n"
"}\n"
);
MVCR(
"<?php\n"
"class X {\n"
" function f() {\n"
" $y = new Y;\n"
" $y->foo();\n"
" static::g();\n"
" $y->foo();\n"
" self::g();\n"
" Y::foo() && static::g();\n"
" }\n"
" static function g() { var_dump(__CLASS__); }\n"
"}\n"
"class Y extends X {\n"
" static function g() { var_dump(__CLASS__); }\n"
" static function foo() { return true; }\n"
"}\n"
"function test() {\n"
" $x = new X;\n"
" $y = new Y;\n"
" $x->f();\n"
" $y->f();\n"
"}\n"
"test();\n"
);
MVCR(
"<?php\n"
"class A {\n"
" static public function foo() {\n"
" static::bar();\n"
" }\n"
" public function bar() {\n"
" var_dump(__CLASS__);\n"
" }\n"
" public function foo2() {\n"
" B::foo(); // B always changes 'static'\n"
" self::foo(); // 'self' doesn't change 'static'\n"
" }\n"
"}\n"
"class B extends A {\n"
" public function bar() {\n"
" var_dump(__CLASS__);\n"
" }\n"
" public function foo3() {\n"
" $this->foo(); // $this changes 'static'\n"
" parent::foo(); // 'parent' doesn't change 'static'\n"
" }\n"
"}\n"
"\n"
"$a = new A();\n"
"$b = new B();\n"
"\n"
"B::foo(); // B\n"
"$b->foo(); // B\n"
"\n"
"$b->foo2(); // BB\n"
"$b->foo3(); // BB\n"
"\n"
"A::foo(); // A\n"
"$a->foo(); // A\n"
"\n"
"$a->foo2(); // BA\n"
);
MVCR("<?php "
"class X {"
" static function foo() { return false; }"
" static function bar() { return 5.5; }"
" static function baz() { return time(); }"
" }"
"var_dump(X::foo());"
"var_dump(X::bar());"
"var_dump(gettype(X::baz()));");
MVCR("<?php\n"
"class X {\n"
" static function foo() { echo \"X::foo\\n\"; }\n"
" function bar() { static::foo(); }\n"
"}\n"
"class Y extends X {\n"
" static function foo() { echo \"Y::foo\\n\"; }\n"
" function baz() { X::bar(); }\n"
"}\n"
"$y = new Y;\n"
"$y->baz();\n"
"Y::baz();\n");
MVCR("<?php\n"
"function f() { return true; }\n"
"if (f()) {\n"
" class A {\n"
" static $a = 'A';\n"
" static function f() { echo static::$a; }\n"
" function g() { $this->f(); }\n"
" }\n"
"} else {\n"
" class A { }\n"
"}\n"
"class B extends A { static $a = 'B'; }\n"
"$b = new B;\n"
"$b->g();\n");
// instanceof static and new static
MVCR("<?php\n"
"class A {\n"
" static function f() { return new static; }\n"
" static function g($o) { return $o instanceof static; }\n"
"}\n"
"class B extends A { }\n"
"var_dump(A::g(A::f()));\n"
"var_dump(A::g(B::f()));\n"
"var_dump(B::g(A::f()));\n"
"var_dump(B::g(B::f()));\n");
MVCR("<?php\n"
"class TestA {\n"
"protected static function doSomething() {\n"
"echo \"TestA::doSomething\\n\";\n"
"}\n"
"protected static function test() {\n"
"static::doSomething();\n"
"}\n"
"public static function nativeTest($obj) {\n"
"$obj->bar();\n"
"self::test();\n"
"}\n"
"}\n"
"class Foo {\n"
"public function bar() {}\n"
"}\n"
"$obj = new Foo();\n"
"TestA::nativeTest($obj);\n");
MVCR("<?php "
"class X {"
" public function foo($y) {"
" call_user_func(array($y, 'foo'));"
" $y::foo();"
" }"
"}"
"class Y {"
" public static function foo() {"
" var_dump(__METHOD__);"
" static::bar();"
" }"
" public static function bar() {"
" var_dump(__METHOD__);"
" }"
"}"
"$x = new X;"
"$x->foo('y');"
"$x->foo(new Y);");
MVCR("<?php "
"class S {"
" public static function t() {"
" echo func_get_arg(0);"
" }"
"}"
"class C {"
" public static function d() {"
" echo get_called_class();"
" S::t(get_called_class());"
" echo get_called_class();"
" }"
"}"
"C::d();");
MVCR("<?php\n"
"class A {\n"
" public static function foo() {\n"
" var_dump(get_called_class());\n"
" }\n"
" public static function bar() {\n"
" $x = new B;\n"
" $x->fiz(self::foo());\n"
" }\n"
" function fiz($x) {}\n"
"}\n"
"class B extends A {}\n"
"$array = array('foo');\n"
"array_map('B::foo', $array);\n"
"call_user_func('B::foo');\n"
"call_user_func(array('B', 'foo'));\n"
"A::bar();\n");
if (!hhvm) {
MVCR("<?php "
"class X {"
" function foo() { var_dump(__METHOD__, get_called_class()); }"
" static function bar($obj, $meth) {"
" call_user_func(array($obj, $meth));"
" }"
" function buz() { var_dump(get_called_class()); }"
" function baz($a) { forward_static_call($a); }"
"};"
"class Y extends X {"
" function foo() { var_dump(__METHOD__); }"
" static function boo($obj, $meth) {"
" call_user_func(array($obj, $meth));"
" }"
"}"
"class YY extends Y {}"
"class Z {}"
"call_user_func(array('YY', 'buz'));"
"call_user_func(array('YY', 'parent::buz'));"
"Y::boo('YY', 'parent::buz');"
"$obj = new Y;"
"X::bar($obj, 'static::foo');"
"Y::bar($obj, 'static::foo');"
"X::bar($obj, 'self::foo');"
"Y::bar($obj, 'self::foo');"
"X::bar($obj, 'parent::foo');"
"Y::bar($obj, 'parent::foo');"
"X::bar($obj, 'X::foo');"
"Y::bar($obj, 'X::foo');"
"$obj = new X;"
"Y::boo($obj, 'parent::foo');"
"$obj = 'Y';"
"X::bar($obj, 'static::foo');"
"Y::bar($obj, 'static::foo');"
"X::bar($obj, 'self::foo');"
"Y::bar($obj, 'self::foo');"
"X::bar($obj, 'parent::foo');"
"Y::bar($obj, 'parent::foo');"
"X::bar($obj, 'X::foo');"
"Y::bar($obj, 'X::foo');"
"$obj = 'X';"
"X::bar($obj, 'static::foo');"
"Y::bar($obj, 'static::foo');"
"X::bar($obj, 'self::foo');"
"Y::bar($obj, 'self::foo');"
"X::bar($obj, 'parent::foo');"
"Y::bar($obj, 'parent::foo');"
"X::bar($obj, 'X::foo');"
"Y::bar($obj, 'X::foo');"
"$obj = 'Z';"
"X::bar($obj, 'X::foo');"
"X::bar($obj, 'static::foo');"
"X::baz('X::buz');"
"Y::baz('X::buz');"
"X::baz(array('X', 'buz'));"
"Y::baz(array('X', 'buz'));");
}
MVCR("<?php\n"
"class X {\n"
" function bar() {\n"
" var_dump(get_called_class());\n"
" }\n"
"};\n"
"class Y extends X {\n"
" function foo() {\n"
" call_user_func(array('SELF', 'bar'));\n"
" call_user_func(array('PARENT', 'bar'));\n"
" call_user_func(array('STATIC', 'bar'));\n"
" call_user_func('SELF::bar');\n"
" call_user_func('PARENT::bar');\n"
" call_user_func('STATIC::bar');\n"
" }\n"
"}\n"
"Y::foo();");
MVCR("<?php "
"class X {"
" static function foo() {"
" var_dump(__METHOD__, get_called_class());"
" }"
" function bar() {"
" var_dump(__METHOD__, get_called_class());"
" }"
"}"
"class Y extends X {}"
"class Z extends X {"
" static function foo() {"
" var_dump(__METHOD__, get_called_class());"
" }"
"}"
"function test($x, $o) {"
" $x->getMethod('foo')->invoke($o);"
" $x->getMethod('foo')->invoke(null);"
" $x->getMethod('bar')->invoke($o);"
"}"
"test(new ReflectionClass('X'), new X);"
"test(new ReflectionClass('Y'), new X);"
// "test(new ReflectionClass('X'), new Y);"
// "test(new ReflectionClass('Y'), new Y);"
"test(new ReflectionClass('X'), new X);"
// "test(new ReflectionClass('X'), new Z);"
"test(new ReflectionClass('Z'), new Z);"
"call_user_func(array(new Y, 'X::foo'));"
"call_user_func(array(new Z, 'X::foo'));");
MVCR("<?php "
"class Y {"
" static function baz($a) { var_dump(get_called_class()); }"
"}"
"class X {"
" function foo() {"
" Y::baz(static::bar());"
" }"
" static function bar() {"
" var_dump(get_called_class());"
" }"
"}"
"$x = new X;"
"$x->foo();");
return true;
}
bool TestCodeRun::TestCallStatic() {
MVCRO("<?php\n"
"class c2 {\n"
" public static function __callStatic($func, $args) {\n"
" echo \"c2::__callStatic\n\";\n"
" }\n"
"}\n"
"class d2 extends c2 {\n"
" public function __call($func, $args) {\n"
" echo \"d2::__call\n\";\n"
" }\n"
" public function test1a() {\n"
" c2::foo();\n"
" }\n"
"}\n"
"$obj = new d2;\n"
"$obj->test1a();\n",
"d2::__call\n"
// "c2::__callStatic\n" <--- PHP 5.3 returns this
);
MVCRO("<?php\n"
"class b2 { }\n"
"class c2 extends b2 {\n"
" public static function __callStatic($func, $args) {\n"
" echo \"c2::__callStatic\n\"; }\n"
"}\n"
"class d2 extends c2 {\n"
" public function __call($func, $args) {\n"
" echo \"d2::__call\n\";\n"
" }\n"
" public function test1a() {\n"
" b2::foo();\n"
" }\n"
"}\n"
"set_error_handler('h');\n"
"function h() { var_dump('errored');}"
"$obj = new d2;\n"
"$obj->test1a();\n"
"var_dump('end');\n",
"d2::__call\n"
"string(3) \"end\"\n"
// "string(7) \"errored\"\n" <--- PHP 5.3 returns this
);
MVCRO("<?php\n"
"class b2 {}\n"
"class c2 extends b2 {\n"
" public function __call($func, $args) {\n"
" echo \"c2::__call\n\";\n"
" }\n"
" public function test1a() {\n"
" b2::foo();\n"
" }\n"
"}\n"
"set_error_handler('h');\n"
"function h() { var_dump('errored');}"
"$obj = new c2;\n"
"$obj->test1a();\n"
"var_dump('end');\n",
"c2::__call\n"
"string(3) \"end\"\n"
// "string(7) \"errored\"\n" <--- PHP 5.3 returns this
);
MVCR("<?php\n"
"class c3 {\n"
" public function __call($func, $args) {\n"
" echo \"c3::__call\n\";\n"
" }\n"
" public static function __callStatic($func, $args) {\n"
" echo \"c3::__callStatic\n\";\n"
" }\n"
" public function test1b() {\n"
" c3::foo(); // invokes c3::__callStatic\n"
" }\n"
"}\n"
"class d3 extends c3 {\n"
" public function test1b() {\n"
" c3::foo(); // invokes c3::__callStatic\n"
" }\n"
"}\n"
"\n"
"c3::test1b();\n"
"d3::test1b();\n");
MVCR("<?php\n"
"class a1 {\n"
" public function __call($func, $args) {\n"
" var_dump('a1::__call');\n"
" }\n"
" public function test() {\n"
" a1::foo();\n"
" }\n"
"}\n"
"$obj = new a1;\n"
"$obj->test();\n");
MVCRO("<?php\n"
"class a1 {\n"
" public function __call($func, $args) {\n"
" var_dump('a1::__call');\n"
" }\n"
"}\n"
"class b1 {\n"
" public function test() {\n"
" a1::foo();\n"
" }\n"
"}\n"
"set_error_handler('h'); function h() { var_dump('errored');}"
"$obj = new b1;\n"
"$obj->test();\n"
"var_dump('end');\n",
"string(7) \"errored\"\n"
);
MVCR("<?php\n"
"class a2 {\n"
" public function __call($func, $args) {\n"
" var_dump('a2::__call');\n"
" }\n"
" public function test() {\n"
" a2::foo();\n"
" }\n"
"}\n"
"class b2 extends a2 {\n"
" public function test() {\n"
" a2::foo();\n"
" b2::foo();\n"
" }\n"
"}\n"
"$obj = new a2;\n"
"$obj->test();\n"
"$obj = new b2;\n"
"$obj->test();\n");
MVCR("<?php\n"
"class a1 {\n"
" public function __call($func, $args) {\n"
" var_dump('a1::__call');\n"
" }\n"
" public static function __callStatic($func, $args) {\n"
" var_dump('a1::__callStatic');\n"
" }\n"
" public function test() {\n"
" a1::foo();\n"
" }\n"
"}\n"
"class b1 {\n"
" public function test() {\n"
" a1::foo();\n"
" }\n"
"}\n"
"$obj = new a1;\n"
"$obj->test();\n"
"$obj = new b1;\n"
"$obj->test();\n");
MVCR("<?php\n"
"class a2 {\n"
" public function __call($func, $args) {\n"
" var_dump('a2::__call');\n"
" }\n"
" public static function __callStatic($func, $args) {\n"
" var_dump('a2::__callStatic');\n"
" }\n"
" public function test() {\n"
" a2::foo();\n"
" }\n"
"}\n"
"class b2 extends a2 {\n"
" public function test() {\n"
" a2::foo();\n"
" b2::foo();\n"
" }\n"
"}\n"
"$obj = new a2;\n"
"$obj->test();\n"
"$obj = new b2;\n"
"$obj->test();\n");
MVCR("<?php\n"
"class a1 {\n"
" public static function __callStatic($func, $args) {\n"
" var_dump('a1::__callStatic');\n"
" }\n"
" public function test() {\n"
" a1::foo();\n"
" }\n"
"}\n"
"class b1 {\n"
" public function test() {\n"
" a1::foo();\n"
" }\n"
"}\n"
"$obj = new a1;\n"
"$obj->test();\n"
"$obj = new b1;\n"
"$obj->test();\n");
MVCR("<?php\n"
"class a2 {\n"
" public static function __callStatic($func, $args) {\n"
" var_dump('a2::__callStatic');\n"
" }\n"
" public function test() {\n"
" a2::foo();\n"
" }\n"
"}\n"
"class b2 extends a2 {\n"
" public function test() {\n"
" a2::foo();\n"
" b2::foo();\n"
" }\n"
"}\n"
"$obj = new a2;\n"
"$obj->test();\n"
"$obj = new b2;\n"
"$obj->test();\n");
MVCR("<?php\n"
"class MethodTest {\n"
" public function __call($name, $arguments) {\n"
" var_dump($name, implode(', ', $arguments));\n"
" }\n"
" public static function __callStatic($name, $arguments) {\n"
" var_dump($name, implode(', ', $arguments));\n"
" }\n"
"}\n"
"$obj = new MethodTest;\n"
"$obj->runTest('in object context');\n"
"MethodTest::runTest('in static context');\n");
MVCR("<?php\n"
"abstract class BaseClass {"
" public static function __callStatic($name, $arguments) {"
" echo \"Calling static method '$name' \""
" . implode(', ', $arguments). \"\\n\";"
" }"
"}"
"BaseClass::foo();");
MVCR("<?php\n"
"abstract class BaseClass {"
"}"
"class SubClass extends BaseClass {"
" public static function __callStatic($name, $arguments) {"
" echo \"Calling static method '$name' \""
" . implode(', ', $arguments). \"\\n\";"
" }"
"}"
"SubClass::foo();");
MVCR("<?php\n"
"abstract class BaseClass {"
" public static function __callStatic($name, $arguments) {"
" echo \"Calling static method '$name' \""
" . implode(', ', $arguments). \"\\n\";"
" }"
"}"
"class SubClass extends BaseClass {"
"}"
"SubClass::foo();");
MVCR("<?php\n"
"abstract class BaseClass {"
" public static function __callStatic($name, $arguments) {"
" echo \"Calling BaseClass static method '$name' \""
" . implode(', ', $arguments). \"\\n\";"
" }"
"}"
"class SubClass extends BaseClass {"
" public static function __callStatic($name, $arguments) {"
" echo \"Calling SubClass static method '$name' \""
" . implode(', ', $arguments). \"\\n\";"
" }"
"}"
"SubClass::foo();"
"BaseClass::foo();");
MVCRO("<?php\n"
"class Base {"
" public static function __callStatic($method, $args) {"
" $klass = get_called_class();"
" echo \"class $klass\\n\";"
" }"
"}"
""
"class Derived extends Base {"
"}"
""
"Base::foo();"
"Derived::foo();",
"class Base\n"
"class Derived\n");
return true;
}
bool TestCodeRun::TestNowDoc() {
MVCR("<?php\n"
"$b = 'bad';\n"
"$a = <<<'NOWDOC'\n"
"$b\n"
"NOWDOC;\n"
"var_dump($a);\n"
"$a = <<<\"NOWDOC\"\n"
"$b\n"
"NOWDOC;\n"
"var_dump($a);\n"
"$a = <<<NOWDOC\n"
"$b\n"
"NOWDOC;\n"
"var_dump($a);\n");
MVCR("<?php\n"
"$a = <<<NOWDOC\n"
"\"'\\t\n"
"NOWDOC;\n"
"var_dump($a);\n"
"$a = <<<'NOWDOC'\n"
"\"'\\t\n"
"NOWDOC;\n"
"var_dump($a);\n"
"$a = <<<\"NOWDOC\"\n"
"\"'\\t\n"
"NOWDOC;\n"
"var_dump($a);\n");
return true;
}
bool TestCodeRun::TestTernaryShortcut() {
MVCR("<?php\n"
"function foo() { var_dump('hello'); return 789;}\n"
"$a = 123 ?: 456;\n"
"var_dump($a);\n"
"$b[123] = 456;\n"
"var_dump(isset($b[123]) ?: false);\n"
"var_dump(foo()?:123);\n");
return true;
}
bool TestCodeRun::TestGoto() {
MVCR("<?php goto a; echo 'Foo'; a: echo 'Bar';");
MVCR("<?php function foo() { goto a; echo 'Foo'; a: echo 'Bar';} foo();");
MVCR("<?php function foo() { "
"goto a; b: echo 'Foo'; return;a: echo 'Bar'; goto b;} foo();");
MVCR("<?php for($i=0,$j=50; $i<100; $i++) { "
" while($j--) { if($j==17) goto end; }"
"} "
"echo 'no'; end: echo 'yes';");
MVCR("<?php goto a; if (false) { a: print 'here';} ");
MVCR("<?php my_lbl: print 'here';");
MVCR("<?php\n"
"function fcn() { return true; }\n"
"class X {\n"
" function f($x) {\n"
" goto over_switch;\n"
" switch ($this) {\n"
" case fcn(): echo 'fcn';\n"
" default: echo 'fun';\n"
" }\n"
" over_switch: var_dump($x);\n"
" }\n"
"}\n"
"$x = new X;\n"
"$x->f(42);\n");
MVCR("<?php "
"class MyException extends Exception {}"
"class MyOtherException extends Exception {}"
"function baz($x) {"
" var_dump('baz: ' . $x);"
" if (($x & 7) == 5) throw new Exception('regular');"
" if (($x & 7) == 6) throw new MyException('mine');"
" if (($x & 7) == 7) throw new MyOtherException('other');"
"}"
"function foo($t) {"
" $e = $m = $q = new Exception('none');"
" if ($t & 8) {"
" switch ($t & 3) {"
" case 0: goto l0;"
" case 1: goto l1;"
" case 2: goto l2;"
" case 3: goto l3;"
" }"
" }"
" try {"
" var_dump('begin try1');"
" l0: var_dump('l0');"
" try {"
" var_dump('begin try2');"
" l1: var_dump('l1');"
" baz($t);"
" var_dump('after baz');"
" } catch (MyOtherException $q) {"
" var_dump($q->getMessage());"
" }"
" var_dump('after try2');"
" } catch (Exception $e) {"
" l2: var_dump($e->getMessage());"
" } catch (MyException $m) {"
" l3: var_dump($m->getMessage());"
" }"
" var_dump('after try1');"
"}"
"for ($i = 0; $i < 16; $i++) foo($i);");
MVCR("<?php "
"function g($x) {"
" var_dump($x);"
" if ($x == 123) {"
" throw new Exception();"
" }"
"}"
"function f($x) {"
" if ($x == 1) {"
" goto mylabel1;"
" } else if ($x == 2) {"
" goto mylabel2;"
" } else if ($x == 3) {"
" goto mylabel3;"
" } else if ($x == 4) {"
" goto mylabel4;"
" }"
" try {"
" g($x);"
" echo \"Should not get here\\n\";"
" try {"
" try {"
" mylabel1:"
" g($x);"
" } catch (exception $e) {"
" echo \"1a\\n\";"
" }"
" try {"
" mylabel2:"
" g($x);"
" } catch (exception $e) {"
" echo \"1b\\n\";"
" }"
" } catch (exception $e) {"
" echo \"1\\n\";"
" }"
" try {"
" try {"
" mylabel3:"
" g($x);"
" } catch (exception $e) {"
" echo \"2a\\n\";"
" }"
" try {"
" mylabel4:"
" g($x);"
" } catch (exception $e) {"
" echo \"2b\\n\";"
" }"
" } catch (exception $e) {"
" echo \"2\\n\";"
" }"
" } catch (Exception $e) {"
" echo \"0\\n\";"
" }"
"}"
"f(1);"
"f(2);"
"f(3);"
"f(4);"
"f(123);");
return true;
}
bool TestCodeRun::TestClosure() {
MVCR("<?php $a = function ($v) { return $v > 2; }; echo $a(4).\"\n\";"
" echo call_user_func_array($a, array(4));");
MVCR("<?php $a = function ($a) { return $a;}; var_dump($a(123));");
MVCR("<?php $abc = 123; $a = function () use ($abc) { var_dump($abc);}; "
"$a();");
MVCR("<?php\n"
"function foo() {\n"
" $var = 123;\n"
" $ref = 456;\n"
" $abc = 789;\n"
" $a = function () use ($var, &$ref) {\n"
" var_dump($abc, $var, $ref);\n"
" $abc = $var = $ref = 333;\n"
" };\n"
" var_dump($a());\n"
" var_dump($abc, $var, $ref);\n"
"}\n"
"foo();\n");
MVCR("<?php\n"
"$x = false;\n"
"$f = function ($arg0) use (&$x) { $x = $arg0; };\n"
"$f(32);\n"
"var_dump($x);\n");
MVCR("<?php\n"
"function f() {\n"
" $test = false;\n"
" $f = function ($p) use (&$test) {\n"
" if ($p) $test = true;\n"
" };\n"
" $f(true);\n"
" var_dump($test);\n"
"}\n"
"f();\n");
MVCR("<?php\n"
"class Foo {\n"
" function bar() {\n"
" $abc = 123;\n"
" $a = function ($abc) use ($abc) {\n"
" var_dump($abc);\n"
" };\n"
" return $a;\n"
" }\n"
"}\n"
"$a = Foo::bar();\n"
"$a(456);\n");
MVCR("<?php\n"
"class Foo {\n"
" function bar() {\n"
" $abc = 123;\n"
" $a = function ($abc) use ($abc, $abc) {\n"
" var_dump($abc);\n"
" };\n"
" return $a;\n"
" }\n"
"}\n"
"$a = Foo::bar();\n"
"$a(456);\n");
MVCR("<?php\n"
"class Foo {\n"
" function bar() {\n"
" $abc = 123;\n"
" $a = function ($abc) use (&$abc, &$abc) {\n"
" var_dump($abc);\n"
" };\n"
" return $a;\n"
" }\n"
"}\n"
"$a = Foo::bar();\n"
"$a(456);\n");
MVCR("<?php\n"
"class Foo {\n"
" function bar() {\n"
" $abc = 123;\n"
" $a = function ($x) use ($abc) {\n"
" $n = func_num_args();\n"
" $args = func_get_args();\n"
" var_dump($n, $args);\n"
" };\n"
" return $a;\n"
" }\n"
"\n"
" function baz($obj) {\n"
" $abc = 456;\n"
" $obj(789);\n"
" }\n"
"}\n"
"$a = Foo::bar();\n"
"Foo::baz($a);\n");
MVCR("<?php\n"
"class Foo {\n"
" function bar() {\n"
" $a = function () { var_dump(__CLASS__, __FUNCTION__);};\n"
" $a();\n"
" }\n"
"}\n"
"Foo::bar();\n");
MVCR("<?php\n"
"function h() {\n"
" return array_filter(array(1, 2, 3),\n"
" function($e) { return !($e & 1); });\n"
"}\n"
"h();\n"
"var_dump(h());\n");
MVCR("<?php\n"
"$v=5;"
"call_user_func("
" function() use($v) "
" { echo $v; }"
");"
"$f = function() use($v) { echo $v; };"
"call_user_func($f);"
"call_user_func_array("
" function() use($v) "
" { echo $v; }, array()"
");"
"call_user_func($f, array());");
MVCR("<?php\n"
"$myfunc = function() {"
" echo \"hello, world!\\n\";"
"};"
"$myfunc();"
"call_user_func($myfunc);"
"call_user_func_array($myfunc, array());"
"$isc = is_callable($myfunc, false, &$p);"
"echo \"is_callable(\\$myfunc) = $isc\\n\";"
"var_dump($p);");
MVCR("<?php\n"
"function f() {"
"$someVar = 456;"
"$closure = function($param) use ($someVar) {"
"echo $param . ' ' . $someVar . \"\\n\";"
"};"
"return $closure;"
"}"
"$x = f();"
"$x(2);"
"call_user_func($x, 2);");
MVCR("<?php\n"
"$my_array = array(7, 1, 5, 6);\n"
"$some_value = 6;\n"
"usort($my_array,\n"
" function($a, $b) use ($some_value) {\n"
" if ($a === $some_value) {\n"
" if ($b === $some_value) {\n"
" return 0;\n"
" } else {\n"
" return -1;\n"
" }\n"
" } else if ($b === $some_value) {\n"
" return 1;\n"
" }\n"
" if ($a < $b) return -1;\n"
" if ($a <= $b) return 0;\n"
" return 1;\n"
" }\n"
");\n");
MVCR("<?php\n"
"function f() {"
" $someVar = 456;"
" $closure = function($param) use (&$someVar) {"
" echo $param . ' ' . $someVar . \"\\n\";"
" $param = 7;"
" $someVar = 11;"
" };"
" return $closure;"
"}"
"$x = f();"
"$x(2);"
"$x(2);");
MVCR("<?php\n"
"function f() {"
" $someVar = 456;"
" $closure = function($param) use ($someVar) {"
" echo $param . ' ' . $someVar . \"\\n\";"
" $param = 7;"
" $someVar = 11;"
" };"
" return $closure;"
"}"
"$x = f();"
"$x(2);"
"$x(2);");
MVCR("<?php "
"function test($x) {"
" $s_path = serialize($x);"
" $filter = function ($rel) use ($s_path) {"
" return $s_path;"
" };"
" var_dump($filter(0));"
"}"
"test('hello');"
"test(array(1,2,'foo'=>'bar'));");
MVCR("<?php "
"function test($a, $b) {"
" return array_map(function (array $x) use ($b) {"
" var_dump($x,$b);"
" }, $a);"
"}"
"test(array(array(1), array(2)), 5);");
MVCR("<?php\n"
"function f(&$u0) {\n"
" return function () use (&$u0, $u0) { $u0++; };\n"
"}\n"
"function g(&$u0) {\n"
" return function () use ($u0, &$u0) { $u0++; };\n"
"}\n"
"$x1 = 0;\n"
"$f = f($x1);\n"
"var_dump($x1);\n"
"$f();\n"
"var_dump($x1);\n"
"\n"
"$x2 = 0;\n"
"$g = g($x2);\n"
"var_dump($x2);\n"
"$g();\n"
"var_dump($x2);\n");
MVCR("<?php\n"
"function get() { return true; }\n"
"if (get()) {\n"
" function f($x) {\n"
" return function () use ($x) { return $x; };\n"
" }\n"
"} else {\n"
" function f($x) {\n"
" return function () use ($x) { return $x + 1; };\n"
" }\n"
"}\n"
"$f = f(32);\n"
"var_dump($f());\n");
MVCR("<?php\n"
"function mkC() {\n"
" return function () {\n"
" static $x = 0;\n"
" return $x++;\n"
" };\n"
"}\n"
"$c0 = mkC();\n"
"var_dump($c0());\n"
"var_dump($c0());\n"
"\n"
"$c1 = mkC();\n"
"var_dump($c1());\n"
"var_dump($c1());\n");
MVCRO("<?php\n"
"class A {"
" public function foo() {"
" $values = array(1, 2, 3);"
" $values = array_map(function($p) use ($this) {"
" return $this->goo($p);"
" }, $values);"
" var_dump($values);"
" }"
" public function bar() { return $this; }"
" public function goo($p) { return $p; }"
"}"
"$obj = new A;"
"var_dump($obj->bar());"
"$obj->foo();",
"object(A)#1 (0) {\n"
"}\n"
"array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(2)\n"
" [2]=>\n"
" int(3)\n"
"}\n");
return true;
}
bool TestCodeRun::TestNamespace() {
MVCR("<?php\n"
"namespace my\\name;\n"
"class MyClass {}\n"
"function myfunction() {}\n"
"const MYCONST = 123;\n"
"\n"
"$a = new MyClass; var_dump(get_class($a));\n"
"$c = new \\my\\name\\MyClass; var_dump(get_class($a));\n"
"$a = strlen('hi'); var_dump($a);\n"
"$d = namespace\\MYCONST; var_dump($d);\n"
"$d = __NAMESPACE__ . '\\MYCONST'; var_dump(constant($d));\n"
"var_dump(defined('MYCONST'));\n");
MVCR("<?php\n"
"namespace foo\\baz {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace bar\\baz {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace {\n"
" use foo\\baz as baz;\n"
" baz\\foo();\n"
"}\n");
MVCR("<?php\n"
"namespace foo\\baz {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace bar\\baz {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace bar {\n"
" use foo\\baz as baz;\n"
" baz\\foo();\n"
"}\n");
MVCR("<?php\n"
" namespace foo\\baz {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace bar\\baz {\n"
" function foo() { var_dump(__NAMESPACE__);}}\n"
"namespace bar {\n"
" baz\\foo();\n"
"}\n");
MVCR("<?php\n"
"namespace {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
"}\n"
"namespace B {\n"
" foo();\n"
"}\n");
MVCR("<?php\n"
"namespace {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" foo();\n"
"}\n");
MVCR("<?php\n"
"namespace {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" \\B\\foo();\n"
"}\n");
MVCR("<?php\n"
"namespace {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" \\foo();\n"
"}\n");
MVCR("<?php\n"
"namespace {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" $a = 'foo';\n"
" $a();\n"
"}\n");
MVCR("<?php\n"
"namespace {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" function foo() { var_dump(__NAMESPACE__);}\n"
"}\n"
"namespace B {\n"
" call_user_func('foo');\n"
"}\n");
MVCR("<?php "
"namespace {"
" function fiz() { var_dump(__METHOD__); }"
" const FIZ = 25;"
" const FUZ = 1;"
"}"
"namespace foo {"
" class bar {"
" public function test() { echo __CLASS__ . PHP_EOL; }"
" }"
" const FUZ = 2;"
" class baz extends bar {"
" public function fiz() {"
" self::test();"
" parent::test();"
" static::test();"
" bar::test();"
" }"
" }"
" $x = new baz();"
" $x->fiz();"
" var_dump(true);"
" var_dump(false);"
" var_dump(null);"
" var_dump(INF);"
" var_dump(FIZ);"
" var_dump(FUZ);"
" var_dump(\\FUZ);"
"}");
MVCR("<?php\n"
"namespace A\\B;\n"
"class Foo {\n"
" static $baz = 32;\n"
" function __construct(array $a) {\n"
" var_dump($a);\n"
" }\n"
" function callUnknownClassMethod($method) {\n"
" return SomeUnknownClass::$method();\n"
" }\n"
" function unsetStaticProperty() {\n"
" unset(Foo::$baz);\n"
" }\n"
"}\n"
"if (rand(0, 1)) {\n"
" class B {\n"
" static $baz = 'baz';\n"
" const FOO = 30;\n"
" function f() {\n"
" return Foo::NoSuchConstant;\n"
" }\n"
" }\n"
"} else {\n"
" class B {\n"
" static $baz = 'baz';\n"
" const FOO = 30;\n"
" function f() {\n"
" return Foo::NoSuchConstant;\n"
" }\n"
" }\n"
"}\n"
"$f = new Foo(array(0));\n"
"var_dump(Foo::$baz);\n"
"var_dump(B::FOO);\n"
"var_dump(B::$baz);\n");
return true;
}
bool TestCodeRun::TestYield() {
HipHopSyntax w(this);
MVCRO("<?php function fruit() { yield 'apple'; yield 'banana';} "
"foreach (fruit() as $fruit) { var_dump($fruit);} ",
"string(5) \"apple\"\n"
"string(6) \"banana\"\n"
);
MVCRO("<?php class F { function fruit() { yield 'apple'; yield 'banana';} }"
"foreach (F::fruit() as $fruit) { var_dump($fruit);} ",
"string(5) \"apple\"\n"
"string(6) \"banana\"\n"
);
MVCRO("<?php class F { function fruit() { yield 'apple'; yield 'banana';} }"
"$f = new F; foreach ($f->fruit() as $fruit) { var_dump($fruit);} ",
"string(5) \"apple\"\n"
"string(6) \"banana\"\n"
);
MVCRO("<?php function fruit() { $a = 123; yield $a; yield ++$a;} "
"foreach (fruit() as $fruit) { var_dump($fruit);} ",
"int(123)\n"
"int(124)\n"
);
MVCRO("<?php function fruit() { echo \"sadpanda, no fruit\"; yield break; } "
"foreach (fruit() as $fruit) { var_dump($fruit);} ",
"sadpanda, no fruit"
);
MVCRO("<?php function fruit() { $a = 123; yield $a;yield break;yield ++$a;} "
"foreach (fruit() as $fruit) { var_dump($fruit);} ",
"int(123)\n"
);
MVCRO("<?php function nums() { for ($i = 0; $i < 3; $i++) yield $i;} "
"foreach (nums() as $num) { var_dump($num);} ",
"int(0)\n"
"int(1)\n"
"int(2)\n"
);
MVCRO("<?php function nums() { $i = 0; while ($i < 3) yield $i++;} "
"foreach (nums() as $num) { var_dump($num);} ",
"int(0)\n"
"int(1)\n"
"int(2)\n"
);
MVCRO("<?php function nums() { $i = 0; do yield $i++; while ($i < 3);} "
"foreach (nums() as $num) { var_dump($num);} ",
"int(0)\n"
"int(1)\n"
"int(2)\n"
);
MVCRO("<?php function nums() { $i = 0; foo: switch ($i) { "
"case 0: yield $i; $i = 1; case 999: yield $i; break; $i = -1; "
"case 1: $i = 2; yield $i; yield break;} goto foo;} "
"foreach (nums() as $num) { var_dump($num);} ",
"int(0)\n"
"int(1)\n"
"int(2)\n"
);
MVCRO("<?php\n"
"function f() { yield func_num_args(); yield func_get_arg(1); }\n"
"foreach (f(1, 2, 3) as $v) { var_dump($v); }\n",
"int(3)\n"
"int(2)\n"
);
MVCRO("<?php\n"
"function f($a1, &$a2) {\n"
" foreach ($a1 as $k1 => $v1) {\n"
" foreach ($a2 as $k2 => &$v2) {\n"
" $v2 += $v1; yield $v2;\n"
" }\n"
" }\n"
"}\n"
"$a1 = array(1, 2);\n"
"$a2 = array(1, 2);\n"
"foreach (f($a1, $a2) as $v) { var_dump($v); }\n"
"var_dump($a2[0], $a2[1]);\n",
"int(2)\n"
"int(3)\n"
"int(4)\n"
"int(5)\n"
"int(4)\n"
"int(5)\n");
// yield within anonymous function
MVCRO("<?php\n"
"$a = function() { yield 1; yield 2; };\n"
"foreach ($a() as $v) { var_dump($v); }\n",
"int(1)\n"
"int(2)\n");
MVCRO("<?php\n"
"function f() {\n"
" $a = function() { yield 1; yield 2; };\n"
" return $a;\n"
"}\n"
"$f = f();\n"
"foreach ($f() as $v) { var_dump($v); }\n",
"int(1)\n"
"int(2)\n");
MVCRO("<?php\n"
"class A {\n"
" function f() {\n"
" $a = function() { yield 1; yield 2; };\n"
" return $a;\n"
" }\n"
"}\n"
"$a = new A;\n"
"$f = $a->f();\n"
"foreach ($f() as $v) { var_dump($v); }\n",
"int(1)\n"
"int(2)\n");
// Continuatin::send()
MVCRO("<?php\n"
"function f() {\n"
" $a = yield 1; list($a, $b) = yield $a; yield $b;\n"
"}\n"
"$c = f();\n"
"$c->next();\n"
"var_dump($c->current());\n"
"$c->send(2);\n"
"var_dump($c->current());\n"
"$c->send(array(3, 4));\n"
"var_dump($c->current());\n",
"int(1)\n"
"int(2)\n"
"int(4)\n");
MVCRO("<?php\n"
"class A {"
" public function foo() {"
" $this->bar(function() {yield 1; yield 2; yield 3;});"
" }"
" public function bar(Closure $c) {"
" $a = $c();"
" foreach ($a as $b) {"
" echo $b.\"\\n\";"
" }"
" }"
"}"
"$a = new A();"
"$a->foo();",
"1\n"
"2\n"
"3\n");
MVCRO("<?php "
"function foo($t) {"
" $x = function() use ($t) {"
" var_dump($t);"
" yield 1;"
" };"
" foreach ($x() as $y) {"
" var_dump($y);"
" }"
"}"
"foo(42);",
"int(42)\n"
"int(1)\n");
MVCRO("<?php\n"
"function f($x) {\n"
" switch ($x++ + ++$x) {\n"
" case 1:\n"
" yield 1;\n"
" case 2:\n"
" yield 2;\n"
" case 3:\n"
" yield 3;\n"
" case 4:\n"
" yield 4;\n"
" }\n"
"}\n"
"foreach (f(0) as $x) { var_dump($x); }\n"
"foreach (f(1) as $x) { var_dump($x); }\n",
"int(2)\n"
"int(3)\n"
"int(4)\n"
"int(4)\n");
MVCRO("<?php "
"function f($x) { return $x; }"
"function foo($a) {"
" yield 1;"
" foreach ((array)f($a) as $x) {"
" var_dump('i:'.$x);"
" }"
"}"
"foreach (foo(array(1)) as $x) {"
" var_dump('o:'.$x);"
"}",
"string(3) \"o:1\"\n"
"string(3) \"i:1\"\n");
// closure generator w/ use var by ref
MVCRO("<?php\n"
"$env = 3;\n"
"$f = function ($arg0) use (&$env) {\n"
" yield $arg0;\n"
" yield $arg0 + ($env++);\n"
" yield $arg0 + ($env++) + 1;\n"
"};\n"
"foreach ($f(32) as $x) { var_dump($x); }\n"
"var_dump($env);\n",
"int(32)\n"
"int(35)\n"
"int(37)\n"
"int(5)\n");
// closure generator w/ arg by ref
MVCRO("<?php\n"
"$env = 3;\n"
"$f = function (&$arg0) use ($env) {\n"
" yield $arg0++ + $env;\n"
" yield $arg0++ + $env;\n"
"};\n"
"foreach ($f($env) as $x) {\n"
" var_dump($x);\n"
"}\n"
"var_dump($env);\n",
"int(6)\n"
"int(7)\n"
"int(5)\n");
MVCRO("<?php\n"
"class X {\n"
" public function doIt() {\n"
" throw new Exception('foobar');\n"
" }\n"
"}\n"
"function f($obj) {\n"
" $res = null;\n"
" try {\n"
" $res = $obj->doIt();\n"
" } catch (Exception $e) {\n"
" $res = $e->getMessage();\n"
" }\n"
" yield $res;\n"
"}\n"
"$x = new X;\n"
"foreach (f($x) as $i) { var_dump($i); }\n",
"string(6) \"foobar\"\n");
MVCRO("<?php\n"
"function f($x, $y) {\n"
" yield $x; \n"
" yield $$y;\n"
"}\n"
"foreach (f(10, 'x') as $x) { var_dump($x); }\n"
"function g() {\n"
" extract(func_get_args(), EXTR_PREFIX_ALL, 'foo');\n"
" yield $foo_0;\n"
" yield $foo_1;\n"
"}\n"
"foreach (g('hello', 'world') as $x) { var_dump($x); }\n"
"function h($x, $y) {\n"
" $z = 16;\n"
" $arr = compact('x', 'y', 'z');\n"
" yield $arr['z'];\n"
" yield $arr['x'];\n"
" yield $arr['y'];\n"
"}\n"
"foreach (h(32, 64) as $x) { var_dump($x); }\n"
"function i($x, $y) {\n"
" $arr = compact($x);\n"
" yield $arr[$x];\n"
"}\n"
"foreach (i('y', 32) as $x) { var_dump($x); }\n",
"int(10)\n"
"int(10)\n"
"string(5) \"hello\"\n"
"string(5) \"world\"\n"
"int(16)\n"
"int(32)\n"
"int(64)\n"
"int(32)\n");
MVCRO("<?php\n"
"// redec class gen\n"
"function get() { return true; }\n"
"if (get()) {\n"
" class X { \n"
" public function yielder() { yield 'first'; }\n"
" }\n"
"} else {\n"
" class X { \n"
" public function yielder() { yield 'second'; }\n"
" }\n"
"}\n"
"$x = new X;\n"
"foreach ($x->yielder() as $foo) { var_dump($foo); }\n"
"\n"
"// derive from redec gen\n"
"class Foo {\n"
" public function fooMsg() { return 'foo'; }\n"
" public function fooGen() { yield $this->fooMsg(); }\n"
"}\n"
"if (get()) {\n"
" class Bar extends Foo {\n"
" public function fooMsg() { return 'bar'; }\n"
" public function barMsg() { return 'bar'; }\n"
" public function barGen() { yield $this->barMsg(); }\n"
" }\n"
"} else {\n"
" class Bar extends Foo {}\n"
"}\n"
"$f = new Foo;\n"
"foreach ($f->fooGen() as $foo) { var_dump($foo); }\n"
"$b = new Bar;\n"
"foreach ($b->fooGen() as $foo) { var_dump($foo); }\n"
"foreach ($b->barGen() as $foo) { var_dump($foo); }\n"
"\n"
"// conditional derive from redec gen\n"
"function get0() { return false; }\n"
"function f($x) {\n"
" if ($x) {\n"
" if (get0()) {\n"
" class X1 {\n"
" public function msg() { return 'first, first'; }\n"
" public function gen() { yield $this->msg(); }\n"
" } \n"
" } else {\n"
" class X1 {\n"
" public function msg() { return 'first, second'; }\n"
" public function gen() { yield $this->msg(); }\n"
" } \n"
" } \n"
" } else {\n"
" if (get()) {\n"
" class Y extends X1 {\n"
" public function msg() { return 'second, first'; }\n"
" public function gen() { yield $this->msg(); }\n"
" } \n"
" } else {\n"
" class Y extends X1 {\n"
" public function msg() { return 'second, second'; }\n"
" public function gen() { yield $this->msg(); }\n"
" } \n"
" } \n"
" }\n"
" $x = $x ? new X1 : new Y;\n"
" foreach ($x->gen() as $foo) { var_dump($foo); }\n"
"}\n"
"f(true);\n"
"f(false);\n",
"string(5) \"first\"\n"
"string(3) \"foo\"\n"
"string(3) \"bar\"\n"
"string(3) \"bar\"\n"
"string(13) \"first, second\"\n"
"string(13) \"second, first\"\n");
MVCRO("<?php\n"
"function get() { return true; }\n"
"if (get()) {\n"
" function gen($i) {\n"
" yield $i;\n"
" yield $i + 1;\n"
" }\n"
"} else {\n"
" function gen($i) {\n"
" yield $i + 1;\n"
" yield $i + 2;\n"
" }\n"
"}\n"
"foreach (gen(3) as $x) { var_dump($x); }\n",
"int(3)\n"
"int(4)\n");
MVCRO("<?php\n"
"class X {\n"
" function foo($t) {\n"
" $$t = 5;\n"
" yield $this;\n"
" }\n"
"}\n"
"$x = new X;\n"
"foreach ($x->foo('this') as $v) { var_dump($v); }\n",
"int(5)\n");
// Test passing null to hphp_get_iterator()
MVCRO("<?php \n"
"function f() {\n"
" $var = hphp_get_iterator(null);\n"
" var_dump(is_null($var));\n"
" var_dump(is_object($var));\n"
" var_dump(get_class($var));\n"
"}\n"
"f();\n",
"bool(false)\n"
"bool(true)\n"
"string(13) \"ArrayIterator\"\n"
);
MVCRO("<?php "
"function foo($x = null) {"
" if ($x) $x = 'foo';"
" var_dump($x);"
" yield 1;"
" }"
"foreach(foo() as $x) {}",
"NULL\n" );
MVCRO("<?php "
"function bar($x) { return $x ? $x + 1 : false; }"
"function foo($a) {"
" $x = bar($a);"
" switch ($x) {"
" case 'hello': echo 1; break;"
" case bar(3): echo 2; break;"
" }"
" yield $x;"
"}"
"foreach(foo(3) as $x) { var_dump($x); }",
"2int(4)\n");
MVCRO("<?php\n"
"$x = 32;\n"
"$SOME_VAR = 'foo';\n"
"function f($a0, $a1, $a2, $a3) {\n"
" var_dump($a0['SOME_VAR'], $a1, $a2, $a3);\n"
"}\n"
"function g($a0, $a1, $a2, $a3) {\n"
" var_dump($a0['SOME_VAR'], $a1, $a2, $a3);\n"
"}\n"
"function h($fcn) {\n"
" global $x;\n"
" $fcn($GLOBALS, $_POST, $x, $x++);\n"
" yield 64;\n"
"}\n"
"foreach (h(rand(0, 1) ? 'f' : 'g') as $v) {\n"
" var_dump($v);\n"
"}\n",
"string(3) \"foo\"\n"
"array(0) {\n"
"}\n"
"int(32)\n"
"int(32)\n"
"int(64)\n");
// globals and statics
MVCRO("<?php\n"
"$x = 0;\n"
"function f() {\n"
" global $x;\n"
" static $y = 0;\n"
" yield $x++;\n"
" yield $y++;\n"
"}\n"
"for ($i = 0; $i < 5; $i++) {\n"
" foreach (f() as $value) {\n"
" var_dump($value);\n"
" }\n"
"}\n"
"var_dump($x);\n",
"int(0)\n"
"int(0)\n"
"int(1)\n"
"int(1)\n"
"int(2)\n"
"int(2)\n"
"int(3)\n"
"int(3)\n"
"int(4)\n"
"int(4)\n"
"int(5)\n");
MVCRO("<?php "
"class A {"
" public static function sgen() {"
" $class = get_called_class();"
" yield $class;"
" }"
" public static function sfoo() {"
" return self::gen();"
" }"
" public function gen() {"
" $class = get_called_class();"
" yield $class;"
" }"
" public function foo() {"
" return self::gen();"
" }"
"}"
"class B extends A {}"
"function t($x) { foreach ($x as $v) { var_dump($v); } }"
"t(B::sgen());"
"t(B::sfoo());"
"t(A::sgen());"
"t(A::sfoo());"
"t(B::gen());"
"t(B::foo());"
"t(A::gen());"
"t(A::foo());"
"$b = new B;"
"t($b->gen());"
"t($b->foo());"
"$a = new A;"
"t($a->gen());"
"t($a->foo());"
,
"string(1) \"B\"\n"
"string(1) \"B\"\n"
"string(1) \"A\"\n"
"string(1) \"A\"\n"
"string(1) \"B\"\n"
"string(1) \"B\"\n"
"string(1) \"A\"\n"
"string(1) \"A\"\n"
"string(1) \"B\"\n"
"string(1) \"B\"\n"
"string(1) \"A\"\n"
"string(1) \"A\"\n");
// getting the original function
MVCRO("<?php\n"
"function f($x) {\n"
" yield $x;\n"
"}\n"
"$c = f(32);\n"
"var_dump($c->getOrigFuncName());\n"
"class X {\n"
" function f($x) { yield $x; }\n"
" static function g($x) { yield get_called_class(); }\n"
"}\n"
"class Y extends X {}\n"
"$x = new X;\n"
"$c = $x->f(32);\n"
"var_dump($c->getOrigFuncName());\n"
"$c = X::g(32);\n"
"var_dump($c->getOrigFuncName());\n"
"$c = Y::g(32);\n"
"var_dump($c->getOrigFuncName());\n"
"$fcn = function ($x) { yield $x; };\n"
"$c = $fcn(32);\n"
"var_dump($c->getOrigFuncName());\n",
"string(1) \"f\"\n"
"string(4) \"X::f\"\n"
"string(4) \"X::g\"\n"
"string(4) \"Y::g\"\n"
"string(9) \"{closure}\"\n");
MVCRO("<?php "
"function gen() {"
" yield 1;"
" yield 2;"
" try {"
" $a = yield 3;"
" } catch (Exception $e) {"
" var_dump($e->getMessage());"
" yield 4;"
" }"
" yield 5;"
"}"
"foreach (gen() as $x) { var_dump($x); }"
"$g = gen();"
"$g->next();"
"var_dump($g->current());"
"$g->next();"
"var_dump($g->current());"
"$g->next();"
"var_dump($g->current());"
"$g->raise(new Exception('foobar'));"
"var_dump($g->current());"
"$g->next();"
"var_dump($g->current());"
,
"int(1)\n"
"int(2)\n"
"int(3)\n"
"int(5)\n"
"int(1)\n"
"int(2)\n"
"int(3)\n"
"string(6) \"foobar\"\n"
"int(4)\n"
"int(5)\n");
MVCRO("<?php "
"class YieldedException extends Exception {}"
"class ReflectedException extends Exception {}"
"function throwYieldedException() {"
" throw new YieldedException();"
"}"
"function gen() {"
" try {"
" $a = yield throwYieldedException();"
" echo 'Gen got '.$a;"
" } catch (YieldedException $e) {"
" var_dump('Got yieldedException, re-raising.');"
" throw $e;"
" } catch (ReflectedException $e) {"
" var_dump('Got Reflected Exception');"
" }"
"}"
"try {"
" $g = gen();"
" $g->next();"
"} catch(YieldedException $e) {"
" try {"
" $g->raise(new ReflectedException());"
" } catch (Exception $e) {"
" var_dump($e->getMessage());"
" }"
"}"
,
"string(33) \"Got yieldedException, re-raising.\"\n"
"string(32) \"Continuation is already finished\"\n");
MVCRO("<?php\n"
"function makeClosureCont() {\n"
" return function () {\n"
" static $x = 0;\n"
" yield $x++;\n"
" yield $x++;\n"
" };\n"
"}\n"
"function gen() {\n"
" static $x = 0;\n"
" yield $x++;\n"
" yield $x++;\n"
"}\n"
"$cc = makeClosureCont();\n"
"foreach ($cc() as $v) { var_dump($v); }\n"
"$cc1 = makeClosureCont();\n"
"foreach ($cc1() as $v) { var_dump($v); }\n"
"foreach (gen() as $v) { var_dump($v); }\n"
"foreach (gen() as $v) { var_dump($v); }\n",
"int(0)\n"
"int(1)\n"
"int(0)\n"
"int(1)\n"
"int(0)\n"
"int(1)\n"
"int(2)\n"
"int(3)\n");
MVCRO("<?php "
"class X {"
" public static function gen() {"
" static $x;"
" yield ++$x;"
" yield 2;"
" yield ++$x;"
" }"
"}"
"class Y extends X {}"
"$g = X::gen();"
"foreach ($g as $i) var_dump($i);"
,
"int(1)\n"
"int(2)\n"
"int(2)\n");
MVCRO("<?php "
"trait DY {"
" private $drc = array();"
""
" public function dty($key) {"
" $this->drc[$key] = true;"
" yield (true);"
" }"
" public function edd($key) {"
" if (array_key_exists($key, $this->drc)) {"
" var_dump(true);"
" } "
" }"
"}"
"class C { use DY; }"
"class D extends C { }"
"$obj = new D;"
"foreach($obj->dty('foo') as $var) {"
" var_dump($var);"
"}"
"$obj->edd('foo');",
"bool(true)\n"
"bool(true)\n");
MVCRO("<?php\n"
"trait T {"
" abstract protected function gpc();"
" public function gen() {"
" yield $this->gpc();"
" }"
"}"
"class C1 {"
" use T;"
" protected function gpc() {"
" return 1;"
" }"
"}"
"class C2 {"
" use T;"
" protected function gpc() {"
" return 2;"
" }"
"}"
"$obj1 = new C1();"
"$obj2 = new C2();"
"$c1 = $obj1->gen();"
"$c2 = $obj2->gen();"
"$c1->next();"
"var_dump($c1->current());"
"$c2->next();"
"var_dump($c2->current());",
"int(1)\n"
"int(2)\n");
MVCRO("<?php "
"function foo($results) {"
" yield 0;"
" foreach ($results as &$result) {"
" $result->foo = 1;"
" }"
" var_dump($results);"
" yield 1;"
"}"
"function bar() {"
" foreach (foo(array()) as $r) {"
" var_dump($r);"
" }"
"}"
"bar();",
"int(0)\n"
"array(0) {\n"
"}\n"
"int(1)\n");
MVCRO("<?php"
"class X {"
" private $a = array(1,2,3);"
" function foo() { yield $this->a; }"
"}"
"if (isset($g)) {"
" class Y {}"
"} else {"
" class Y extends X {}"
"}"
"class Z extends Y {}"
"function test() {"
" $z = new Z;"
" foreach ($z->foo() as $v) {"
" var_dump($v);"
" }"
"}"
"test();",
"array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(2)\n"
" [2]=>\n"
" int(3)\n"
"}\n");
// Testing destructor/assignment corner cases
MVCRO("<?php\n"
"\n"
"class Evil {\n"
" public function __destruct() {\n"
" echo \"in __destruct()\\n\";\n"
" try {\n"
" dumpCurrent();\n"
" } catch (Exception $e) {\n"
" printf(\"Caught: %s\\n\", $e->getMessage());\n"
" }\n"
" }\n"
"}\n"
"function dumpCurrent() {\n"
" var_dump($GLOBALS['cont']->current());\n"
" if (isset($GLOBALS['gonext'])) {\n"
" $GLOBALS['cont']->next();\n"
" }\n"
"}\n"
"function gen() {\n"
" yield new Evil;\n"
" yield null;\n"
" yield null;\n"
" yield null;\n"
"}\n"
"function main() {\n"
" $GLOBALS['cont'] = $c = gen();\n"
" $c->next();\n"
"\n"
" $c->send(new Evil);\n"
" $GLOBALS['gonext'] = true;\n"
" $c->next();\n"
" $c->send(new Evil);\n"
" $c->send(null);\n"
" echo \"Finished!\\n\";\n"
"}\n"
"main();\n"
"echo \"Returned from main safely\\n\";\n"
,
"in __destruct()\n"
"NULL\n"
"in __destruct()\n"
"NULL\n"
"Caught: Continuation is already running\n"
"in __destruct()\n"
"NULL\n"
"Caught: Continuation is already running\n"
"Finished!\n"
"Returned from main safely\n");
MVCRO("<?php\n"
"class Foo implements Iterator {\n"
" private $data = array(1, 2, 3);\n"
"\n"
" public function current() {\n"
" return current($this->data);\n"
" }\n"
" public function key() {\n"
" return key($this->data);\n"
" }\n"
" public function next() {\n"
" next($this->data);\n"
" }\n"
" public function rewind() {\n"
" echo \"hagfish\\n\";\n"
" reset($this->data);\n"
" }\n"
" public function valid() {\n"
" return current($this->data);\n"
" }\n"
"}\n"
"\n"
"function run_test() {\n"
" $f = new Foo();\n"
"\n"
" foreach ($f as $value) {\n"
" echo $value . \"\\n\";\n"
" }\n"
"\n"
" yield 1230;\n"
"\n"
" foreach($f as $value) {\n"
" echo $value . \"\\n\";\n"
" }\n"
"}\n"
"\n"
"foreach (run_test() as $_) {}\n",
"hagfish\n1\n2\n3\nhagfish\n1\n2\n3\n");
MVCRO("<?php\n"
"function gen(int $mode) {\n"
" yield $mode;\n"
" switch ($mode) {\n"
" case 0: break;\n"
" case 1: yield break;\n"
" case 2: throw new Exception();\n"
" }\n"
" yield 47;\n"
"}\n"
"\n"
"for ($mode = 0; $mode < 3; ++$mode) {\n"
" echo \"Testing mode $mode:\\n\";\n"
" $gen = gen($mode);\n"
" try {\n"
" $gen->next();\n"
" while ($gen->valid()) {\n"
" var_dump($gen->current());\n"
" $gen->next();\n"
" }\n"
" } catch (Exception $ex) {\n"
" echo \"EXCEPTION\\n\";\n"
" }\n"
" var_dump($gen->valid());\n"
" var_dump($gen->current());\n"
"}\n",
"Testing mode 0:\n"
"int(0)\n"
"int(47)\n"
"bool(false)\n"
"NULL\n"
"Testing mode 1:\n"
"int(1)\n"
"bool(false)\n"
"NULL\n"
"Testing mode 2:\n"
"int(2)\n"
"EXCEPTION\n"
"bool(false)\n"
"NULL\n");
return true;
}
bool TestCodeRun::TestHint() {
MVCR("<?php "
"class bool{}"
"class boolean{}"
"class int{}"
"class integer{}"
"class double{}"
"class float{}"
"class real{}"
"class string {}"
"function foo(bool $b1, boolean $b2,"
" int $i1, integer $i2,"
" double $d1, float $d2, real $d3,"
" string $s) {"
" var_dump(func_get_args());"
"}"
"foo(new bool, new boolean,"
" new int, new integer,"
" new double, new float, new real,"
" new string);");
HipHopSyntax w(this);
MVCRO("<?php\n"
"function f1(int $i = 1) { var_dump($i); }\n"
"function f2(double $d = 5.5) { var_dump($d); }\n"
"function f3(bool $b = true) { var_dump($b); }\n"
"function f4(string $s = 'hello') { var_dump($s); }\n"
"f1(); f2(); f3(); f4();\n",
"int(1)\n"
"float(5.5)\n"
"bool(true)\n"
"string(5) \"hello\"\n");
MVCRO("<?php "
"g(DATE_COOKIE);"
"f(count(array()));"
"function f(int $i) {"
" var_dump($i);"
"}"
"function g(string $s) {"
" var_dump($s);"
"}",
"string(16) \"l, d-M-y H:i:s T\"\n"
"int(0)\n");
MVCRO("<?php\n"
"class Foo {"
" const BAR = 1;"
"}"
"function test(int $a = -Foo::BAR) {"
"return $a;"
"}"
"var_dump(test());"
"var_dump(test(2));",
"int(-1)\n"
"int(2)\n");
MVCRO("<?php\n"
"class C{}\n"
"function f1(string $x = null) {"
"$y = (string) $x; var_dump($y); return $y; }\n"
"function f2(array $x = null) {"
"$y = (array) $x; var_dump($y); return $y; }\n"
"function f3(C $x = null) {"
"$y = (object) $x; var_dump($y); return $y; }\n"
"function f4(int $x = null) {"
"$y = (int) $x; var_dump($y); return $y; }\n"
"function f5(bool $x = null) {"
"$y = (bool) $x; var_dump($y); return $y; }\n"
"function f6(double $x = null) {"
"$y = (double) $x; var_dump($y); return $y; }\n"
"var_dump(f1()); var_dump(f2()); var_dump(f3()); \n"
"var_dump(f4()); var_dump(f5()); var_dump(f6());\n"
"var_dump(f1(null)); var_dump(f2(null)); var_dump(f3(null));\n"
"var_dump(f4(null)); var_dump(f5(null)); var_dump(f6(null));\n"
"function rf1($x) { if ($x) return 'f1'; return 0; }\n"
"function rf2($x) { if ($x) return 'f2'; return 0; }\n"
"function rf3($x) { if ($x) return 'f3'; return 0; }\n"
"function rf4($x) { if ($x) return 'f4'; return 0; }\n"
"function rf5($x) { if ($x) return 'f5'; return 0; }\n"
"function rf6($x) { if ($x) return 'f6'; return 0; }\n"
"var_dump(call_user_func(rf1(true)));\n"
"var_dump(call_user_func(rf2(true)));\n"
"var_dump(call_user_func(rf3(true)));\n"
"var_dump(call_user_func(rf4(true)));\n"
"var_dump(call_user_func(rf5(true)));\n"
"var_dump(call_user_func(rf6(true)));\n"
"var_dump(call_user_func(rf1(true), null));\n"
"var_dump(call_user_func(rf2(true), null));\n"
"var_dump(call_user_func(rf3(true), null));\n"
"var_dump(call_user_func(rf4(true), null));\n"
"var_dump(call_user_func(rf5(true), null));\n"
"var_dump(call_user_func(rf6(true), null));\n"
"var_dump(call_user_func_array(rf1(true), array()));\n"
"var_dump(call_user_func_array(rf2(true), array()));\n"
"var_dump(call_user_func_array(rf3(true), array()));\n"
"var_dump(call_user_func_array(rf4(true), array()));\n"
"var_dump(call_user_func_array(rf5(true), array()));\n"
"var_dump(call_user_func_array(rf6(true), array()));\n"
"var_dump(call_user_func_array(rf1(true), array(null)));\n"
"var_dump(call_user_func_array(rf2(true), array(null)));\n"
"var_dump(call_user_func_array(rf3(true), array(null)));\n"
"var_dump(call_user_func_array(rf4(true), array(null)));\n"
"var_dump(call_user_func_array(rf5(true), array(null)));\n"
"var_dump(call_user_func_array(rf6(true), array(null)));\n",
"string(0) \"\"\n"
"string(0) \"\"\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"int(0)\n"
"int(0)\n"
"bool(false)\n"
"bool(false)\n"
"float(0)\n"
"float(0)\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"int(0)\n"
"int(0)\n"
"bool(false)\n"
"bool(false)\n"
"float(0)\n"
"float(0)\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"int(0)\n"
"int(0)\n"
"bool(false)\n"
"bool(false)\n"
"float(0)\n"
"float(0)\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"int(0)\n"
"int(0)\n"
"bool(false)\n"
"bool(false)\n"
"float(0)\n"
"float(0)\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"int(0)\n"
"int(0)\n"
"bool(false)\n"
"bool(false)\n"
"float(0)\n"
"float(0)\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"object(stdClass)#1 (0) {\n"
"}\n"
"int(0)\n"
"int(0)\n"
"bool(false)\n"
"bool(false)\n"
"float(0)\n"
"float(0)\n");
MVCRO("<?php\n"
"$WHICH = 0;\n"
"function decide() {\n"
" global $WHICH;\n"
" return $WHICH;\n"
"}\n"
"if (decide()) {\n"
" class X {\n"
" public function generator() {\n"
" yield 0;\n"
" yield 1;\n"
" }\n"
" }\n"
"} else {\n"
" class X {\n"
" public function generator() {\n"
" yield 1;\n"
" yield 2;\n"
" }\n"
" }\n"
"}\n"
"$x = new X;\n"
"foreach ($x->generator() as $v) {\n"
" var_dump($v);\n"
"}\n",
"int(1)\n"
"int(2)\n");
MVCRO("<?php\n"
"class C {}\n"
"class D {}\n"
"class X {\n"
" public function f($x1, $x2 = null, $x3 = 123, string $x4,\n"
" string $x5 = null, string $x6 = \"abc\",\n"
" array $x7, array $x8 = null, C $x9, \n"
" D $x10 = null, bool $x11, boolean $x12 = true, \n"
" int $x13, integer $x14 = 73, real $x15, \n"
" double $x16 = 1.5, float $x17) {}\n"
"}\n"
"function main() {\n"
" $rc = new ReflectionClass('X');\n"
" $rf = $rc->getMethod('f');\n"
" $params = $rf->getParameters();\n"
" $first = true;\n"
"\n"
" $clsDecl = \"class Y extends X {\npublic function f(\";\n"
" foreach ($params as $rp) {\n"
" if (!$first) $clsDecl .= ', ';\n"
" $first = false;\n"
" $th = $rp->getTypehintText();\n"
" if ($th) {\n"
" $clsDecl .= ($th . ' ');\n"
" }\n"
" $clsDecl .= ('$' . $rp->getName());\n"
" if ($rp->isDefaultValueAvailable()) {\n"
" $clsDecl .= (' = ' . $rp->getDefaultValueText());\n"
" }\n"
" }\n"
" $clsDecl .= \") {}\n}\n\";\n"
" echo $clsDecl;\n"
"}\n"
"main();\n"
,
"class Y extends X {\n"
"public function f($x1, $x2 = NULL, $x3 = 123, string $x4, "
"string $x5 = NULL, string $x6 = \"abc\", array $x7, array $x8 = NULL, "
"C $x9, D $x10 = NULL, bool $x11, boolean $x12 = true, int $x13, "
"integer $x14 = 73, real $x15, double $x16 = 1.5, float $x17) {}\n"
"}\n"
);
return true;
}
bool TestCodeRun::TestUserAttributes() {
HipHopSyntax w(this);
MVCRO("<?php\n"
"final class B {\n"
" final public function foo() { echo \"B::foo\\n\"; }\n"
" final public static function bar() { echo \"B::bar\\n\"; }\n"
"}\n"
"<< __MockClass >>\n"
"class C extends B {\n"
" public function foo() { echo \"C::foo\\n\"; }\n"
" public static function bar() { echo \"C::bar\\n\"; }\n"
"}\n"
"function test() {\n"
" $obj = new C;\n"
" $obj->foo();\n"
" C::bar();\n"
"}\n"
"test();\n"
,
"C::foo\n"
"C::bar\n");
MVCRO("<?php\n"
"<< Foo1, Bar1(), Baz1('blah',array(1,2)) >> interface I {}\n"
"<< Foo2, Bar2(), Baz2('blah',array(1,2)) >> trait T {}\n"
"<< Foo3, Bar3(), Baz3('blah',array(1,2)) >> function f() {}\n"
"<< Foo4, Bar4(), Baz4('blah',array(1,2)) >>\n"
"function g() { yield null; }\n"
"class C {\n"
" << Foo5, Bar5(), Baz5('blah',array(1,2)) >>\n"
" public function f() {}\n"
" << Foo6, Bar6(), Baz6('blah',array(1,2)) >>\n"
" public function g() { yield null; }\n"
"}\n"
"echo \"Done\\n\";\n"
,
"Done\n");
MVCRO("<?php\n"
"<<A(1),B('foo',array(42,73))>>\n"
"class C {\n"
" <<A(2),B('bar',array(43,74))>>\n"
" function f() {}\n"
"}\n"
"$rc = new ReflectionClass('C');\n"
"$attrs = $rc->getAttributes();\n"
"ksort($attrs);\n"
"var_dump($attrs);\n"
"$rm = $rc->getMethod('f');\n"
"$attrs = $rm->getAttributes();\n"
"ksort($attrs);\n"
"var_dump($attrs);\n"
"\n"
"<<A(3),B('bar',array(44,75))>>\n"
"function f() {}\n"
"$rf = new ReflectionFunction('f');\n"
"$attrs = $rf->getAttributes();\n"
"ksort($attrs);\n"
"var_dump($attrs);\n"
,
"array(2) {\n"
" [\"A\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(1)\n"
" }\n"
" [\"B\"]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" array(2) {\n"
" [0]=>\n"
" int(42)\n"
" [1]=>\n"
" int(73)\n"
" }\n"
" }\n"
"}\n"
"array(2) {\n"
" [\"A\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(2)\n"
" }\n"
" [\"B\"]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(3) \"bar\"\n"
" [1]=>\n"
" array(2) {\n"
" [0]=>\n"
" int(43)\n"
" [1]=>\n"
" int(74)\n"
" }\n"
" }\n"
"}\n"
"array(2) {\n"
" [\"A\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(3)\n"
" }\n"
" [\"B\"]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(3) \"bar\"\n"
" [1]=>\n"
" array(2) {\n"
" [0]=>\n"
" int(44)\n"
" [1]=>\n"
" int(75)\n"
" }\n"
" }\n"
"}\n");
MVCRO("<?php\n"
"<<A(1)>>\n"
"function f() {}\n"
"$rf = new ReflectionFunction('f');\n"
"var_dump($rf->getAttribute('A'));\n"
"var_dump($rf->getAttribute('B'));\n"
"var_dump($rf->getAttributes());\n"
"var_dump($rf->getAttributeRecursive('A'));\n"
"var_dump($rf->getAttributeRecursive('B'));\n"
"var_dump($rf->getAttributesRecursive());\n"
,
"array(1) {\n"
" [0]=>\n"
" int(1)\n"
"}\n"
"NULL\n"
"array(1) {\n"
" [\"A\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(1)\n"
" }\n"
"}\n"
"array(1) {\n"
" [0]=>\n"
" int(1)\n"
"}\n"
"NULL\n"
"array(1) {\n"
" [\"A\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(1)\n"
" }\n"
"}\n");
MVCRO("<?php\n"
"class A {\n"
" <<W(1),X(2)>>\n"
" private function foo() {}\n"
"}\n"
"class B extends A {}\n"
"class C extends B {\n"
" <<X(3),Y(4)>>\n"
" protected function foo() {}\n"
"}\n"
"class D extends C {}\n"
"class E extends D {\n"
" <<Y(5),Z(6)>>\n"
" public function foo() {}\n"
"}\n"
"class F extends E {}\n"
"\n"
"$rm = new ReflectionMethod('F', 'foo');\n"
"\n"
"var_dump($rm->getAttribute('W'));\n"
"var_dump($rm->getAttribute('X'));\n"
"var_dump($rm->getAttribute('Y'));\n"
"var_dump($rm->getAttribute('Z'));\n"
"\n"
"$attrs = $rm->getAttributes();\n"
"ksort($attrs);\n"
"var_dump($attrs);\n"
"\n"
"var_dump($rm->getAttributeRecursive('W'));\n"
"var_dump($rm->getAttributeRecursive('X'));\n"
"var_dump($rm->getAttributeRecursive('Y'));\n"
"var_dump($rm->getAttributeRecursive('Z'));\n"
"\n"
"$attrs = $rm->getAttributesRecursive();\n"
"ksort($attrs);\n"
"var_dump($attrs);\n"
,
"NULL\n"
"NULL\n"
"array(1) {\n"
" [0]=>\n"
" int(5)\n"
"}\n"
"array(1) {\n"
" [0]=>\n"
" int(6)\n"
"}\n"
"array(2) {\n"
" [\"Y\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(5)\n"
" }\n"
" [\"Z\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(6)\n"
" }\n"
"}\n"
"NULL\n"
"array(1) {\n"
" [0]=>\n"
" int(3)\n"
"}\n"
"array(1) {\n"
" [0]=>\n"
" int(5)\n"
"}\n"
"array(1) {\n"
" [0]=>\n"
" int(6)\n"
"}\n"
"array(3) {\n"
" [\"X\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(3)\n"
" }\n"
" [\"Y\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(5)\n"
" }\n"
" [\"Z\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" int(6)\n"
" }\n"
"}\n");
MVCRO("<?php\n"
"function get_rf_for_method($fn, $class) {\n"
" $rc = new ReflectionClass($class);\n"
" return $rc->getMethod($fn);\n"
"}\n"
"\n"
"function show($fn, $class=null) {\n"
" $rf = null;\n"
" if ($class) {\n"
" $rf = get_rf_for_method($fn, $class);\n"
" } else {\n"
" $rf = new ReflectionFunction($fn);\n"
" }\n"
" $params = $rf->getParameters();\n"
" foreach ($params as $param) {\n"
" echo \"{$param->getName()}:\\n\";\n"
" $attrs = $param->getAttributes();\n"
" ksort($attrs);\n"
" var_dump($attrs);\n"
" }\n"
"}\n"
"\n"
"function showr($fn, $class=null) {\n"
" $rf = null;\n"
" if ($class) {\n"
" $rf = get_rf_for_method($fn, $class);\n"
" } else {\n"
" $rf = new ReflectionFunction($fn);\n"
" }\n"
" $params = $rf->getParameters();\n"
" foreach ($params as $param) {\n"
" echo \"{$param->getName()}:\\n\";\n"
" $attrs = $param->getAttributesRecursive();\n"
" ksort($attrs);\n"
" var_dump($attrs);\n"
" }\n"
"}\n"
"\n"
"function doboth($fn, $class=null) {\n"
" echo \">>> \";\n"
" if ($class) echo \"$class::\";\n"
" echo \"$fn =>\\n---- non-recursive: ----\\n\";\n"
" show($fn, $class);\n"
" echo \"\\n---- recursive: ----\\n\";\n"
" showr($fn, $class);\n"
" echo \"\\n\";\n"
"}\n"
"\n"
"//------------------------\n"
"\n"
"function no_attrs($p1, $p2) {}\n"
"function simple_attr(<<Attribute>> $param) {}\n"
"function two_attrs(<<Attr1>> $p1, <<Attr2>> $p2) {}\n"
"\n"
"class C {\n"
" public static function m(<<Attr(1,2,3)>> $param) {}\n"
" public static function n(<<Foo, Bar>> $param) {}\n"
" public function o(<<Hi('bye')>> $param) {}\n"
" public function p(<<A('b', array('c', 'd')), E('fg')>> $param) {}\n"
" public function q(<<RS>> $tuv) {}\n"
" public function wxy(<<And_>> $z, <<NextTime>> $wont_you_sing_with_me) {}\n"
"}\n"
"\n"
"class D extends C {\n"
" // Static functions shouldn't care about the parent class\n"
" public static function m($param) {}\n"
"\n"
" // TODO: should we include n, and should m's attrs inherit from C::m?\n"
"\n"
" // Changing the value of the attribute\n"
" public function o(<<Hi('hello')>> $param) {}\n"
"\n"
" // Changing the name of the parameter\n"
" public function q($rstuv) {}\n"
"\n"
" // Adding an attribute and leaving one off\n"
" public function wxy(<<EnglishPeopleCallThisZed>> $z, $wont_you_sing_with_me) {}\n"
"}\n"
"\n"
"//------------------------\n"
"\n"
"doboth('no_attrs');\n"
"doboth('simple_attr');\n"
"doboth('two_attrs');\n"
"doboth('m', 'C');\n"
"doboth('n', 'C');\n"
"doboth('o', 'C');\n"
"doboth('p', 'C');\n"
"doboth('q', 'C');\n"
"doboth('wxy', 'C');\n"
"doboth('m', 'D');\n"
"doboth('n', 'D');\n"
"doboth('o', 'D');\n"
"doboth('p', 'D');\n"
"doboth('q', 'D');\n"
"doboth('wxy', 'D');"
,
">>> no_attrs =>\n"
"---- non-recursive: ----\n"
"p1:\n"
"array(0) {\n"
"}\n"
"p2:\n"
"array(0) {\n"
"}\n"
"\n"
"---- recursive: ----\n"
"p1:\n"
"array(0) {\n"
"}\n"
"p2:\n"
"array(0) {\n"
"}\n"
"\n"
">>> simple_attr =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Attribute\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Attribute\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
">>> two_attrs =>\n"
"---- non-recursive: ----\n"
"p1:\n"
"array(1) {\n"
" [\"Attr1\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"p2:\n"
"array(1) {\n"
" [\"Attr2\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"p1:\n"
"array(1) {\n"
" [\"Attr1\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"p2:\n"
"array(1) {\n"
" [\"Attr2\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
">>> C::m =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Attr\"]=>\n"
" array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(2)\n"
" [2]=>\n"
" int(3)\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Attr\"]=>\n"
" array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(2)\n"
" [2]=>\n"
" int(3)\n"
" }\n"
"}\n"
"\n"
">>> C::n =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(2) {\n"
" [\"Bar\"]=>\n"
" array(0) {\n"
" }\n"
" [\"Foo\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(2) {\n"
" [\"Bar\"]=>\n"
" array(0) {\n"
" }\n"
" [\"Foo\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
">>> C::o =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Hi\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(3) \"bye\"\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Hi\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(3) \"bye\"\n"
" }\n"
"}\n"
"\n"
">>> C::p =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(2) {\n"
" [\"A\"]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(1) \"b\"\n"
" [1]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(1) \"c\"\n"
" [1]=>\n"
" string(1) \"d\"\n"
" }\n"
" }\n"
" [\"E\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(2) \"fg\"\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(2) {\n"
" [\"A\"]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(1) \"b\"\n"
" [1]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(1) \"c\"\n"
" [1]=>\n"
" string(1) \"d\"\n"
" }\n"
" }\n"
" [\"E\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(2) \"fg\"\n"
" }\n"
"}\n"
"\n"
">>> C::q =>\n"
"---- non-recursive: ----\n"
"tuv:\n"
"array(1) {\n"
" [\"RS\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"tuv:\n"
"array(1) {\n"
" [\"RS\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
">>> C::wxy =>\n"
"---- non-recursive: ----\n"
"z:\n"
"array(1) {\n"
" [\"And_\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"wont_you_sing_with_me:\n"
"array(1) {\n"
" [\"NextTime\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"z:\n"
"array(1) {\n"
" [\"And_\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"wont_you_sing_with_me:\n"
"array(1) {\n"
" [\"NextTime\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
">>> D::m =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(0) {\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Attr\"]=>\n"
" array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(2)\n"
" [2]=>\n"
" int(3)\n"
" }\n"
"}\n"
"\n"
">>> D::n =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(2) {\n"
" [\"Bar\"]=>\n"
" array(0) {\n"
" }\n"
" [\"Foo\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(2) {\n"
" [\"Bar\"]=>\n"
" array(0) {\n"
" }\n"
" [\"Foo\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
">>> D::o =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Hi\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(5) \"hello\"\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(1) {\n"
" [\"Hi\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(5) \"hello\"\n"
" }\n"
"}\n"
"\n"
">>> D::p =>\n"
"---- non-recursive: ----\n"
"param:\n"
"array(2) {\n"
" [\"A\"]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(1) \"b\"\n"
" [1]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(1) \"c\"\n"
" [1]=>\n"
" string(1) \"d\"\n"
" }\n"
" }\n"
" [\"E\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(2) \"fg\"\n"
" }\n"
"}\n"
"\n"
"---- recursive: ----\n"
"param:\n"
"array(2) {\n"
" [\"A\"]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(1) \"b\"\n"
" [1]=>\n"
" array(2) {\n"
" [0]=>\n"
" string(1) \"c\"\n"
" [1]=>\n"
" string(1) \"d\"\n"
" }\n"
" }\n"
" [\"E\"]=>\n"
" array(1) {\n"
" [0]=>\n"
" string(2) \"fg\"\n"
" }\n"
"}\n"
"\n"
">>> D::q =>\n"
"---- non-recursive: ----\n"
"rstuv:\n"
"array(0) {\n"
"}\n"
"\n"
"---- recursive: ----\n"
"rstuv:\n"
"array(1) {\n"
" [\"RS\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n"
">>> D::wxy =>\n"
"---- non-recursive: ----\n"
"z:\n"
"array(1) {\n"
" [\"EnglishPeopleCallThisZed\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"wont_you_sing_with_me:\n"
"array(0) {\n"
"}\n"
"\n"
"---- recursive: ----\n"
"z:\n"
"array(2) {\n"
" [\"And_\"]=>\n"
" array(0) {\n"
" }\n"
" [\"EnglishPeopleCallThisZed\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"wont_you_sing_with_me:\n"
"array(1) {\n"
" [\"NextTime\"]=>\n"
" array(0) {\n"
" }\n"
"}\n"
"\n");
return true;
}
#ifdef TAINTED
#define INIT_TEST_TAINT_HELPERS \
"$taint_counter = 0;\n" \
"function assert_tainted($str, $taint) {\n" \
" global $taint_counter;\n" \
" if (!fb_get_taint($str, $taint)) {\n" \
" var_dump($taint_counter);\n" \
" }\n" \
" $taint_counter++;" \
"}\n" \
"function assert_not_tainted($str, $taint) {\n" \
" global $taint_counter;\n" \
" if (fb_get_taint($str, $taint)) {\n" \
" var_dump($taint_counter);\n" \
" }\n" \
" $taint_counter++;" \
"}\n"
// We reconstruct our strings to ensure they aren't ever treated as
// literals by hphp.
#define INIT_TEST_TAINT_STRINGS \
"$tmp = \"heLlO\\nworld\\ntoto\\narent\\ntaTa\";\n" \
"$good1 = '';\n" \
"for ($i = 0; $i < strlen($tmp); $i++) {\n" \
" $good1 .= $tmp[$i];\n" \
"}\n" \
"$tmp = 'world';\n" \
"$good2 = '';\n" \
"for ($i = 0; $i < strlen($tmp); $i++) {\n" \
" $good2 .= $tmp[$i];\n" \
"}\n" \
"$tmp = \"eViL\\nsTring\\nare\\tfun\\narent\\tworld?\";\n" \
"$bad1 = '';\n" \
"for ($i = 0; $i < strlen($tmp); $i++) {\n" \
" $bad1 .= $tmp[$i];\n" \
"}\n" \
"$tmp = 'arent';\n" \
"$bad2 = '';\n" \
"for ($i = 0; $i < strlen($tmp); $i++) {\n" \
" $bad2 .= $tmp[$i];\n" \
"}\n" \
"unset($tmp);\n" \
"fb_set_taint($bad1, TAINT_ALL);\n" \
"fb_set_taint($bad2, TAINT_ALL);\n"
bool TestCodeRun::TestTaint() {
HipHopSyntax w(this);
// Literals and assignments
MVCRO("<?php\n"
"var_dump(fb_get_taint('foostr', TAINT_ALL));\n"
"$a = 'foostr';\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"$b = $a;\n"
"var_dump(fb_get_taint($b, TAINT_ALL));\n",
"bool(false)\n"
"bool(false)\n"
"bool(false)\n");
// Functions and classes
MVCRO("<?php\n"
"$tmp = 'foostr';\n"
"$a = '';\n"
"$b = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $a .= $tmp[$i];\n"
"}\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $b .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($b, TAINT_ALL);\n"
"function foo($a, $b) {\n"
" var_dump(fb_get_taint($a, TAINT_ALL));\n"
" var_dump(fb_get_taint($b, TAINT_ALL));\n"
" $a .= $b;\n"
" return $a;\n"
"}\n"
"foo($a, $b);"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint($b, TAINT_ALL));\n"
"class Foo {\n"
" const FOO = 'foostr';\n"
" public $m_a, $m_b;\n"
" function __construct($a, $b) {\n"
" $this->m_a = $a;\n"
" $this->m_b = $b;\n"
" }\n"
" function test() {\n"
" var_dump(fb_get_taint($this->m_a, TAINT_ALL));\n"
" var_dump(fb_get_taint($this->m_b, TAINT_ALL));\n"
" }\n"
"}\n"
"$foo = new Foo($a, $b);\n"
"$foo->test();\n"
"var_dump(fb_get_taint(Foo::FOO, TAINT_ALL));\n" ,
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n");
// Copy-on-taint and taint independence
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$a = 'foostr';\n"
"$b = 'foostr';\n"
"$c = $b;\n"
"assert_not_tainted('foostr', TAINT_ALL);\n"
"assert_not_tainted($a, TAINT_ALL);\n"
"assert_not_tainted($b, TAINT_ALL);\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"fb_set_taint($a, TAINT_ALL);\n"
"assert_not_tainted('foostr', TAINT_ALL);\n"
"assert_tainted($a, TAINT_ALL);\n"
"assert_not_tainted($b, TAINT_ALL);\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"fb_set_taint($b, TAINT_ALL);\n"
"assert_not_tainted('foostr', TAINT_ALL);\n"
"assert_tainted($a, TAINT_ALL);\n"
"assert_tainted($b, TAINT_ALL);\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"fb_unset_taint($a, TAINT_ALL);\n"
"assert_not_tainted('foostr', TAINT_ALL);\n"
"assert_not_tainted($a, TAINT_ALL);\n"
"assert_tainted($b, TAINT_ALL);\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"fb_set_taint($c, TAINT_ALL);\n"
"fb_unset_taint($b, TAINT_ALL);\n"
"assert_not_tainted('foostr', TAINT_ALL);\n"
"assert_not_tainted($a, TAINT_ALL);\n"
"assert_not_tainted($b, TAINT_ALL);\n"
"assert_tainted($c, TAINT_ALL);\n"
"if ($a === $c) {\n"
" $a = $b;\n"
"}\n"
"assert_not_tainted($a, TAINT_ALL);\n"
"$c = 'barstr';\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"$a = 'foostr';\n"
"fb_set_taint($a, TAINT_HTML);\n"
"$b = $a;\n"
"fb_set_taint($b, TAINT_MUTATED);\n"
"assert_not_tainted('foostr', TAINT_HTML);\n"
"assert_tainted($a, TAINT_HTML);\n"
"assert_tainted($b, TAINT_HTML);\n"
"assert_not_tainted('foostr', TAINT_MUTATED);\n"
"assert_not_tainted($a, TAINT_MUTATED);\n"
"assert_tainted($b, TAINT_MUTATED);\n",
"");
// Clean concatenations
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$tmp = 'foo';\n"
"$a = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $a .= $tmp[$i];\n"
"}\n"
"$tmp = 'str';\n"
"$b = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $b .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"$c = 'foo' . 'str';\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"$c = 'foo' . $b;\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"$c = $a . 'str';\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"$c = $a . $b;\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"$c = '';\n"
"$c .= 'foostr';\n"
"assert_not_tainted($c, TAINT_ALL);\n"
"$c = '';\n"
"$c .= $a;\n"
"assert_not_tainted($c, TAINT_ALL);\n",
"");
// Taint propagation in concatenations
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"$a = $good1 . $good2;\n"
"assert_not_tainted($a, TAINT_ALL);\n"
"$a = $good1 . $bad1;\n"
"assert_tainted($a, TAINT_ALL);\n"
"$a = $bad1 . $good1;\n"
"assert_tainted($a, TAINT_ALL);\n"
"$a = $bad1 . $bad2;\n"
"assert_tainted($a, TAINT_ALL);\n"
"$a = $good1;\n"
"$a .= $good2;\n"
"assert_not_tainted($a, TAINT_ALL);\n"
"$a = $good1;\n"
"$a .= $bad1;\n"
"assert_tainted($a, TAINT_ALL);\n"
"$a = $bad1;\n"
"$a .= $good1;\n"
"assert_tainted($a, TAINT_ALL);\n"
"$a = $bad1;\n"
"$a .= $bad2;\n"
"assert_tainted($a, TAINT_ALL);\n"
"$a = \"$good1$good2\";\n"
"assert_not_tainted($a, TAINT_ALL);\n"
"$a = \"$good1$bad1\";\n"
"assert_tainted($a, TAINT_ALL);\n"
"$a = \"$bad1$good1\";\n"
"assert_tainted($a, TAINT_ALL);\n"
"$a = \"$bad1$bad2\";\n"
"assert_tainted($a, TAINT_ALL);\n",
"");
// Long concatenations
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$tmp = 'foostr';\n"
"$a = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $a .= $tmp[$i];\n"
"}\n"
"$tmp = 'badstr';\n"
"$b = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $b .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($b, TAINT_ALL);\n"
"$c = $a . $b;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $b . $a . $a;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $a . $b . $a;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $a . $a . $b;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $a . $a . $a . $b;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $a . $a . $a . $a . $b;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $a . $a . $a . $a . $a . $b;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $a . $a . $a . $a . $a . $a . $b;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $a . $a . $a . $a . $a . $a . $a . $b;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = $a . $a . $b . $a . $a . $a . $a . $a;\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$b\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$b$a$a\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$b$a\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$a$b\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$a$a$b\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$a$a$a$b\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$a$a$a$a$b\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$a$a$a$a$a$b\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$a$a$a$a$a$a$b\";\n"
"assert_tainted($c, TAINT_ALL);\n"
"$c = \"$a$a$b$a$a$a$a$a\";\n"
"assert_tainted($c, TAINT_ALL);\n",
"");
// Complex concatenations (adapted from TestString)
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$a = array('x'=>'foo');\n"
"$tmp = 'qqq';\n"
"$b = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $b .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"class c {}\n"
"$c = new c;\n"
"$c->p = 'zzz';\n"
"assert_not_tainted(\"AAA ${a['x']} $a[x] $b $c->p\", TAINT_ALL);\n"
"fb_set_taint($b, TAINT_ALL);\n"
"assert_tainted(\"AAA ${a['x']} $a[x] $b $c->p\", TAINT_ALL);\n"
"class X {\n"
" static function g() {}\n"
"};\n"
"$tmp = 'efg';\n"
"$a = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $a .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"$b = rand() % 42;\n"
"assert_tainted('abc' . X::g() . $b . $a, TAINT_ALL);\n"
"fb_set_taint($a, TAINT_ALL);\n"
"assert_tainted('abc' . X::g() . 42 . $a, TAINT_ALL);\n"
"assert_tainted('abc' . X::g() . $b . $a, TAINT_ALL);\n"
"function f() {\n"
" $tmp = 'x';\n"
" $a = '';\n"
" for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $a .= $tmp[$i];\n"
" }\n"
" unset($tmp);\n"
" fb_set_taint($a, TAINT_ALL);\n"
" return $a;\n"
"}\n"
"function g() {}\n"
"function test1($a) {\n"
" $buf = '';\n"
" foreach ($a as $s) {\n"
" $buf .= f() . g() . 'h' . f() . 'h' . g();\n"
" }\n"
" foreach ($a as $s) {\n"
" $buf .= ($s . 'h' . $s);\n"
" }\n"
" return $buf;\n"
"}\n"
"assert_tainted(test1(array(1)), TAINT_ALL);\n"
"function test2() {\n"
" return f() . g() . f() . g();\n"
"}\n"
"assert_tainted(test2(), TAINT_ALL);\n"
"function test3() {\n"
" return f() . g() . f() . g() . f() . g() . f() . g() . f();\n"
"}\n"
"assert_tainted(test3(), TAINT_ALL);\n"
"function test4() {\n"
" $s = f();\n"
" $s .=\n"
" ('foo'.\n"
" 'bar'.\n"
" f().\n"
" 'foo'.\n"
" 'baz'.\n"
" f().\n"
" 'fuz'.\n"
" 'boo'.\n"
" f().\n"
" 'fiz'.\n"
" 'faz');\n"
" $s .= f();\n"
" return $s;\n"
"}\n"
"assert_tainted(test4(), TAINT_ALL);\n"
"function test6() {\n"
" return g().f().g();\n"
"}\n"
"assert_tainted(test6(), TAINT_ALL);\n",
"");
// Arrays
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"$tmp = 'toto';\n"
"$good3 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good3 .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"$arrg = array($good1);\n"
"$arrb = array($bad1);\n"
"assert_not_tainted($arrg[0], TAINT_ALL);\n"
"assert_tainted($arrb[0], TAINT_ALL);\n"
"$arr = array(\n"
" $good1 => $good2,\n"
" $bad1 => $bad2,\n"
" $bad2 => array(\n"
" $good2 => $bad2,\n"
" $bad2 => $good3,\n"
" ),\n"
");\n"
"assert_not_tainted($arr, TAINT_ALL);\n"
"assert_tainted(print_r($arr, true), TAINT_ALL);\n"
"assert_not_tainted($arr[$good1], TAINT_ALL);\n"
"assert_tainted($arr[$bad1], TAINT_ALL);\n"
"assert_not_tainted($arr[$bad2], TAINT_ALL);\n"
"assert_tainted(print_r($arr[$bad2], true), TAINT_ALL);\n"
"assert_tainted($arr[$bad2][$good2], TAINT_ALL);\n"
"assert_not_tainted($arr[$bad2][$bad2], TAINT_ALL);\n"
"$keys = array_keys($arr);\n"
"assert_not_tainted($keys[0], TAINT_ALL);\n"
"assert_tainted($keys[1], TAINT_ALL);\n"
"assert_tainted($keys[2], TAINT_ALL);\n",
"");
// Typecasts
MVCRO("<?php\n"
"var_dump(fb_get_taint(NULL, TAINT_ALL));\n"
"var_dump(fb_get_taint(true, TAINT_ALL));\n"
"var_dump(fb_get_taint(false, TAINT_ALL));\n"
"var_dump(fb_get_taint(rand(), TAINT_ALL));\n"
"var_dump(fb_get_taint((rand() / rand()), TAINT_ALL));\n"
"$a = NULL;\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint((string)$a, TAINT_ALL));\n"
"$a = true;\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint((string)$a, TAINT_ALL));\n"
"$a = false;\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint((string)$a, TAINT_ALL));\n"
"$a = rand();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint((string)$a, TAINT_ALL));\n"
"$a = rand() / rand();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint((string)$a, TAINT_ALL));\n"
"$a = rand();\n"
"$arr = array(\n"
" 'foostr' => rand(),\n"
" $a => 'barbaz',\n"
");\n"
"var_dump(fb_get_taint($arr, TAINT_ALL));\n"
"var_dump(fb_get_taint($arr['foostr'], TAINT_ALL));\n"
"var_dump(fb_get_taint($arr[$a], TAINT_ALL));\n"
"class CleanObj {\n"
" function __toString() { return 'obj'; }\n"
"}\n"
"class TaintedObj {\n"
" function __toString() {\n"
" $bad1 = \"eViL\\nsTring\\nare\\tfun\\narent\\tthey?\";\n"
" fb_set_taint($bad1, TAINT_MUTATED);\n"
" return 'obj' . $bad1;\n"
" }\n"
"}\n"
"$obj1 = new CleanObj();\n"
"var_dump(fb_get_taint($obj1, TAINT_MUTATED));\n"
"$obj2 = new TaintedObj();\n"
"var_dump(fb_get_taint($obj2, TAINT_MUTATED));\n",
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n");
// Tokens
MVCRO("<?php\n"
"$tmp = 'goodname';\n"
"$goodtok = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $goodtok .= $tmp[$i];\n"
"}\n"
"$tmp = 'badname';\n"
"$badtok = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $badtok .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($badtok, TAINT_ALL);\n"
"$$goodtok = 'goodval';\n"
"$vars = array_keys(get_defined_vars(), 'goodval');\n"
"var_dump(fb_get_taint($vars[0], TAINT_ALL));\n"
"$$badtok = 'badval';\n"
"$vars = array_keys(get_defined_vars(), 'badval');\n"
"var_dump(fb_get_taint($vars[0], TAINT_ALL));\n"
"function foostr() {\n"
" var_dump(fb_get_taint(__FUNCTION__, TAINT_ALL));\n"
"}\n"
"foostr();\n"
"class foostr {\n"
" public function __construct() { }\n"
" public function foostr() {\n"
" var_dump(fb_get_taint(__CLASS__, TAINT_ALL));\n"
" var_dump(fb_get_taint(__METHOD__, TAINT_ALL));\n"
" }\n"
" public static function staticFoostr() {\n"
" var_dump(fb_get_taint(__CLASS__, TAINT_ALL));\n"
" var_dump(fb_get_taint(__METHOD__, TAINT_ALL));\n"
" }\n"
"}\n"
"$a = new foostr();\n"
"$a->foostr();\n"
"foostr::staticFoostr();\n",
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n");
// Closures
MVCRO("<?php\n"
"$tmp = 'foostr';\n"
"$a = '';\n"
"$b = '';\n"
"$c = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $a .= $tmp[$i];\n"
"}\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $b .= $tmp[$i];\n"
"}\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $c .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($b, TAINT_ALL);\n"
"$closure =\n"
" function($a) use ($c) {\n"
" var_dump(fb_get_taint($a, TAINT_ALL));\n"
" var_dump(fb_get_taint($c, TAINT_ALL));\n"
" };\n"
"$closure($a);\n"
"$closure($b);\n"
"$closure($c);\n"
"fb_set_taint($c, TAINT_ALL);\n"
"$closure =\n"
" function($a) use ($c) {\n"
" var_dump(fb_get_taint($a, TAINT_ALL));\n"
" var_dump(fb_get_taint($c, TAINT_ALL));\n"
" };\n"
"$closure($a);\n"
"$closure($b);\n"
"$closure($c);\n"
"function make_closure($c) {\n"
" $closure =\n"
" function($a) use ($c) {\n"
" var_dump(fb_get_taint($a, TAINT_ALL));\n"
" var_dump(fb_get_taint($c, TAINT_ALL));\n"
" };\n"
" return $closure;\n"
"}\n"
"$closure = make_closure($c);\n"
"$closure($a);\n"
"$closure($b);\n"
"$closure($c);\n",
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n");
// Generators
MVCRO("<?php\n"
"function foo($b) {\n"
" $tmp = 'foostr';\n"
" $a = '';\n"
" for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $a .= $tmp[$i];\n"
" }\n"
" unset($tmp);\n"
" fb_set_taint($a, TAINT_ALL);\n"
" var_dump(fb_get_taint($b, TAINT_ALL));\n"
" yield fb_get_taint($a, TAINT_ALL);\n"
" var_dump(fb_get_taint($b, TAINT_ALL));\n"
" yield fb_get_taint($a, TAINT_ALL);\n"
"}\n"
"$tmp = 'foostr';\n"
"$b = '';\n"
"$c = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $b .= $tmp[$i];\n"
"}\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $c .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($c, TAINT_ALL);\n"
"foreach (foo($b) as $a) { var_dump($a); }\n"
"foreach (foo($c) as $a) { var_dump($a); }\n",
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n");
return true;
}
bool TestCodeRun::TestTaintExt() {
HipHopSyntax w(this);
/**
* Apache
*
* apache_note: Should maintain taint on strings as they are passed
* in and out and does so without the use of TaintObservers.
*
* The remaining apache functions either fully taint (those retrieving
* headers) or are control functions which don't require taint.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"apache_note($good1, $good2);\n"
"assert_not_tainted(apache_note($good1), TAINT_ALL);\n"
"apache_note($good1, $bad2);\n"
"assert_tainted(apache_note($good1), TAINT_ALL);\n"
"apache_note($bad1, $good2);\n"
"assert_not_tainted(apache_note($bad1), TAINT_ALL);\n"
"apache_note($bad1, $bad2);\n"
"assert_tainted(apache_note($bad1), TAINT_ALL);\n",
"");
/**
* APC
*
* apc_add, apc_store, apc_fetch: These should maintain taint on
* strings as they are passed in and out of APC. This is done so
* using TaintObservers and hence there is no distinction made
* between taints on keys and values.
*
* To implement the semantics of only passing the taint of values,
* we would have either to make sweeping assumptions about the use
* cases of SharedVariant or to make heavy-handed alterations to
* all SharedStore classes, neither of which we really want.
*
* In general, though, it seems rather unwise to use user-controlled
* strings as APC keys, so this is probably fine.
*
* No taint is required for the remaining functions.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"apc_add($good2, $bad1);\n"
"apc_add($bad2, $good1);\n"
"apc_add($bad2, $bad1, 0, 1);\n"
"apc_add($good2, $good1, 0, 1);\n"
"assert_tainted(apc_fetch($good2), TAINT_ALL);\n"
"assert_tainted(apc_fetch($bad2), TAINT_ALL);\n"
"$foo = false;\n"
"assert_not_tainted(apc_fetch($good2, $foo, 1), TAINT_ALL);\n"
"assert_tainted(apc_fetch($bad2, $foo, 1), TAINT_ALL);\n"
"apc_store($good2, $good1);\n"
"apc_store($bad2, $bad1);\n"
"assert_not_tainted(apc_fetch($good2), TAINT_ALL);\n"
"assert_tainted(apc_fetch($bad2), TAINT_ALL);\n"
"apc_delete($bad2);\n"
"assert_not_tainted(apc_fetch($good2), TAINT_ALL);\n"
"apc_clear_cache(1);\n"
"apc_add($good2, $good1, 0, 1);\n"
"apc_add($bad2, $bad1, 0, 1);\n"
"assert_not_tainted(apc_fetch($good2, $foo, 1), TAINT_ALL);\n"
"assert_tainted(apc_fetch($bad2, $foo, 1), TAINT_ALL);\n"
"apc_clear_cache();\n",
"");
/**
* APD
*
* These functions are not supported in hphp and are hence untainted.
*/
/**
* Array
*/
#define TEST_TAINT_EXT_ARRAY_STD_TAINTS \
"bool(true)\n" \
"bool(false)\n" \
"bool(false)\n" \
"bool(true)\n" \
"bool(false)\n" \
"bool(false)\n" \
"bool(true)\n" \
"bool(true)\n"
#define TEST_TAINT_EXT_ARRAY_KEY_TAINTS \
"bool(true)\n" \
"bool(false)\n" \
"bool(false)\n" \
"bool(true)\n" \
#define TEST_TAINT_EXT_ARRAY_VAL_TAINTS \
"bool(false)\n" \
"bool(true)\n" \
"bool(false)\n" \
"bool(true)\n"
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"$good3 = '';\n"
"$good4 = '';\n"
"$bad3 = '';\n"
"$bad4 = '';\n"
"$tmp = 'frenchonion';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good3 .= $tmp[$i];\n"
"}\n"
"$tmp = 'udon';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good4 .= $tmp[$i];\n"
"}\n"
"$tmp = 'splitpea';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $bad3 .= $tmp[$i];\n"
"}\n"
"$tmp = 'creamofmanure';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $bad4 .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($bad3, TAINT_ALL);\n"
"fb_set_taint($bad4, TAINT_ALL);\n"
"function check_array($arr, $check_key = true, $check_val = true) {\n"
" foreach ($arr as $k => $v) {\n"
" if ($check_key) {\n"
" var_dump(fb_get_taint($k, TAINT_ALL));\n"
" }\n"
" if ($check_val) {\n"
" var_dump(fb_get_taint($v, TAINT_ALL));\n"
" }\n"
" }\n"
"}\n"
"$mixed_arr = array(\n"
" $bad3 => $good1,\n"
" $good3 => $bad1,\n"
" $good4 => $good2,\n"
" $bad4 => $bad2,\n"
");\n"
"$num_arr = array($good1, $bad1, $good2, $bad2);\n"
"$arr = array_change_key_case($mixed_arr);\n"
"foreach ($arr as $k => $v) {\n"
" var_dump(fb_get_taint($k, TAINT_HTML));\n"
" var_dump(fb_get_taint($k, TAINT_MUTATED));\n"
" var_dump(fb_get_taint($v, TAINT_ALL));\n"
"}\n"
"$arr = array_chunk($mixed_arr, 2, true);\n"
"check_array($arr[0]);\n"
"check_array($arr[1]);\n"
"check_array(array_combine(\n"
" array($bad3, $good3, $good4, $bad4),\n"
" $num_arr\n"
"));\n"
"check_array(array_count_values($mixed_arr), true, false);\n"
"check_array(array_fill_keys($num_arr, $bad1));\n"
"check_array(array_fill(0, 2, $good1), false);\n"
"check_array(array_fill(0, 2, $bad1), false);\n"
"check_array(array_filter(\n"
" $mixed_arr,\n"
" function($str) { return strlen($str) < 42; }\n"
"));\n"
"check_array(array_flip($mixed_arr));\n"
"check_array(array_keys($mixed_arr), false);\n"
"check_array(array_map(\n"
" function($str) { return $str . $str; },\n"
" $mixed_arr\n"
"));\n"
"$arr = array_chunk($mixed_arr, 2, true);\n"
"check_array(array_merge($arr[0], $arr[1]));\n"
"check_array(array_replace(\n"
" $mixed_arr,\n"
" array(\n"
" $bad3 => $bad1,\n"
" $good3 => $bad2,\n"
" $good4 => $good1,\n"
" $bad4 => $good2,\n"
" )\n"
"));\n"
"check_array(array_pad($mixed_arr, 5, $good1));\n"
"check_array(array_pad($mixed_arr, 5, $bad1));\n"
"$arr = $num_arr;\n"
"$v = array_pop($arr);\n"
"$u = array_pop($arr);\n"
"check_array($arr, false);\n"
"var_dump(fb_get_taint($u, TAINT_ALL));\n"
"var_dump(fb_get_taint($v, TAINT_ALL));\n"
"array_push($arr, $u);\n"
"array_push($arr, $v);\n"
"check_array($arr, false);\n"
"var_dump(fb_get_taint(array_reduce(\n"
" $mixed_arr,\n"
" function($a, $b) { return $a . $b; },\n"
" ''\n"
"), TAINT_ALL));\n"
"check_array(array_reverse($mixed_arr));\n"
"var_dump(fb_get_taint(array_search($good1, $mixed_arr), TAINT_ALL));\n"
"var_dump(fb_get_taint(array_search($bad1, $mixed_arr), TAINT_ALL));\n"
"var_dump(fb_get_taint(array_search($good2, $mixed_arr), TAINT_ALL));\n"
"var_dump(fb_get_taint(array_search($bad2, $mixed_arr), TAINT_ALL));\n"
"$arr = $num_arr;\n"
"$v = array_shift($arr);\n"
"$u = array_shift($arr);\n"
"var_dump(fb_get_taint($v, TAINT_ALL));\n"
"var_dump(fb_get_taint($u, TAINT_ALL));\n"
"check_array($arr, false);\n"
"array_unshift($arr, $u);\n"
"array_unshift($arr, $v);\n"
"check_array($arr, false);\n"
"check_array(array_slice($mixed_arr, 0, 4), false);\n"
"check_array(array_slice($mixed_arr, 0, 4, true));\n"
"$arr = $mixed_arr;\n"
"$ins = array_splice($arr, 1, 2);\n"
"array_splice($arr, 1, 0, $ins);\n"
"check_array($arr, false);\n"
"check_array(array_values($mixed_arr), false);\n"
"$arr = $mixed_arr;\n"
"array_walk(\n"
" $arr,\n"
" function ($v, $k, $x) { $v .= $x; $k .= $x; },\n"
" 'foobar'\n"
");\n"
"check_array($arr);\n"
"check_array(compact('bad3', 'good3', 'good4', 'bad4'), false);\n"
"check_array(array_diff($num_arr, array_slice($num_arr, 0, 2)), false);\n"
"check_array(array_diff($num_arr, array_slice($num_arr, 2, 2)), false);\n"
"check_array(array_diff_key(\n"
" array_flip($mixed_arr),\n"
" array_flip(array_slice($mixed_arr, 2, 2))\n"
"), false);\n"
"check_array(array_diff_key(\n"
" array_flip($mixed_arr),\n"
" array_flip(array_slice($mixed_arr, 0, 2))\n"
"), false);\n"
"check_array(array_intersect($mixed_arr, $num_arr), false);\n"
"check_array(array_intersect_key(\n"
" array_flip($mixed_arr),\n"
" array_flip($num_arr)\n"
"), false);\n"
"$arr = $mixed_arr;\n"
"sort($arr);\n"
"check_array($arr, false);\n"
"asort($mixed_arr);\n"
"check_array($mixed_arr);\n"
"ksort($mixed_arr);\n"
"check_array($mixed_arr);\n",
// array_change_key_case
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
// array_chunk
TEST_TAINT_EXT_ARRAY_STD_TAINTS
// array_combine
TEST_TAINT_EXT_ARRAY_STD_TAINTS
// array_count_values
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_fill_keys
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
// array_fill
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
// array_filter
TEST_TAINT_EXT_ARRAY_STD_TAINTS
// array_flip
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
// array_keys
TEST_TAINT_EXT_ARRAY_KEY_TAINTS
// array_map
TEST_TAINT_EXT_ARRAY_STD_TAINTS
// array_merge
TEST_TAINT_EXT_ARRAY_STD_TAINTS
// array_replace
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
// array_pad
TEST_TAINT_EXT_ARRAY_STD_TAINTS
"bool(true)\n"
"bool(false)\n"
TEST_TAINT_EXT_ARRAY_STD_TAINTS
"bool(true)\n"
"bool(true)\n"
// array_pop
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_push
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_reduce
"bool(true)\n"
// array_reverse
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
// array_search
TEST_TAINT_EXT_ARRAY_KEY_TAINTS
// array_shift
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_unshift
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_slice
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
TEST_TAINT_EXT_ARRAY_STD_TAINTS
// array_splice
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_values
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_walk
TEST_TAINT_EXT_ARRAY_STD_TAINTS
// compact
TEST_TAINT_EXT_ARRAY_KEY_TAINTS
// array_diff
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_diff_key
TEST_TAINT_EXT_ARRAY_KEY_TAINTS
// array_intersect
TEST_TAINT_EXT_ARRAY_VAL_TAINTS
// array_intersect_key
TEST_TAINT_EXT_ARRAY_KEY_TAINTS
// sort
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
// asort
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
// ksort
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n");
#undef TEST_TAINT_EXT_ARRAY_VAL_RESULT
#undef TEST_TAINT_EXT_ARRAY_KEY_RESULT
#undef TEST_TAINT_EXT_ARRAY_STD_RESULT
/**
* BC Math
*
* bc{add, sub, mul, div, pow, mod, powmod, sqrt}: These taint with the
* same semantics as concatenation; that is, they propagate taint only
* and do not mutate.
*
* The remaining functions, bcscale and bccomp, have no need for taint.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$tmp = '3141592653589793238462';\n"
"$good1 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good1 .= $tmp[$i];\n"
"}\n"
"$tmp = '2';\n"
"$good2 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good2 .= $tmp[$i];\n"
"}\n"
"$tmp = '2718281828459045235360';\n"
"$bad1 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $bad1 .= $tmp[$i];\n"
"}\n"
"$tmp = '3';\n"
"$bad2 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $bad2 .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($bad1, TAINT_ALL);\n"
"fb_set_taint($bad2, TAINT_ALL);\n"
"$binary_ops = array(\n"
" 'bcadd',\n"
" 'bcsub',\n"
" 'bcmul',\n"
" 'bcdiv',\n"
" 'bcmod',\n"
" 'bcpow',\n"
");\n"
"foreach($binary_ops as $func) {\n"
" assert_not_tainted($func($good1, $good2), TAINT_ALL);\n"
" assert_tainted($func($good1, $bad2), TAINT_ALL);\n"
" assert_tainted($func($bad1, $good2), TAINT_ALL);\n"
" assert_tainted($func($bad1, $bad2), TAINT_ALL);\n"
"}\n"
"assert_not_tainted(bcpowmod($good1, $good2, $good2), TAINT_ALL);\n"
"assert_tainted(bcpowmod($good1, $good2, $bad2), TAINT_ALL);\n"
"assert_tainted(bcpowmod($good1, $bad2, $good2), TAINT_ALL);\n"
"assert_tainted(bcpowmod($bad1, $good2, $bad2), TAINT_ALL);\n"
"assert_tainted(bcpowmod($bad1, $bad2, $good2), TAINT_ALL);\n"
"assert_tainted(bcpowmod($bad1, $bad2, $bad2), TAINT_ALL);\n"
"assert_not_tainted(bcsqrt($good1), TAINT_ALL);\n"
"assert_tainted(bcsqrt($bad1), TAINT_ALL);\n",
"");
/**
* bzip: no tests
*
* Functions which read from files fully taint but their outputs are
* never traced.
*/
/**
* Class
*
* No TaintObservers are declared for any class extension functions;
* we test get_object_vars() to ensure that taint will still be passed
* out by reference.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"class Foo {\n"
" public $good;\n"
" public $bad;\n"
" public function __construct() {\n"
" global $good1, $bad1;\n"
" $this->good = $good1;\n"
" $this->bad = $bad1;\n"
" }\n"
" public function foo() { }\n"
"}\n"
"$a = new Foo();\n"
"$arr = get_object_vars($a);\n"
"assert_not_tainted($arr['good'], TAINT_ALL);\n"
"assert_tainted($arr['bad'], TAINT_ALL);\n",
"");
/**
* Closure
* Continuation
* Ctype
*
* No functions are defined in closure, only object creation helpers
* are defined in continuation, and character typing doesn't produce
* any output; none of these need taint.
*/
/**
* Curl
*
* Functions such as curl_exec() and curl_getinfo() return fully tainted
* strings; all remaining functions have no need for taint.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$c = curl_init('http://www.steal-my.info');\n"
"curl_setopt($c, CURLOPT_RETURNTRANSFER, true);\n"
"assert_tainted(curl_exec($c), TAINT_ALL);\n"
"$info = curl_getinfo($c);\n"
"foreach ($info as $v) {\n"
//" assert_tainted($v, TAINT_ALL);\n"
"}\n"
"assert_tainted(curl_multi_getcontent($c), TAINT_ALL);\n"
"$r = evhttp_get('http://www.steal-my.info');\n"
"assert_tainted($r['response'], TAINT_ALL);\n"
"foreach ($r['headers'] as $h) {\n"
" assert_tainted($h, TAINT_ALL);\n"
"}\n"
"$r = evhttp_post('http://www.steal-my.info', '');\n"
"assert_tainted($r['response'], TAINT_ALL);\n"
"foreach ($r['headers'] as $h) {\n"
" assert_tainted($h, TAINT_ALL);\n"
"}\n",
"");
/**
* Datetime (TODO)
*/
/**
* Debugger
* DOMDocument (TODO)
* Error
*
* Debugger and error both contain only control functions and do not
* require taint (error does include some passing around of strings, but
* we elect not to taint there). DOMDocument tainting could use more
* investigation.
*/
/**
* FB
*
* fb_rename_function: Although we rename the function, the rename is
* superficial in the sense that __FUNCTION__ still yields the original
* name; we sanity check this to make sure taint doesn't leak.
*
* All other functions are control functions which do not require taint.
*/
{
OptionSetter w(this, OptionSetter::CompileTime,
"-vDynamicInvokeFunctions.*=foo");
MVCRO("<?php\n"
INIT_TEST_TAINT_STRINGS
"function foo() { "
"var_dump(fb_get_taint(__FUNCTION__, TAINT_ALL)); }\n"
"foo();\n"
"fb_rename_function('foo', $bad2);\n"
"$bad2();\n"
"fb_rename_function($bad2, $good2);\n"
"$good2();\n",
"bool(false)\n"
"bool(false)\n"
"bool(false)\n");
}
/**
* FBML (TODO)
*
* We elect to ignore FBML for taint purposes for the time being.
*/
/**
* File (TODO)
*/
/**
* Function
*
* func_get_arg*(): These should pass taint by reference.
* call_user_func*(): These should pass the taint of arguments by
* reference but should not leak any taint into the normal codepath
* of the callback.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_STRINGS
// Ensure that falling into the callback doesn't drop taint.
"function callback_check_propagation($a, $b) {\n"
" var_dump(fb_get_taint($a, TAINT_ALL));\n"
" var_dump(fb_get_taint($b, TAINT_ALL));\n"
"}\n"
// Ensure that the call_user_func*() family is not scoping in any
// TaintObservers. To do this check, we do an access on the variable
// we've passed in, we create a String object without scoping in new
// TaintObservers by making a new variable, then we check that said
// variable's name is not tainted.
"function callback_check_independence($a) {\n"
" if ($a === 'foobarbaz') {\n"
" $var = 'something';\n"
" }\n"
" var_dump(fb_get_taint($var, TAINT_ALL));\n"
" var_dump(fb_get_taint(\n"
" array_keys(get_defined_vars(), 'something'),\n"
" TAINT_ALL\n"
" ));\n"
"}\n"
// Check taint of arguments
"function check_args() {\n"
" $arr = func_get_args();\n"
" for ($i = 0; $i < count($arr); $i++) {\n"
" var_dump(fb_get_taint(func_get_arg($i), TAINT_ALL));\n"
" }\n"
" for ($i = 0; $i < count($arr); $i++) {\n"
" var_dump(fb_get_taint($arr[$i], TAINT_ALL));\n"
" }\n"
" foreach ($arr as $arg) {\n"
" var_dump(fb_get_taint($arg, TAINT_ALL));\n"
" }\n"
"}\n"
"$arr_good = array($good1, $good2);\n"
"$arr_mixed = array($good1, $bad1);\n"
"$arr_bad = array($bad1, $bad2);\n"
"call_user_func('callback_check_propagation', $good1, $good2);\n"
"call_user_func('callback_check_propagation', $good1, $bad1);\n"
"call_user_func('callback_check_propagation', $bad1, $bad2);\n"
"call_user_func_array('callback_check_propagation', $arr_good);\n"
"call_user_func_array('callback_check_propagation', $arr_mixed);\n"
"call_user_func_array('callback_check_propagation', $arr_bad);\n"
"$a = 'foobarbaz';\n"
"fb_set_taint($a, TAINT_ALL);\n"
"call_user_func('callback_check_independence', $a);\n"
"call_user_func_array('callback_check_independence', array($a));\n"
"check_args($bad1, $good1);\n"
"call_user_func('check_args', $bad1, $good1);\n",
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n");
/**
* Hash: no tests
*
* We mutate on all hashing functions; the remaining functions do not
* require taint. In particular, for hash_file(), we mutate only and
* do not apply other taints.
*
* Unfortunately, we are unable to preserve taint that enters the
* hash context system since it is implemented with raw char *'s.
* Since we are hashing, this probably isn't the end of the world...
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"assert_not_tainted(hash('sha1', $good1), TAINT_HTML);\n"
"assert_tainted(hash('sha1', $bad1), TAINT_HTML);\n"
"assert_tainted(hash('sha1', $good1), TAINT_MUTATED);\n"
"assert_tainted(hash('sha1', $bad1), TAINT_MUTATED);\n",
"");
/**
* iconv: no tests
*
* Any function performing encoding or decoding should mutate; the rest
* do not need taint.
*/
/**
* ICU
*
* Both icu.idl.php functions should mutate and propagate taint; the
* functions in icu_*.idl.php do not require taint.
*/
MVCRO("<?php\n"
"$tmp = \"\\xe5\\x9b\\x9b\n"
" \\xe5\\x8d\\x81\\xe5\\x9b\\x9b\\xe7\n"
" \\x9f\\xb3\\xe7\\x8d\\x85\\xe5\\xad\\x90\";\n"
"$good1 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good1 .= $tmp[$i];\n"
"}\n"
"$tmp = \"\\xd1\\x84\\xd0\\xb5\\xd0\\xb9\\xd1\n"
" \\x81\\xd0\\xb1\\xd1\\x83\\xc5\\x93\\xd0\\xba\";\n"
"$bad1 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $bad1 .= $tmp[$i];\n"
"}\n"
"$tmp = 'Hello world';\n"
"$good2 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good2 .= $tmp[$i];\n"
"}\n"
"$tmp = 'Hello evil';\n"
"$bad2 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $bad2 .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($bad1, TAINT_ALL);\n"
"fb_set_taint($bad2, TAINT_ALL);\n"
"var_dump(fb_get_taint(icu_transliterate($good1, false), TAINT_HTML));\n"
"var_dump(fb_get_taint(icu_transliterate($good1, false), TAINT_MUTATED));\n"
"var_dump(fb_get_taint(icu_transliterate($bad1, false), TAINT_HTML));\n"
"var_dump(fb_get_taint(icu_transliterate($bad1, false), TAINT_MUTATED));\n"
"$good_arr = icu_tokenize($good2);\n"
"$bad_arr = icu_tokenize($bad2);\n"
"foreach ($good_arr as $token) {\n"
" var_dump(fb_get_taint($token, TAINT_HTML));\n"
" var_dump(fb_get_taint($token, TAINT_MUTATED));\n"
"}\n"
"foreach ($bad_arr as $token) {\n"
" var_dump(fb_get_taint($token, TAINT_HTML));\n"
" var_dump(fb_get_taint($token, TAINT_MUTATED));\n"
"}\n",
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n");
/**
* Image
* Imagesprite
*
* These libraries only include image manipulation files (along with exif
* data handlers, which we presume safe); we do not inject taint.
*/
/**
* IMAP (TODO)
*/
/**
* Intl: no tests
*
* We mutate in string translation functions; the remaining functions
* do not require taint.
*/
/**
* IPC
*
* We would like IPC functions to maintain the following taint semantics;
* however, since message passing and shared memory are both implemented
* at the char * level, we can't.
*
* This has the potential to be pretty bad since IPC functions allow
* user-controlled to spread quite far, but unless someone is willing to
* change the implementations, we have to live with it.
*
* MVCRO("<?php\n"
* INIT_TEST_TAINT_STRINGS
* "$q = msg_get_queue(0);\n"
* "msg_send($q, 1, $bad1);\n"
* "msg_send($q, 1, $good1);\n"
* "$str = '';\n"
* "msg_receive($q, 0, $str);\n"
* "var_dump(fb_get_taint($str, TAINT_ALL));\n"
* "msg_receive($q, 0, $str);\n"
* "var_dump(fb_get_taint($str, TAINT_ALL));\n"
* "msg_remove_queue($q);\n"
* "$shm = shm_attach(0);\n"
* "shm_put_var($shm, $good2, $bad1);\n"
* "shm_put_var($shm, $bad2, $good1);\n"
* "var_dump(fb_get_taint(shm_get_var($shm, $good2), TAINT_ALL));\n"
* "var_dump(fb_get_taint(shm_get_var($shm, $bad2), TAINT_ALL));\n"
* "shm_remove_var($shm, $good2);\n"
* "shm_remove_var($shm, $bad2);\n"
* "shm_put_var($shm, $good2, $good1);\n"
* "shm_put_var($shm, $bad2, $bad1);\n"
* "var_dump(fb_get_taint(shm_get_var($shm, $good2), TAINT_ALL));\n"
* "var_dump(fb_get_taint(shm_get_var($shm, $bad2), TAINT_ALL));\n"
* "shm_remove_var($shm, $bad2);\n"
* "var_dump(fb_get_taint(shm_get_var($shm, $good2), TAINT_ALL));\n"
* "shm_put_var($shm, $bad2, $bad1);\n"
* "shm_detach($shm);\n"
* "$shm = shm_attach(0);\n"
* "var_dump(fb_get_taint(shm_get_var($shm, $good2), TAINT_ALL));\n"
* "var_dump(fb_get_taint(shm_get_var($shm, $bad2), TAINT_ALL));\n"
* "shm_remove($shm);\n",
* "bool(true)\n"
* "bool(false)\n"
* "bool(true)\n"
* "bool(false)\n"
* "bool(false)\n"
* "bool(true)\n"
* "bool(false)\n"
* "bool(false)\n"
* "bool(true)\n");
*/
/**
* Iterator
*
* This library only includes hphp-specific control functions, which do
* not require taint.
*/
/**
* LDAP (TODO)
*/
/**
* Magick
*
* This is an image manipulation library which does not require taint.
*/
/**
* Mailparse (TODO)
*/
/**
* Math
*
* Base conversion functions that return non-numbers mutate; the remaining
* functions operate on numerics only and do not need taint.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$tmp = '42';\n"
"$good42 = '';\n"
"$bad42 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good42 .= $tmp[$i];\n"
"}\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $bad42 .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($bad42, TAINT_ALL);\n"
"assert_not_tainted(decbin(42), TAINT_HTML);\n"
"assert_tainted(decbin(42), TAINT_MUTATED);\n"
"assert_not_tainted(dechex(42), TAINT_HTML);\n"
"assert_tainted(dechex(42), TAINT_MUTATED);\n"
"assert_not_tainted(decoct(42), TAINT_HTML);\n"
"assert_tainted(decoct(42), TAINT_MUTATED);\n"
"assert_not_tainted(base_convert(rand(), 10, 3), TAINT_HTML);\n"
"assert_tainted(base_convert(rand(), 10, 3), TAINT_MUTATED);\n"
"assert_not_tainted(base_convert($good42, 10, 3), TAINT_HTML);\n"
"assert_tainted(base_convert($good42, 10, 3), TAINT_MUTATED);\n"
"assert_tainted(base_convert($bad42, 10, 3), TAINT_HTML);\n"
"assert_tainted(base_convert($bad42, 10, 3), TAINT_MUTATED);\n",
"");
/**
* MB: no tests
*
* TODO: regex functions
*
* We do not taint control functions; the remaining functions we taint
* much like their string extension counterparts.
*/
/**
* Mcrypt: no tests
*/
/**
* Memcached: no tests
* Memcache: no tests
*
* All get() and fetch() functions and methods fully taint; remaining
* functions do not require taint.
*/
/**
* Misc
*
* define, constant: Taint is passed by reference.
*
* No other misc functions require taint.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"define('GOOD', $good2);\n"
"define('BAD', $bad2);\n"
"assert_not_tainted(GOOD, TAINT_ALL);\n"
"assert_not_tainted(constant('GOOD'), TAINT_ALL);\n"
"assert_tainted(BAD, TAINT_ALL);\n"
// It may be worth investigating why the following does not hold:
// "assert_tainted(constant('BAD'), TAINT_ALL);\n"
,
"");
/**
* MySQL
*
* Any strings coming from MySQL queries should be fully tainted; we
* instantiate TaintObservers as necessary to preserver these
* semantics.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$conn = mysql_connect("
"'" TEST_HOSTNAME "', "
"'" TEST_USERNAME "', "
"'" TEST_PASSWORD "'"
");\n"
"mysql_select_db('" TEST_DATABASE "');\n"
"mysql_query(\n"
" 'CREATE TABLE test ('.\n"
" 'id int not null auto_increment, '.\n"
" 'name varchar(255) not null, '.\n"
" 'primary key (id)) '.\n"
" 'engine=innodb'\n"
");\n"
"assert_tainted(mysql_stat(), TAINT_MUTATED);\n"
"mysql_query(\"INSERT INTO test (name) VALUES ('test'), ('test2')\");\n"
"assert_tainted(mysql_info(), TAINT_MUTATED);\n"
"$res = mysql_query('SELECT * FROM test');\n"
"$row = mysql_fetch_row($res);\n"
"assert_tainted($row[1], TAINT_HTML);\n"
"$res = mysql_query('SELECT * FROM test');\n"
"$row = mysql_fetch_assoc($res);\n"
"assert_tainted($row['name'], TAINT_HTML);\n"
"$keys = array_keys($row);\n"
"assert_tainted($keys[0], TAINT_HTML);\n"
"assert_tainted($keys[1], TAINT_HTML);\n"
"$row = mysql_fetch_assoc($res);\n"
"assert_tainted($row['name'], TAINT_HTML);\n"
"$keys = array_keys($row);\n"
"assert_tainted($keys[0], TAINT_HTML);\n"
"assert_tainted($keys[1], TAINT_HTML);\n"
"$res = mysql_query('SELECT * FROM test');\n"
"$row = mysql_fetch_array($res);\n"
"assert_tainted($row[1], TAINT_HTML);\n"
"assert_tainted($row['name'], TAINT_HTML);\n"
"$keys = array_keys($row);\n"
"assert_tainted($keys[1], TAINT_HTML);\n"
"assert_tainted($keys[3], TAINT_HTML);\n"
"$res = mysql_query('SELECT * FROM test');\n"
"$row = mysql_fetch_object($res);\n"
"assert_tainted($row->name, TAINT_HTML);\n"
"$res = mysql_query('SELECT * FROM test');\n"
"$ret = mysql_result($res, 0, 'name');\n"
"assert_tainted($ret, TAINT_HTML);\n"
"$ret = mysql_result($res, 0, 'name');\n"
"assert_tainted($ret, TAINT_HTML);\n"
"$ret = mysql_fetch_field($res, 1);\n"
"assert_tainted($ret->name, TAINT_HTML);\n"
"$ret = mysql_field_name($res, 1);\n"
"assert_tainted($ret, TAINT_HTML);\n"
"$ret = mysql_field_table($res, 1);\n"
"assert_tainted($ret, TAINT_HTML);\n"
"mysql_query('DROP TABLE test');\n",
"");
/**
* Network (TODO)
*/
/**
* OpenSSL (TODO)
*/
/**
* Option
*
* get_defined_constants: Taint is passed by reference.
*
* The remaining functions are control functions not requiring taint.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"define('GOOD', $good1);\n"
"define('BAD', $bad1);\n"
"assert_not_tainted(GOOD, TAINT_ALL);\n"
"assert_tainted(BAD, TAINT_ALL);\n"
"$arr = get_defined_constants();\n"
"assert_not_tainted($arr['GOOD'], TAINT_ALL);\n"
"assert_tainted($arr['BAD'], TAINT_ALL);\n"
"define($good2, $bad1);\n"
"define($bad2, $good1);\n"
"assert_tainted(world, TAINT_ALL);\n"
"assert_not_tainted(arent, TAINT_ALL);\n"
"$arr = get_defined_constants();\n"
"assert_tainted($arr[$good2], TAINT_ALL);\n"
"assert_not_tainted($arr[$bad2], TAINT_ALL);\n",
"");
/**
* Oracle (TODO)
*/
/**
* Output
*
* The output buffering system as a whole must propagate taint correctly.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
// ob_start
"ob_start();\n"
"ob_start();\n"
"echo $good1;\n"
"$a = ob_get_clean();\n"
"echo $a;\n"
"$b = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint($b, TAINT_ALL));\n"
"ob_start();\n"
"ob_start();\n"
"echo $bad1;\n"
"$a = ob_get_clean();\n"
"echo $a;\n"
"$b = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint($b, TAINT_ALL));\n"
// ob_clean
"ob_start();\n"
"echo $good1;\n"
"ob_clean();\n"
"echo $good2;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"echo $bad1;\n"
"ob_clean();\n"
"echo $good1;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"echo $good1;\n"
"ob_clean();\n"
"echo $bad1;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"echo $bad1;\n"
"ob_clean();\n"
"echo $bad2;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
// ob_flush
"ob_start();\n"
"ob_start();\n"
"echo $good1;\n"
"ob_flush();\n"
"ob_end_clean();\n"
"$a = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"ob_start();\n"
"ob_start();\n"
"echo $bad1;\n"
"ob_flush();\n"
"ob_end_clean();\n"
"$a = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
// ob_end_clean
"ob_start();\n"
"ob_start();\n"
"echo $good1;\n"
"ob_end_clean();\n"
"echo $good2;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"ob_start();\n"
"echo $bad1;\n"
"ob_end_clean();\n"
"echo $good1;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"ob_start();\n"
"echo $good1;\n"
"ob_end_clean();\n"
"echo $bad1;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"ob_start();\n"
"echo $bad1;\n"
"ob_end_clean();\n"
"echo $bad2;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
// ob_end_flush
"ob_start();\n"
"ob_start();\n"
"echo $good1;\n"
"ob_end_flush();\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"ob_start();\n"
"echo $bad1;\n"
"ob_end_flush();\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
// ob_get_clean
"ob_start();\n"
"echo $good1;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"echo $bad1;\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
// ob_get_contents
"ob_start();\n"
"echo $good1;\n"
"$a = ob_get_contents();\n"
"ob_end_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"ob_start();\n"
"echo $bad1;\n"
"$a = ob_get_contents();\n"
"ob_end_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
// ob_get_flush
"ob_start();\n"
"ob_start();\n"
"echo $good1;\n"
"$a = ob_get_flush();\n"
"ob_end_clean();\n"
"$b = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint($b, TAINT_ALL));\n"
"ob_start();\n"
"ob_start();\n"
"echo $bad1;\n"
"$a = ob_get_flush();\n"
"ob_end_clean();\n"
"$b = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"var_dump(fb_get_taint($b, TAINT_ALL));\n"
// ob concatenation semantics
"ob_start();\n"
"echo $good1;\n"
"echo $good2;\n"
"$a = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"ob_start();\n"
"echo $good1;\n"
"echo $bad1;\n"
"$a = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"ob_start();\n"
"echo $bad1;\n"
"echo $good1;\n"
"$a = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n"
"ob_start();\n"
"echo $bad1;\n"
"echo $bad2;\n"
"$a = ob_get_clean();\n"
"var_dump(fb_get_taint($a, TAINT_ALL));\n",
// ob_start
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
// ob_clean
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
// ob_flush
"bool(false)\n"
"bool(true)\n"
// ob_end_clean
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
// ob_end_flush
"bool(false)\n"
"bool(true)\n"
// ob_get_clean
"bool(false)\n"
"bool(true)\n"
// ob_get_contents
"bool(false)\n"
"bool(true)\n"
// ob_get_flush
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
// ob concatenations semantics
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n");
/**
* PDO
* php_mcc
*
* Neither of these libraries define functions (only methods), so for now
* we do not taint.
*/
/**
* Posix
*
* Although in theory, functions like posix_getcwd() could be user-
* controlled, we avoid tainting for simplicity.
*/
/**
* Preg
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
"$tmp = 'The quick brown fox jumped over the lazy dog.';\n"
"$good = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good .= $tmp[$i];\n"
"}\n"
"$bad = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $bad .= $tmp[$i];\n"
"}\n"
"$p1b = '';\n"
"$p2g = '';\n"
"$p3g = '';\n"
"$tmp = '/quick/';\n"
"for($i = 0; $i < strlen($tmp); $i++) {\n"
" $p1b .= $tmp[$i];\n"
"}\n"
"$tmp = '/brown/';\n"
"for($i = 0; $i < strlen($tmp); $i++) {\n"
" $p2g .= $tmp[$i];\n"
"}\n"
"$tmp = '/fox/';\n"
"for($i = 0; $i < strlen($tmp); $i++) {\n"
" $p3g .= $tmp[$i];\n"
"}\n"
"$r1g = '';\n"
"$r2b = '';\n"
"$r3g = '';\n"
"$tmp = 'slow';\n"
"for($i = 0; $i < strlen($tmp); $i++) {\n"
" $r1g .= $tmp[$i];\n"
"}\n"
"$tmp = 'black';\n"
"for($i = 0; $i < strlen($tmp); $i++) {\n"
" $r2b .= $tmp[$i];\n"
"}\n"
"$tmp = 'bear';\n"
"for($i = 0; $i < strlen($tmp); $i++) {\n"
" $r3g .= $tmp[$i];\n"
"}\n"
"fb_set_taint($bad, TAINT_HTML);\n"
"fb_set_taint($p1b, TAINT_HTML);\n"
"fb_set_taint($r2b, TAINT_MUTATED);\n"
"$res = preg_grep('/.*/', array($r1g, $r2b, $r3g));\n"
"assert_not_tainted($res[0], TAINT_MUTATED);\n"
"assert_tainted($res[1], TAINT_MUTATED);\n"
"assert_not_tainted($res[2], TAINT_MUTATED);\n"
"$res = preg_replace(\n"
" array($p1b, $p2g, $p3g),\n"
" array($r1g, $r2b, $r3g),\n"
" $good\n"
");\n"
"assert_tainted($res, TAINT_HTML);\n"
"assert_tainted($res, TAINT_MUTATED);\n"
"$res = preg_split('/ /', $bad);\n"
"foreach ($res as $str) {\n"
" assert_tainted($str, TAINT_HTML);\n"
" assert_tainted($str, TAINT_MUTATED);\n"
"}\n",
"");
/**
* Process: no tests
*
* shellescapeargs, shellescapecmd: These functions mutate but clear
* TAINT_BIT_SHELL.
*
* The remaining functions do not require taint.
*/
/**
* Reflection
*
* These functions are FFI's or are metadata getters, so we elect not
* to taint.
*/
/**
* Server (TODO)
*/
/**
* Session (TODO)
*/
/**
* SimpleXML: no tests
*
* simplexml_load_string: We propagate the input string's taints to the
* strings of the created XML object.
* simplexml_load_file: We assume the file is safe.
*
* The remaining functions are control functions which don't require
* taint.
*/
/**
* SOAP
*
* The only functions defined are a very few control functions, which do
* not require taint.
*/
/**
* SPLFile (TODO)
* SPL (TODO)
*/
/**
* SQLLite3 (TODO)
*/
/**
* Stream (TODO)
*/
/**
* String
*
* A very important class to taint semantics. In general, string functions
* with output should mutate and should otherwise propagate taint. There
* are a few exceptions which do not mutate for convenience, namely:
* - rtrim
* - implode
* - join
* - str_repeat
* - str_pad
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_HELPERS
INIT_TEST_TAINT_STRINGS
"$tmp = 'toto';\n"
"$good3 = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $good3 .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"$common_suite_funcs = array(\n"
" 'stripcslashes',\n"
" 'addslashes',\n"
" 'stripslashes',\n"
" 'nl2br',\n"
" 'quotemeta',\n"
" 'str_shuffle',\n"
" 'strrev',\n"
" 'strtolower',\n"
" 'strtoupper',\n"
" 'ucfirst',\n"
" 'ucwords',\n"
" 'strip_tags',\n"
" 'trim',\n"
" 'ltrim',\n"
" 'html_entity_decode',\n"
" 'htmlentities',\n"
" 'htmlspecialchars_decode',\n"
" 'htmlspecialchars',\n"
" 'quoted_printable_encode',\n"
" 'quoted_printable_decode',\n"
" 'convert_uudecode',\n"
" 'convert_uuencode',\n"
" 'str_rot13',\n"
" 'crypt',\n"
" 'md5',\n"
" 'sha1',\n"
");\n"
"function test_common_suite($func) {\n"
" global $good1, $bad1;\n"
" assert_not_tainted($func($good1), TAINT_HTML);\n"
" assert_tainted($func($bad1), TAINT_HTML);\n"
" assert_tainted($func($good1), TAINT_MUTATED);\n"
" assert_tainted($func($bad1), TAINT_MUTATED);\n"
"}\n"
"foreach ($common_suite_funcs as $func) {\n"
" test_common_suite($func);\n"
"}\n"
"assert_not_tainted(addcslashes($good1, $good2), TAINT_HTML);\n"
"assert_tainted(addcslashes($good1, $bad2), TAINT_HTML);\n"
"assert_tainted(addcslashes($bad1, $good2), TAINT_HTML);\n"
"assert_tainted(addcslashes($bad1, $bad2), TAINT_HTML);\n"
"assert_tainted(addcslashes($good1, $good2), TAINT_MUTATED);\n"
"assert_tainted(addcslashes($good1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(addcslashes($bad1, $good2), TAINT_MUTATED);\n"
"assert_tainted(addcslashes($bad1, $bad2), TAINT_MUTATED);\n"
"assert_not_tainted(rtrim($good1), TAINT_HTML);\n"
"assert_tainted(rtrim($bad1), TAINT_HTML);\n"
"assert_not_tainted(rtrim($good1), TAINT_MUTATED);\n"
"assert_tainted(rtrim($bad1), TAINT_MUTATED);\n"
"assert_not_tainted(rtrim($good1, $good2), TAINT_HTML);\n"
"assert_tainted(rtrim($good1, $bad2), TAINT_HTML);\n"
"assert_tainted(rtrim($bad1, $good2), TAINT_HTML);\n"
"assert_tainted(rtrim($bad1, $bad2), TAINT_HTML);\n"
"assert_not_tainted(rtrim($good1, $good2), TAINT_MUTATED);\n"
"assert_tainted(rtrim($good1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(rtrim($bad1, $good2), TAINT_MUTATED);\n"
"assert_tainted(rtrim($bad1, $bad2), TAINT_MUTATED);\n"
"assert_not_tainted(chop($good1), TAINT_HTML);\n"
"assert_tainted(chop($bad1), TAINT_HTML);\n"
"assert_not_tainted(chop($good1), TAINT_MUTATED);\n"
"assert_tainted(chop($bad1), TAINT_MUTATED);\n"
"$arr = explode(\"\\n\", $good1);\n"
"assert_not_tainted($arr[0], TAINT_HTML);\n"
"assert_not_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
"$arr = explode(\"\\n\", $bad1);\n"
"assert_tainted($arr[0], TAINT_HTML);\n"
"assert_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
"$arr = array();\n"
"$arr[] = $good1;\n"
"$arr[] = $good2;\n"
"assert_not_tainted(implode(\"\\t\", $arr), TAINT_HTML);\n"
"assert_not_tainted(implode(\"\\t\", $arr), TAINT_MUTATED);\n"
"assert_tainted(implode($bad2, $arr), TAINT_HTML);\n"
"assert_tainted(implode($bad2, $arr), TAINT_MUTATED);\n"
"$arr[] = $bad1;\n"
"assert_tainted(implode(\"\\t\", $arr), TAINT_HTML);\n"
"assert_tainted(implode(\"\\t\", $arr), TAINT_MUTATED);\n"
"$arr = array();\n"
"$arr[] = $good1;\n"
"$arr[] = $good2;\n"
"assert_not_tainted(join(\"\\t\", $arr), TAINT_HTML);\n"
"assert_not_tainted(join(\"\\t\", $arr), TAINT_MUTATED);\n"
"assert_tainted(join($bad2, $arr), TAINT_HTML);\n"
"assert_tainted(join($bad2, $arr), TAINT_MUTATED);\n"
"$arr[] = $bad1;\n"
"assert_tainted(join(\"\\t\", $arr), TAINT_HTML);\n"
"assert_tainted(join(\"\\t\", $arr), TAINT_MUTATED);\n"
"$arr = str_split($good1, 2);\n"
"assert_not_tainted($arr[0], TAINT_HTML);\n"
"assert_not_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
"$arr = str_split($bad1, 2);\n"
"assert_tainted($arr[0], TAINT_HTML);\n"
"assert_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
"assert_not_tainted(chunk_split($good1, 3, $good2), TAINT_HTML);\n"
"assert_tainted(chunk_split($bad1, 3, $good1), TAINT_HTML);\n"
"assert_tainted(chunk_split($good1, 3, $bad1), TAINT_HTML);\n"
"assert_tainted(chunk_split($good1, 3, $good2), TAINT_MUTATED);\n"
"assert_tainted(chunk_split($bad1, 3, $good1), TAINT_MUTATED);\n"
"assert_tainted(chunk_split($good1, 3, $bad1), TAINT_MUTATED);\n"
"assert_not_tainted(strtok($good1, \"\\n\"), TAINT_HTML);\n"
"assert_not_tainted(strtok(\"\\n\"), TAINT_HTML);\n"
"assert_tainted(strtok($good1, \"\\n\"), TAINT_MUTATED);\n"
"assert_tainted(strtok(\"\\n\"), TAINT_MUTATED);\n"
"assert_tainted(strtok($bad1, \"\\n\"), TAINT_HTML);\n"
"assert_tainted(strtok(\"\\n\"), TAINT_HTML);\n"
"assert_tainted(strtok($bad1, \"\\n\"), TAINT_MUTATED);\n"
"assert_tainted(strtok(\"\\n\"), TAINT_MUTATED);\n"
"assert_not_tainted(str_replace($good2, $good3, $good1), TAINT_HTML);\n"
"assert_tainted(str_replace($bad2, $good3, $good1), TAINT_HTML);\n"
"assert_tainted(str_replace($good2, $bad1, $good1), TAINT_HTML);\n"
"assert_tainted(str_replace($bad2, $bad1, $good1), TAINT_HTML);\n"
"assert_tainted(str_replace($good2, $good3, $bad1), TAINT_HTML);\n"
"assert_tainted(str_replace($bad2, $good3, $bad1), TAINT_HTML);\n"
"assert_tainted(str_replace($good2, $bad1, $bad1), TAINT_HTML);\n"
"assert_tainted(str_replace($bad2, $bad1, $bad1), TAINT_HTML);\n"
"assert_tainted(str_replace($good2, $good3, $good1), TAINT_MUTATED);\n"
"assert_tainted(str_replace($bad2, $good3, $good1), TAINT_MUTATED);\n"
"assert_tainted(str_replace($good2, $bad1, $good1), TAINT_MUTATED);\n"
"assert_tainted(str_replace($bad2, $bad1, $good1), TAINT_MUTATED);\n"
"assert_tainted(str_replace($good2, $good3, $bad1), TAINT_MUTATED);\n"
"assert_tainted(str_replace($bad2, $good3, $bad1), TAINT_MUTATED);\n"
"assert_tainted(str_replace($good2, $bad1, $bad1), TAINT_MUTATED);\n"
"assert_tainted(str_replace($bad2, $bad1, $bad1), TAINT_MUTATED);\n"
"$bad3 = $good2;\n"
"$bad4 = $good3;\n"
"fb_set_taint($bad3, TAINT_HTML);\n"
"fb_set_taint($bad4, TAINT_SQL);\n"
"$arr = str_replace(\n"
" array($good3, $bad3, 'toto'),\n"
" array($good2, $good3, $bad4),\n"
" array($bad1, $good1)\n"
");\n"
"assert_tainted($arr[0], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_SQL);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[1], TAINT_SQL);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
// If a replacement is not made, no taint, not even MUTATED, is passed.
"assert_not_tainted(str_replace('soup', $good3, $good1), TAINT_MUTATED);\n"
"assert_tainted(str_replace('soup', $good3, $bad1), TAINT_MUTATED);\n"
"$arr = str_replace(\n"
" array($good3, $bad4, 'toto'),\n"
" array($good2, $good3, $bad3),\n"
" array($bad1, $good1)\n"
");\n"
"assert_tainted($arr[0], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_SQL);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_not_tainted($arr[1], TAINT_HTML);\n"
"assert_not_tainted($arr[1], TAINT_SQL);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
"$arr = str_replace(\n"
" array($bad4, $good2, 'bobo'),\n"
" array($good3, $good3, $bad3),\n"
" array($bad1, $good1)\n"
");\n"
"assert_tainted($arr[0], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_SQL);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_not_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[1], TAINT_SQL);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
"assert_not_tainted(substr_replace($good1, $good2, 2, 3), TAINT_HTML);\n"
"assert_not_tainted(substr_replace($good1, $good2, 2), TAINT_HTML);\n"
"assert_tainted(substr_replace($good1, $bad2, 2, 3), TAINT_HTML);\n"
"assert_tainted(substr_replace($good1, $bad2, 2), TAINT_HTML);\n"
"assert_tainted(substr_replace($bad1, $good2, 2, 3), TAINT_HTML);\n"
"assert_tainted(substr_replace($bad1, $good2, 2), TAINT_HTML);\n"
"assert_tainted(substr_replace($bad1, $bad2, 2, 3), TAINT_HTML);\n"
"assert_tainted(substr_replace($bad1, $bad2, 2), TAINT_HTML);\n"
"assert_tainted(substr_replace($good1, $good2, 2, 3), TAINT_MUTATED);\n"
"assert_tainted(substr_replace($good1, $good2, 2), TAINT_MUTATED);\n"
"assert_tainted(substr_replace($good1, $bad2, 2, 3), TAINT_MUTATED);\n"
"assert_tainted(substr_replace($good1, $bad2, 2), TAINT_MUTATED);\n"
"assert_tainted(substr_replace($bad1, $good2, 2, 3), TAINT_MUTATED);\n"
"assert_tainted(substr_replace($bad1, $good2, 2), TAINT_MUTATED);\n"
"assert_tainted(substr_replace($bad1, $bad2, 2, 3), TAINT_MUTATED);\n"
"assert_tainted(substr_replace($bad1, $bad2, 2), TAINT_MUTATED);\n"
/*
"$arr = substr_replace(\n"
" array($bad1, $good1),\n"
" $bad2, 2, 3\n"
");\n"
"assert_tainted($arr[0], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
"$arr = substr_replace(\n"
" array($bad1, $good1),\n"
" array($bad2, $good2),\n"
" 2, 3\n"
");\n"
"assert_tainted($arr[0], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_not_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
"$arr = substr_replace(\n"
" array($bad1, $good1),\n"
" array($good2, $bad2),\n"
" 2, 3\n"
");\n"
"assert_tainted($arr[0], TAINT_HTML);\n"
"assert_tainted($arr[0], TAINT_MUTATED);\n"
"assert_tainted($arr[1], TAINT_HTML);\n"
"assert_tainted($arr[1], TAINT_MUTATED);\n"
*/
"assert_not_tainted(substr($good1, 5, 5), TAINT_HTML);\n"
"assert_tainted(substr($bad1, 5, 5), TAINT_HTML);\n"
"assert_tainted(substr($good1, 5, 5), TAINT_MUTATED);\n"
"assert_tainted(substr($bad1, 5, 5), TAINT_MUTATED);\n"
"assert_not_tainted(str_pad($good1, 5, $good2), TAINT_HTML);\n"
"assert_tainted(str_pad($bad1, 5, $good1), TAINT_HTML);\n"
"assert_tainted(str_pad($good1, 5, $bad1), TAINT_HTML);\n"
"assert_tainted(str_pad($bad1, 5, $bad2), TAINT_HTML);\n"
"assert_not_tainted(str_pad($good1, 5, $good2), TAINT_MUTATED);\n"
"assert_tainted(str_pad($bad1, 5, $good1), TAINT_MUTATED);\n"
"assert_tainted(str_pad($good1, 5, $bad1), TAINT_MUTATED);\n"
"assert_tainted(str_pad($bad1, 5, $bad2), TAINT_MUTATED);\n"
"assert_not_tainted(str_repeat($good1, 5), TAINT_HTML);\n"
"assert_tainted(str_repeat($bad1, 13), TAINT_HTML);\n"
"assert_not_tainted(str_repeat($good1, 5), TAINT_MUTATED);\n"
"assert_tainted(str_repeat($bad1, 13), TAINT_MUTATED);\n"
"assert_not_tainted(wordwrap($good1, 5, $good2, true), TAINT_HTML);\n"
"assert_tainted(wordwrap($bad1, 5, $good1, true), TAINT_HTML);\n"
"assert_tainted(wordwrap($good1, 5, $bad1, true), TAINT_HTML);\n"
"assert_tainted(wordwrap($bad1, 5, $bad2, true), TAINT_HTML);\n"
"assert_tainted(wordwrap($good1, 5, $good2, true), TAINT_MUTATED);\n"
"assert_tainted(wordwrap($bad1, 5, $good1, true), TAINT_MUTATED);\n"
"assert_tainted(wordwrap($good1, 5, $bad1, true), TAINT_MUTATED);\n"
"assert_tainted(wordwrap($bad1, 5, $bad2, true), TAINT_MUTATED);\n"
"fb_set_taint($bad3, TAINT_ALL);\n"
"assert_not_tainted(strtr($good1, $good2, $good3), TAINT_HTML);\n"
"assert_tainted(strtr($good1, $good2, $bad3), TAINT_HTML);\n"
"assert_tainted(strtr($good1, $bad2, $good3), TAINT_HTML);\n"
"assert_tainted(strtr($good1, $bad2, $bad3), TAINT_HTML);\n"
"assert_tainted(strtr($bad1, $good2, $good3), TAINT_HTML);\n"
"assert_tainted(strtr($bad1, $good2, $bad3), TAINT_HTML);\n"
"assert_tainted(strtr($bad1, $bad2, $good3), TAINT_HTML);\n"
"assert_tainted(strtr($bad1, $bad2, $bad3), TAINT_HTML);\n"
"assert_tainted(strtr($good1, $good2, $good3), TAINT_MUTATED);\n"
"assert_tainted(strtr($good1, $good2, $bad3), TAINT_MUTATED);\n"
"assert_tainted(strtr($good1, $bad2, $good3), TAINT_MUTATED);\n"
"assert_tainted(strtr($good1, $bad2, $bad3), TAINT_MUTATED);\n"
"assert_tainted(strtr($bad1, $good2, $good3), TAINT_MUTATED);\n"
"assert_tainted(strtr($bad1, $good2, $bad3), TAINT_MUTATED);\n"
"assert_tainted(strtr($bad1, $bad2, $good3), TAINT_MUTATED);\n"
"assert_tainted(strtr($bad1, $bad2, $bad3), TAINT_MUTATED);\n"
// TODO: Test the other strtr()
"assert_not_tainted(chr(69), TAINT_HTML);\n"
"assert_tainted(chr(69), TAINT_MUTATED);\n"
"assert_not_tainted(strstr($good1, $good2), TAINT_HTML);\n"
"assert_not_tainted(strstr($good1, $bad2), TAINT_HTML);\n"
"assert_tainted(strstr($bad1, $good2), TAINT_HTML);\n"
"assert_tainted(strstr($bad1, $bad2), TAINT_HTML);\n"
"assert_tainted(strstr($good1, $good2), TAINT_MUTATED);\n"
"assert_tainted(strstr($good1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(strstr($bad1, $good2), TAINT_MUTATED);\n"
"assert_tainted(strstr($bad1, $bad2), TAINT_MUTATED);\n"
"assert_not_tainted(strchr($good1, $good2), TAINT_HTML);\n"
"assert_not_tainted(strchr($good1, $bad2), TAINT_HTML);\n"
"assert_tainted(strchr($bad1, $good2), TAINT_HTML);\n"
"assert_tainted(strchr($bad1, $bad2), TAINT_HTML);\n"
"assert_tainted(strchr($good1, $good2), TAINT_MUTATED);\n"
"assert_tainted(strchr($good1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(strchr($bad1, $good2), TAINT_MUTATED);\n"
"assert_tainted(strchr($bad1, $bad2), TAINT_MUTATED);\n"
"assert_not_tainted(strrchr($good1, $good2), TAINT_HTML);\n"
"assert_not_tainted(strrchr($good1, $bad2), TAINT_HTML);\n"
"assert_tainted(strrchr($bad1, $good2), TAINT_HTML);\n"
"assert_tainted(strrchr($bad1, $bad2), TAINT_HTML);\n"
"assert_tainted(strrchr($good1, $good2), TAINT_MUTATED);\n"
"assert_tainted(strrchr($good1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(strrchr($bad1, $good2), TAINT_MUTATED);\n"
"assert_tainted(strrchr($bad1, $bad2), TAINT_MUTATED);\n"
"assert_not_tainted(strpbrk($good1, $good2), TAINT_HTML);\n"
// We'd like this to be
// "assert_not_tainted(strpbrk($good1, $bad2), TAINT_HTML);\n"
"assert_tainted(strpbrk($good1, $bad2), TAINT_HTML);\n"
"assert_tainted(strpbrk($bad1, $good2), TAINT_HTML);\n"
"assert_tainted(strpbrk($bad1, $bad2), TAINT_HTML);\n"
"assert_tainted(strpbrk($good1, $good2), TAINT_MUTATED);\n"
"assert_tainted(strpbrk($good1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(strpbrk($bad1, $good2), TAINT_MUTATED);\n"
"assert_tainted(strpbrk($bad1, $bad2), TAINT_MUTATED);\n"
"$tmp = '%s %s';\n"
"$badpat = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $badpat .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($badpat, TAINT_ALL);\n"
"assert_not_tainted(sprintf('%s %s', $good1, $good2), TAINT_HTML);\n"
"assert_tainted(sprintf('%s %s', $good1, $bad2), TAINT_HTML);\n"
"assert_tainted(sprintf('%s %s', $bad1, $good2), TAINT_HTML);\n"
"assert_tainted(sprintf('%s %s', $bad1, $bad2), TAINT_HTML);\n"
"assert_tainted(sprintf('%s %s', $good1, $good2), TAINT_MUTATED);\n"
"assert_tainted(sprintf('%s %s', $good1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(sprintf('%s %s', $bad1, $good2), TAINT_MUTATED);\n"
"assert_tainted(sprintf('%s %s', $bad1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(sprintf($badpat, $good1, $good2), TAINT_HTML);\n"
"assert_tainted(sprintf($badpat, $good1, $bad2), TAINT_HTML);\n"
"assert_tainted(sprintf($badpat, $bad1, $good2), TAINT_HTML);\n"
"assert_tainted(sprintf($badpat, $bad1, $bad2), TAINT_HTML);\n"
"assert_tainted(sprintf($badpat, $good1, $good2), TAINT_MUTATED);\n"
"assert_tainted(sprintf($badpat, $good1, $bad2), TAINT_MUTATED);\n"
"assert_tainted(sprintf($badpat, $bad1, $good2), TAINT_MUTATED);\n"
"assert_tainted(sprintf($badpat, $bad1, $bad2), TAINT_MUTATED);\n"
"assert_not_tainted(vsprintf('%s %s', array($good1, $good2)), TAINT_HTML);\n"
"assert_tainted(vsprintf('%s %s', array($good1, $bad2)), TAINT_HTML);\n"
"assert_tainted(vsprintf('%s %s', array($bad1, $good2)), TAINT_HTML);\n"
"assert_tainted(vsprintf('%s %s', array($bad1, $bad2)), TAINT_HTML);\n"
"assert_tainted(vsprintf('%s %s', array($good1, $good2)), TAINT_MUTATED);\n"
"assert_tainted(vsprintf('%s %s', array($good1, $bad2)), TAINT_MUTATED);\n"
"assert_tainted(vsprintf('%s %s', array($bad1, $good2)), TAINT_MUTATED);\n"
"assert_tainted(vsprintf('%s %s', array($bad1, $bad2)), TAINT_MUTATED);\n"
"assert_tainted(vsprintf($badpat, array($good1, $good2)), TAINT_HTML);\n"
"assert_tainted(vsprintf($badpat, array($good1, $bad2)), TAINT_HTML);\n"
"assert_tainted(vsprintf($badpat, array($bad1, $good2)), TAINT_HTML);\n"
"assert_tainted(vsprintf($badpat, array($bad1, $bad2)), TAINT_HTML);\n"
"assert_tainted(vsprintf($badpat, array($good1, $good2)), TAINT_MUTATED);\n"
"assert_tainted(vsprintf($badpat, array($good1, $bad2)), TAINT_MUTATED);\n"
"assert_tainted(vsprintf($badpat, array($bad1, $good2)), TAINT_MUTATED);\n"
"assert_tainted(vsprintf($badpat, array($bad1, $bad2)), TAINT_MUTATED);\n"
"ob_start();\n"
"printf('%s %s', $good1, $good2);\n"
"assert_not_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"printf('%s %s', $good1, $bad2);\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"printf('%s %s', $bad1, $good2);\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"printf('%s %s', $bad1, $bad2);\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"printf('%s %s', $good1, $good2);\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"printf('%s %s', $good1, $bad2);\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"printf('%s %s', $bad1, $good2);\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"printf('%s %s', $bad1, $bad2);\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"printf($badpat, $good1, $good2);\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"printf($badpat, $good1, $bad2);\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"printf($badpat, $bad1, $good2);\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"printf($badpat, $bad1, $bad2);\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"printf($badpat, $good1, $good2);\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"printf($badpat, $good1, $bad2);\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"printf($badpat, $bad1, $good2);\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"printf($badpat, $bad1, $bad2);\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"vprintf('%s %s', array($good1, $good2));\n"
"assert_not_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"vprintf('%s %s', array($good1, $bad2));\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"vprintf('%s %s', array($bad1, $good2));\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"vprintf('%s %s', array($bad1, $bad2));\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"vprintf('%s %s', array($good1, $good2));\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"vprintf('%s %s', array($good1, $bad2));\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"vprintf('%s %s', array($bad1, $good2));\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"vprintf('%s %s', array($bad1, $bad2));\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"vprintf($badpat, array($good1, $good2));\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"vprintf($badpat, array($good1, $bad2));\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"vprintf($badpat, array($bad1, $good2));\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"vprintf($badpat, array($bad1, $bad2));\n"
"assert_tainted(ob_get_clean(), TAINT_HTML);\n"
"ob_start();\n"
"vprintf($badpat, array($good1, $good2));\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"vprintf($badpat, array($good1, $bad2));\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"vprintf($badpat, array($bad1, $good2));\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n"
"ob_start();\n"
"vprintf($badpat, array($bad1, $bad2));\n"
"assert_tainted(ob_get_clean(), TAINT_MUTATED);\n",
"");
/**
* Thread
*
* This is an hphp-specific thread-control library which does not require
* taint.
*/
/**
* Thrift
*
* We currently do not taint thrift calls.
*/
/**
* URL: no tests
*
* Currently all functions mutate. Mutating get_headers() currently causes
* segfaults when tracing and requires further investigation (TODO).
*/
/**
* Variable
*
* serialize, unserialize: These two functions both mutate their outputs.
*
* Most other variable functions propagate taint, but do so by reference
* without the need of TaintObservers.
*/
MVCRO("<?php\n"
INIT_TEST_TAINT_STRINGS
"$tmp = 's:5:\"hello\";';\n"
"$serialized_good = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $serialized_good .= $tmp[$i];\n"
"}\n"
"$tmp = 's:11:\"evil string\";';\n"
"$serialized_bad = '';\n"
"for ($i = 0; $i < strlen($tmp); $i++) {\n"
" $serialized_bad .= $tmp[$i];\n"
"}\n"
"unset($tmp);\n"
"fb_set_taint($serialized_bad, TAINT_ALL);\n"
"$good_arr = array($good2 => $good1);\n"
"$mixed_arr = array($good2 => $bad1, $bad2 => $good1);\n"
"$bad_arr = array($bad2 => $bad1);\n"
"var_dump(fb_get_taint(strval($good1), TAINT_ALL));\n"
"var_dump(fb_get_taint(strval($bad1), TAINT_ALL));\n"
"var_dump(fb_get_taint(print_r($good1, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(print_r($bad1, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(print_r($good_arr, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(print_r($mixed_arr, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(print_r($bad_arr, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(var_export($good1, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(var_export($bad1, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(var_export($good_arr, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(var_export($mixed_arr, true), TAINT_ALL));\n"
"var_dump(fb_get_taint(var_export($bad_arr, true), TAINT_ALL));\n"
"ob_start();\n"
"var_export($good1);\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"var_export($bad1);\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"var_dump($good1);\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"var_dump($bad1);\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"debug_zval_dump($good1);\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"ob_start();\n"
"debug_zval_dump($bad1);\n"
"var_dump(fb_get_taint(ob_get_clean(), TAINT_ALL));\n"
"var_dump(fb_get_taint(serialize($good1), TAINT_HTML));\n"
"var_dump(fb_get_taint(serialize($good1), TAINT_MUTATED));\n"
"var_dump(fb_get_taint(serialize($bad1), TAINT_HTML));\n"
"var_dump(fb_get_taint(serialize($bad1), TAINT_MUTATED));\n"
"var_dump(fb_get_taint(unserialize($serialized_good), TAINT_HTML));\n"
"var_dump(fb_get_taint(unserialize($serialized_good), TAINT_MUTATED));\n"
"var_dump(fb_get_taint(unserialize($serialized_bad), TAINT_HTML));\n"
"var_dump(fb_get_taint(unserialize($serialized_bad), TAINT_MUTATED));\n"
"$arr = get_defined_vars();\n"
"var_dump(fb_get_taint($arr['good1'], TAINT_ALL));\n"
"var_dump(fb_get_taint($arr['bad1'], TAINT_ALL));\n"
"$arr = array(\n"
" 'good1' => $good1,\n"
" 'bad1' => $bad1,\n"
");\n"
"extract($arr, EXTR_PREFIX_ALL, 'extract');\n"
"var_dump(fb_get_taint($extract_good1, TAINT_ALL));\n"
"var_dump(fb_get_taint($extract_bad1, TAINT_ALL));\n",
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(true)\n");
/**
* XML (TODO)
* XMLReader (TODO)
* XMLWriter (TODO)
*/
/**
* zlib (TODO)
*/
return true;
}
#endif
bool TestCodeRun::TestParser() {
MVCRO("<?php function foo() { return array(1, 2, 3);} var_dump(foo()[2]);"
,
"int(3)\n"
);
MVCRO("<?php "
":test::go();"
"class :test {"
" static function go() {"
" echo \"Everything's cool\\n\";"
" }"
"}"
,
"Everything's cool\n"
);
MVCRO("<?php\n"
"class Foo {\n"
" public $a;\n"
" static public $b;\n"
" static public $c;\n"
"}\n"
"$foo = new Foo;\n"
"$foo->a = function ($x) { echo '!' . $x; };\n"
"($foo->a)(\"foo\\n\");\n"
"Foo::$b = function ($x) { echo '?' . $x; };\n"
"(Foo::$b)(\"bar\\n\");\n"
"Foo::$c[0] = function ($x) { echo '.' . $x; };\n"
"(Foo::$c[0])(\"baz\\n\");\n"
,
"!foo\n"
"?bar\n"
".baz\n"
);
MVCRO("<?php\n"
"($a) = 1;\n"
"var_dump($a);\n"
"$b = array();\n"
"($b)[0] = 2;\n"
"var_dump($b[0]);\n"
"$c = new stdClass;\n"
"($c)->prop = 3;\n"
"var_dump($c->prop);\n"
,
"int(1)\n"
"int(2)\n"
"int(3)\n"
);
return true;
}
bool TestCodeRun::TestTypeAssertions() {
MVCR("<?php\n"
"function g(&$x) { var_dump($x); }\n"
"function f($x) {\n"
" if (is_array($x)) { \n"
" var_dump($x);\n"
" var_dump($x[0]);\n"
" var_dump($x[0][1]);\n"
" }\n"
" if (is_array($x) && $x) { \n"
" g($x);\n"
" g($x[0]);\n"
" g($x[0][1]);\n"
" }\n"
"}\n"
"f(null);\n"
"f(array());\n"
"f(array(0, 1));\n"
"f(array(array(1 => 1)));\n");
MVCR("<?php\n"
"function f($x) {\n"
" if (is_array($x) && isset($x[0])) { var_dump($x[0]); }\n"
" else if (is_string($x) && $x && $x[0]) { var_dump($x[0]); }\n"
" else if (is_integer($x)) { var_dump($x); }\n"
"}\n"
"f(array(32));\n"
"f('foobar');\n"
"f(32);\n");
MVCR("<?php\n"
"function f($x) {\n"
" $r = is_array($x) ? $x[0] : false;\n"
" var_dump($r);\n"
" $x = is_string($x) && isset($x[0]) ? $x[0] : false;\n"
" var_dump($x);\n"
" $x = is_string($x) && isset($x[1]) ? "
" $x[1] : isset($x[0]) ? $x[0] : false;\n"
" var_dump($x);\n"
"}\n"
"f('');\n"
"f('foo');\n"
"f('f');\n"
"f(array());\n"
"f(array(32));\n");
MVCR("<?php\n"
"class X {\n"
" public $x = 'foo';\n"
"}\n"
"class Y {\n"
" public $y = 'bar';\n"
"}\n"
"class X1 extends X {\n"
" public $x = 'baz';\n"
"}\n"
"function f($x) {\n"
" if ($x instanceof X && isset($x->x)) {\n"
" var_dump($x->x);\n"
" }\n"
" if ($x instanceof Y && isset($x->y)) {\n"
" var_dump($x->y);\n"
" }\n"
" if (is_a($x, 'X1')) {\n"
" var_dump($x->x);\n"
" }\n"
"}\n"
"f(null);\n"
"f(new X);\n"
"f(new Y);\n"
"f(new X1);\n"
"f(new stdClass());\n");
MVCR("<?php\n"
"function f($x) {\n"
" while (is_array($x) && isset($x[0])) $x = $x[0];\n"
" var_dump($x);\n"
"}\n"
"function g($x) {\n"
" for (; is_array($x) && isset($x[0]); $x = $x[0]);\n"
" var_dump($x);\n"
"}\n"
"function h($x) {\n"
" if (!is_array($x) || !isset($x[0])) return;\n"
" do {\n"
" $x = $x[0];\n"
" } while (is_array($x) && isset($x[0]));\n"
" var_dump($x);\n"
"}\n"
"f(array(array(array(array('hello')))));\n"
"g(array(array(array(array('hello')))));\n"
"h(array(array(array(array('hello')))));\n");
MVCR("<?php\n"
"function block() {}\n"
"function f($x) {\n"
" if (is_int($x) || is_array($x)) {\n"
" var_dump($x[0]);\n"
" }\n"
"}\n"
"function g($x) {\n"
" $x = (array) $x;\n"
" block();\n"
" var_dump($x[0]);\n"
"}\n"
"f(array(10));\n"
"g(array(10));\n");
MVCR("<?php\n"
"function f($x) {\n"
" if (!is_array($x)) {\n"
" var_dump($x[0]);\n"
" } else if (isset($x[0])) {\n"
" var_dump($x[0]);\n"
" }\n"
" if (!!!is_array($x)) {\n"
" var_dump($x[0]);\n"
" } else if (isset($x[0])) {\n"
" var_dump($x[0]);\n"
" }\n"
"}\n"
"function g($x) {\n"
" if (!is_array($x)) return;\n"
" var_dump($x[0]);\n"
"}\n"
"function h($x) {\n"
" if (!is_array($x) && !is_string($x)) {\n"
" var_dump('1');\n"
" } else {\n"
" var_dump($x[0]);\n"
" }\n"
"}\n"
"function i($x) {\n"
" return !is_array($x) ? $x[0] : $x[0];\n"
"}\n"
"class X implements arrayaccess {\n"
" private $container = array();\n"
" public function __construct($container) {\n"
" $this->container = $container;\n"
" }\n"
" public function offsetSet($offset, $value) {\n"
" if (is_null($offset)) {\n"
" $this->container[] = $value;\n"
" } else {\n"
" $this->container[$offset] = $value;\n"
" } \n"
" }\n"
" public function offsetExists($offset) {\n"
" return isset($this->container[$offset]);\n"
" }\n"
" public function offsetUnset($offset) {\n"
" unset($this->container[$offset]);\n"
" }\n"
" public function offsetGet($offset) {\n"
" return isset($this->container[$offset]) ?\n"
" $this->container[$offset] : null;\n"
" }\n"
"}\n"
"$x = new X(array(0, 1, 2));\n"
"f($x);\n"
"f(array(0, 1, 2));\n"
"g($x);\n"
"g(array(0, 1, 2));\n"
"h(array(0, 1, 2));\n"
"h('foobar');\n"
"h(new stdClass());\n"
"var_dump(i($x));\n"
"var_dump(i(array(0, 1, 2)));\n");
MVCR("<?php\n"
"class Base {\n"
" public function f() {\n"
" var_dump('Base::f');\n"
" }\n"
"}\n"
"function get() { return true; }\n"
"if (get()) {\n"
" class X {\n"
" public function f() {\n"
" var_dump('X1::f');\n"
" }\n"
" }\n"
"} else {\n"
" class X {\n"
" public function f() {\n"
" var_dump('X2::f');\n"
" }\n"
" }\n"
"}\n"
"class Y extends X {}\n"
"function f($x) {\n"
" if ($x instanceof Base) {\n"
" $x->f();\n"
" }\n"
" if ($x instanceof X) {\n"
" $x->f();\n"
" }\n"
" if ($x instanceof Y) {\n"
" $x->f();\n"
" }\n"
"}\n"
"f(new Base);\n"
"f(new X);\n"
"f(new Y);\n");
MVCR("<?php\n"
"function f($x) {\n"
" var_dump(is_array($x), $x[0]);\n"
"}\n"
"f(array(0));\n"
"f('foo');\n");
MVCR("<?php\n"
"class X {\n"
" public $propX;\n"
" function baz() {\n"
" echo 'X';\n"
" }\n"
" function foo() {\n"
" if ($this instanceof Y) {\n"
" $this->bar();\n"
" $this->baz();\n"
" var_dump($this->propX);\n"
" return $this->propY;\n"
" }\n"
" return null;\n"
" }\n"
"}\n"
"class Y extends X {\n"
" public $propY;\n"
" function bar(){\n"
" echo 'Y';\n"
" }\n"
"}\n"
"$y = new Y;\n"
"$y->propX = 16;\n"
"$y->propY = 32;\n"
"var_dump($y->foo());\n"
"class A1 {\n"
" public $a1prop;\n"
" function a1method() {\n"
" return 0;\n"
" }\n"
" function doStuff() {\n"
" if ($this instanceof D1) {\n"
" var_dump($this->d1prop);\n"
" var_dump($this->d1method());\n"
" } else if ($this instanceof C1) {\n"
" var_dump($this->c1prop);\n"
" var_dump($this->c1method());\n"
" } else if ($this instanceof B1) {\n"
" var_dump($this->b1prop);\n"
" var_dump($this->b1method());\n"
" } else if ($this instanceof A1) {\n"
" var_dump($this->a1prop);\n"
" var_dump($this->a1method());\n"
" }\n"
" }\n"
"}\n"
"class B1 extends A1 {\n"
" public $b1prop;\n"
" function b1method() {\n"
" return 1;\n"
" }\n"
"}\n"
"if (rand(0, 1)) {\n"
" class C1 extends B1 {\n"
" public $c1prop;\n"
" function c1method() {\n"
" return 2;\n"
" }\n"
" }\n"
"} else {\n"
" class C1 extends B1 {\n"
" public $c1prop;\n"
" function c1method() {\n"
" return 2;\n"
" }\n"
" }\n"
"}\n"
"class D1 extends C1 {\n"
" public $d1prop;\n"
" function d1method() {\n"
" return 3;\n"
" }\n"
"}\n"
"$a1 = new A1;\n"
"$a1->a1prop = 0;\n"
"$a1->doStuff();\n"
"$b1 = new B1;\n"
"$b1->b1prop = 1;\n"
"$b1->doStuff();\n"
"$c1 = new C1;\n"
"$c1->c1prop = 2;\n"
"$c1->doStuff();\n"
"$d1 = new D1;\n"
"$d1->d1prop = 3;\n"
"$d1->doStuff();\n");
MVCR("<?php\n"
" function foo() {\n"
" }\n"
" function main() {\n"
" var_dump(is_null(foo()));\n"
" }\n"
" main();\n");
return true;
}
bool TestCodeRun::TestTraits() {
MVCRO(
"<?php\n"
"trait this_is_a_trait { }\n"
"?>\n"
,
""
);
MVCRO(
"<?php\n"
"class Base {\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"trait SayWorld {\n"
" public function sayHello() {\n"
" parent::sayHello();\n"
" echo 'World!';\n"
" }\n"
"}\n"
"class MyHelloWorld extends Base {\n"
" use SayWorld;\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"trait HelloWorld {\n"
" public function sayHello() {\n"
" echo \"Hello World!\\n\";\n"
" }\n"
"}\n"
"class TheWorldIsNotEnough {\n"
" use HelloWorld;\n"
" public function sayHello() {\n"
" echo \"Hello Universe!\\n\";\n"
" }\n"
"}\n"
"$o = new TheWorldIsNotEnough();\n"
"$o->sayHello();\n"
"?>\n"
,
"Hello Universe!\n"
);
MVCRO(
"<?php\n"
"trait Hello {\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"trait World {\n"
" public function sayWorld() {\n"
" echo 'World';\n"
" }\n"
"}\n"
"class MyHelloWorld {\n"
" use Hello, World;\n"
" public function sayExclamationMark() {\n"
" echo \"!\\n\";\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"$o->sayWorld();\n"
"$o->sayExclamationMark();\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"trait Hello {\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"trait World {\n"
" public function sayWorld() {\n"
" echo 'World';\n"
" }\n"
" use Hello;\n"
"}\n"
"class MyHelloWorld {\n"
" use World;\n"
" public function sayExclamationMark() {\n"
" echo \"!\\n\";\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"$o->sayWorld();\n"
"$o->sayExclamationMark();\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"trait SayWorld {\n"
" public function sayHelloWorld() {\n"
" $this->sayHello();\n"
" echo 'World!';\n"
" }\n"
"}\n"
"class MyHelloWorld {\n"
" use SayWorld;\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHelloWorld();\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"trait SayWorld {\n"
" public function sayHello() {\n"
" echo 'Hello from trait!';\n"
" }\n"
"}\n"
"class MyHelloWorld {\n"
" public function sayHello() {\n"
" echo 'Hello from class!';\n"
" }\n"
" use SayWorld;\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"?>\n\n"
,
"Hello from class!\n"
);
MVCRO(
"<?php\n"
"trait SayWorld {\n"
" public function sayHello() {\n"
" echo 'Hello from trait!';\n"
" }\n"
"}\n"
"class Base {\n"
" public function sayHello() {\n"
" echo 'Hello from Base!';\n"
" }\n"
"}\n"
"class MyHelloWorld extends Base{\n"
" use SayWorld;\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"?>\n\n"
,
"Hello from trait!\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT1 {\n"
" public function sayHello() {\n"
" echo 'Hello from MY_TRAIT1!';\n"
" }\n"
"}\n"
"trait MY_TRAIT2 {\n"
" public function sayHello() {\n"
" echo 'Hello from MY_TRAIT2!';\n"
" }\n"
"}\n"
"trait MY_TRAIT3 {\n"
" public function sayHello() {\n"
" echo 'Hello from MY_TRAIT3!';\n"
" }\n"
"}\n"
"class MyHelloWorld{\n"
" use MY_TRAIT1, MY_TRAIT2, MY_TRAIT3 {\n"
" MY_TRAIT2::sayHello insteadof MY_TRAIT1, MY_TRAIT3;\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"?>\n\n"
,
"Hello from MY_TRAIT2!\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT1 {\n"
" public function sayHello() {\n"
" echo 'Hello from MY_TRAIT1!';\n"
" }\n"
"}\n"
"class MyHelloWorld{\n"
" use MY_TRAIT1 {\n"
" MY_TRAIT1::sayHello as falaOi;\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->falaOi();\n"
"?>\n\n"
,
"Hello from MY_TRAIT1!\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT1 {\n"
" public function sayHello() {\n"
" echo \"Hello from MY_TRAIT1!\\n\";\n"
" }\n"
"}\n"
"trait MY_TRAIT2 {\n"
" use MY_TRAIT1;\n"
" public function sayGoodbye() {\n"
" echo \"Goodbye from MY_TRAIT2!\\n\";\n"
" }\n"
"}\n"
"class MyHelloWorld{\n"
" use MY_TRAIT2 {\n"
" MY_TRAIT2::sayHello as falaOi;\n"
" MY_TRAIT2::sayGoodbye as falaTchau;\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->falaOi();\n"
"$o->falaTchau();\n"
"$o->sayHello();\n"
"$o->sayGoodbye();\n"
"?>\n"
,
"Hello from MY_TRAIT1!\n"
"Goodbye from MY_TRAIT2!\n"
"Hello from MY_TRAIT1!\n"
"Goodbye from MY_TRAIT2!\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT2 {\n"
" protected function sayGoodbye() {\n"
" echo \"Goodbye from MY_TRAIT2!\\n\";\n"
" }\n"
"}\n"
"class MyHelloWorld{\n"
" use MY_TRAIT2 {\n"
" MY_TRAIT2::sayGoodbye as public falaTchau;\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->falaTchau();\n"
"?>\n"
,
"Goodbye from MY_TRAIT2!\n"
);
MVCRO(
"<?php\n"
"trait Company {\n"
" public function getName() {\n"
" return 'Facebook';\n"
" }\n"
"}\n"
"trait Person {\n"
" public function getName() {\n"
" return 'Ottoni';\n"
" }\n"
"}\n"
"class Language{}\n"
"class English extends Language {\n"
" use Company, Person {\n"
" Person::getName insteadof Company;\n"
" Company::getName as getCompanyName;\n"
" }\n"
" public function sayHello() {\n"
" echo \"Hello \" . $this->getCompanyName() . \"\\n\";\n"
" echo \"I'm \" . $this->getName() . \"\\n\";\n"
" }\n"
"}\n"
"class Portuguese extends Language {\n"
" use Company, Person {\n"
" Person::getName insteadof Company;\n"
" Company::getName as getCompanyName;\n"
" }\n"
" public function sayHello() {\n"
" echo \"Oi \" . $this->getCompanyName() . \"\\n\";\n"
" echo \"Eu sou \" . $this->getName() . \"\\n\";\n"
" }\n"
"}\n"
"$e = new English();\n"
"$e->sayHello();\n"
"$p = new Portuguese();\n"
"$p->sayHello();\n"
,
"Hello Facebook\n"
"I'm Ottoni\n"
"Oi Facebook\n"
"Eu sou Ottoni\n"
);
MVCRO(
"<?php\n"
"trait A {\n"
" public function say() {\n"
" echo \"Hello\\n\";\n"
" }\n"
"}\n"
"trait B {\n"
" use A {\n"
" A::say as fala;\n"
" }\n"
"}\n"
"class Talker {\n"
" use B;\n"
"}\n"
"$talker = new Talker();\n"
"$talker->fala();\n"
"?>\n"
,
"Hello\n"
);
MVCRO(
"<?php\n"
"trait English {\n"
" public function say() {\n"
" echo \"Banana\\n\";\n"
" }\n"
"}\n"
"trait Portugues {\n"
" use English {\n"
" English::say as fala;\n"
" }\n"
"}\n"
"trait Italiano {\n"
" use Portugues {\n"
" Portugues::fala as parla;\n"
" }\n"
"}\n"
"class Talker {\n"
" use Italiano;\n"
"}\n"
"$talker = new Talker();\n"
"$talker->say();\n"
"$talker->fala();\n"
"$talker->parla();\n"
"?>\n"
,
"Banana\n"
"Banana\n"
"Banana\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT {\n"
" public function sayHello() {\n"
" echo 'World!';\n"
" }\n"
"}\n"
"class MY_CLASS {\n"
" use MY_TRAIT;\n"
"}\n"
"$MY_OBJ = new MY_CLASS();\n"
"$MY_OBJ->sayHello();\n"
"?>\n\n"
,
"World!\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT1 {\n"
" public function sayHello() {\n"
" echo \"Hello from MY_TRAIT1\\n\";\n"
" }\n"
"}\n"
"trait MY_TRAIT2 {\n"
" use MY_TRAIT1;\n"
" public function sayHello() {\n"
" echo \"Hello from MY_TRAIT2\\n\";\n"
" }\n"
"}\n"
"class MY_CLASS {\n"
" use MY_TRAIT2;\n"
"}\n"
"$o = new MY_CLASS;\n"
"$o->sayHello();\n"
"?>\n"
,
"Hello from MY_TRAIT2\n"
);
MVCRO(
"<?php\n"
"trait Company {\n"
" public function getName() {\n"
" return 'Facebook';\n"
" }\n"
"}\n"
"class English {\n"
" use Company;\n"
" public function getHi() {\n"
" return \"Hi \";\n"
" }\n"
" public function sayHello() {\n"
" echo $this->getHi() . $this->getName();\n"
" }\n"
"}\n"
"$e = new English();\n"
"$e->sayHello();\n"
"?>\n\n"
,
"Hi Facebook\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" function foo() {\n"
" echo \"Foo\";\n"
" $this->bar();\n"
" }\n"
" abstract function bar();\n"
"}\n"
"class C {\n"
" use T;\n"
" function bar() {\n"
" echo \"BAR!\\n\";\n"
" }\n"
"}\n"
"$x = new C();\n"
"$x->foo();\n"
"?>\n"
,
"FooBAR!\n"
);
MVCRO(
"<?php\n"
"trait SayWorld {\n"
" public function sayHelloWorld() {\n"
" self::sayHello();\n"
" echo 'World!';\n"
" }\n"
"}\n"
"class MyHelloWorld {\n"
" use SayWorld;\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHelloWorld();\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"class A {\n"
" public static function who() {\n"
" echo \"A: \" . __CLASS__;\n"
" }\n"
" use T;\n"
"}\n"
"trait T {\n"
" public static function test() {\n"
" static::who(); // Here comes Late Static Bindings\n"
" }\n"
"}\n"
"class B extends A {\n"
" public static function who() {\n"
" echo \"B: \" . __CLASS__;\n"
" }\n"
"}\n"
"B::test();\n"
"?>\n\n"
,
"B: B\n"
);
MVCRO(
"<?php\n"
"trait T1 {\n"
" private function Func1() { echo \"Hello\"; }\n"
"}\n"
"class C {\n"
" use T1 {\n"
" T1::Func1 as public;\n"
" }\n"
"}\n"
"$o = new C;\n"
"$o->Func1();\n"
"?>\n\n"
,
"Hello\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" public $y = 3;\n"
"}\n"
"class C {\n"
" public $x = 10;\n"
" use T;\n"
" public function printY() {\n"
" echo \"x = \" . $this->x . \"\\n\";\n"
" echo \"y = \" . $this->y . \"\\n\";\n"
" }\n"
"}\n"
"class D {\n"
" public $y = 4;\n"
"}\n"
"$o = new C;\n"
"$o->printY();\n"
"?>\n"
,
"x = 10\n"
"y = 3\n"
);
MVCRO(
"<?php\n"
"trait T1 {\n"
" public $y = 3;\n"
"}\n"
"trait T2 {\n"
" public $x = 4;\n"
"}\n"
"class C {\n"
" use T1, T2;\n"
" public function printProps() {\n"
" var_dump($this->y);\n"
" var_dump($this->x);\n"
" }\n"
"}\n"
"$o = new C;\n"
"$o->printProps();\n"
"?>\n"
,
"int(3)\n"
"int(4)\n"
);
MVCRO(
"<?php\n"
"trait T1 {\n"
" var $x = 1977;\n"
"}\n"
"trait T2 {\n"
" var $x = 1977;\n"
"}\n"
"class MY_CLASS {\n"
" use T1, T2;\n"
" var $abc = 1;\n"
" public function printProps() {\n"
" var_dump($this->x);\n"
" }\n"
"}\n"
"$o = new MY_CLASS;\n"
"$o->printProps();\n"
"?>\n"
,
"int(1977)\n"
);
MVCRO(
"<?php\n"
"trait T1 {\n"
" public $x = 3;\n"
"}\n"
"trait T2 {\n"
" use T1;\n"
"}\n"
"trait T3 {\n"
" use T1;\n"
"}\n"
"class C {\n"
" use T2, T3;\n"
" public function printProps() {\n"
" var_dump($this->x);\n"
" }\n"
"}\n"
"$o = new C;\n"
"$o->printProps();\n"
"?>\n"
,
"int(3)\n"
);
MVCRO(
"<?php\n"
"class MY_BASE {\n"
" static public $x = 3;\n"
"}\n"
"trait MY_TRAIT {\n"
" static public $x = 3;\n"
"}\n"
"class MY_CLASS extends MY_BASE {\n"
" use MY_TRAIT;\n"
" public function printX() {\n"
" var_dump(self::$x);\n"
" self::$x = 4;\n"
" }\n"
"}\n"
"$o = new MY_CLASS;\n"
"$o->printX();\n"
"var_dump(MY_BASE::$x);\n"
"var_dump(MY_CLASS::$x);\n"
"?>\n"
,
"int(3)\n"
"int(3)\n"
"int(4)\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT {\n"
" static public $x = 3;\n"
"}\n"
"class MY_CLASS{\n"
" use MY_TRAIT;\n"
" public function printX() {\n"
" var_dump(self::$x);\n"
" }\n"
"}\n"
"$o = new MY_CLASS;\n"
"$o->printX();\n"
"?>\n"
,
"int(3)\n"
);
MVCRO(
"<?php\n"
"class MY_BASE {\n"
" public $x = 3;\n"
"}\n"
"trait MY_TRAIT {\n"
" public $x = 4;\n"
"}\n"
"class MY_CLASS extends MY_BASE {\n"
" use MY_TRAIT;\n"
" public $x = 4;\n"
" public function printX() {\n"
" var_dump($this->x);\n"
" }\n"
"}\n"
"$o = new MY_CLASS;\n"
"$o->printX();\n"
"?>\n"
,
"int(4)\n"
);
MVCRO(
"<?php\n"
"class MY_BASE {\n"
" public $x = \"123\";\n"
"}\n"
"trait MY_TRAIT {\n"
" public $x = \"123\";\n"
"}\n"
"class MY_CLASS extends MY_BASE {\n"
" use MY_TRAIT;\n"
" public function printX() {\n"
" var_dump($this->x);\n"
" }\n"
"}\n"
"$o = new MY_CLASS;\n"
"$o->printX();\n"
"?>\n"
,
"string(3) \"123\"\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT {\n"
" public $x;\n"
"}\n"
"class MY_CLASS{\n"
" use MY_TRAIT;\n"
" public $x;\n"
" public function printX() {\n"
" var_dump($this->x);\n"
" $this->x = 10;\n"
" var_dump($this->x);\n"
" }\n"
"}\n"
"$o = new MY_CLASS;\n"
"$o->printX();\n"
"?>\n"
,
"NULL\n"
"int(10)\n"
);
MVCRO(
"<?php\n"
"trait A {\n"
" public function smallTalk() {\n"
" echo \"a\\n\";\n"
" }\n"
" public function bigTalk($n) {\n"
" if ($n == 0) return;\n"
" echo \"A$n\\n\";\n"
" $m = $n - 1;\n"
" $this->bigTalk($m);\n"
" }\n"
"}\n"
"trait B {\n"
" public function smallTalk() {\n"
" echo \"b\\n\";\n"
" }\n"
" public function bigTalk($n) {\n"
" if ($n == 0) return;\n"
" echo \"B$n\\n\";\n"
" $this->bigTalk($n - 1);\n"
" }\n"
"}\n"
"class Talker {\n"
" use A, B {\n"
" B::smallTalk insteadof A;\n"
" A::bigTalk insteadof B;\n"
" B::bigTalk as bTalk;\n"
" }\n"
"}\n"
"$talker = new Talker();\n"
"$talker->smallTalk();\n"
"$talker->bigTalk(1);\n"
"$talker->bTalk(2);\n"
"?>\n"
,
"b\n"
"A1\n"
"B2\n"
"A1\n"
);
MVCRO(
"<?php\n"
"trait A {\n"
" function p() {\n"
" echo \"A\\n\";\n"
" }\n"
"}\n"
"trait B {\n"
" function p() {\n"
" echo \"B\\n\";\n"
" }\n"
"}\n"
"trait C {\n"
" function p() {\n"
" echo \"C\\n\";\n"
" }\n"
"}\n"
"class ABC {\n"
" use A, B, C {\n"
" A::p insteadof B, C;\n"
" }\n"
"}\n"
"$abc = new ABC();\n"
"$abc->p();\n"
"?>\n"
,
"A\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" function foo() {\n"
" echo \"Foo\";\n"
" parent::bar();\n"
" echo \"__class__: \" . __class__ . \"\\n\";\n"
" }\n"
"}\n"
"class C {\n"
" function bar() {\n"
" echo \"BAR!\\n\";\n"
" }\n"
"}\n"
"class D extends C {\n"
" use T;\n"
"}\n"
"$x = new D();\n"
"$x->foo();\n"
"?>\n"
,
"FooBAR!\n"
"__class__: D\n"
);
MVCRO(
"<?php\n"
"trait Counter {\n"
" public function inc() {\n"
" static $c = 0;\n"
" $c = $c + 1;\n"
" echo \"$c\\n\";\n"
" }\n"
"}\n"
"class C1 {\n"
" use Counter;\n"
"}\n"
"class C2 {\n"
" use Counter;\n"
"}\n"
"$o = new C1();\n"
"$o->inc();\n"
"$p = new C2();\n"
"$p->inc();\n"
"$o->inc();\n"
"$p->inc();\n"
"?>\n"
,
"1\n"
"1\n"
"2\n"
"2\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" public static function F() {\n"
" echo \"Hello from static function!\\n\";\n"
" }\n"
"}\n"
"class C {\n"
" use T;\n"
"}\n"
"C::F();\n"
"?>\n"
,
"Hello from static function!\n"
);
MVCRO(
"<?php\n"
"trait T1 {\n"
" static function hello() {\n"
" echo \"Hello \";\n"
" }\n"
"}\n"
"trait T2 {\n"
" use T1;\n"
" static function world() {\n"
" echo \"World!\\n\";\n"
" }\n"
"}\n"
"class C {\n"
" use T2;\n"
" static function p() {\n"
" self::hello();\n"
" self::world();\n"
" }\n"
"}\n"
"C::p();\n"
"?>\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"trait T1 {\n"
" static function hello() {\n"
" echo \"Hello \";\n"
" self::world();\n"
" }\n"
"}\n"
"trait T2 {\n"
" use T1;\n"
" static function world() {\n"
" echo \"World!\\n\";\n"
" }\n"
"}\n"
"class C {\n"
" use T2;\n"
" static function p() {\n"
" self::hello();\n"
" self::world();\n"
" }\n"
"}\n"
"C::p();\n"
"?>\n"
,
"Hello World!\n"
"World!\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" function foo() {\n"
" echo \"Foo\";\n"
" parent::bar();\n"
" echo \"I'm in class \" . get_class() . \"\\n\";\n"
" }\n"
"}\n"
"class C {\n"
" function bar() {\n"
" echo \"BAR!\\n\";\n"
" }\n"
"}\n"
"class D extends C {\n"
" use T;\n"
"}\n"
"$x = new D();\n"
"$x->foo();\n"
"?>\n"
,
"FooBAR!\n"
"I'm in class D\n"
);
MVCRO(
"<?php\n"
"trait HelloWorld {\n"
" private function sayHello() {\n"
" echo \"Hello World!\\n\";\n"
" }\n"
"}\n"
"class MyClass1 {\n"
" use HelloWorld {\n"
" sayHello as public;\n"
" }\n"
"}\n"
"class MyClass2 {\n"
" use HelloWorld {\n"
" sayHello as final;\n"
" }\n"
"}\n"
"$a = new MyClass1;\n"
"$a->sayHello();\n"
"$a = new MyClass2;\n"
"$a->sayHello();\n"
"?>\n"
,
"Hello World!\n"
"Hello World!\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"trait THello1 {\n"
" public $hello = \"Hello\";\n"
"}\n"
"trait THello2 {\n"
" private $world = \"World!\\n\";\n"
"}\n"
"class TraitsTest {\n"
" use THello1;\n"
" use THello2;\n"
" function test() {\n"
" echo $this->hello . ' ' . $this->world;\n"
" }\n"
"}\n"
"var_dump(property_exists('TraitsTest', 'hello'));\n"
"var_dump(property_exists('TraitsTest', 'world'));\n"
"$t = new TraitsTest;\n"
"$t->test();\n"
"?>\n"
,
"bool(true)\n"
"bool(true)\n"
"Hello World!\n"
);
MVCRO(
"<?php\n"
"class Base {\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"class MyHelloWorld extends Base {\n"
" use SayWorld;\n"
"}\n"
"trait SayWorld {\n"
" public function sayHello() {\n"
" parent::sayHello();\n"
" echo 'World!';\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"trait Hello {\n"
" public function say() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"trait World {\n"
" public function say() {\n"
" echo 'World';\n"
" }\n"
"}\n"
"class MyHelloWorld {\n"
" use Hello {\n"
" Hello::say as sayHello;\n"
" }\n"
" public function say() {\n"
" $this->sayHello();\n"
" $this->sayWorld();\n"
" echo \"!\\n\";\n"
" }\n"
" use World {\n"
" World::say as sayWorld;\n"
" }\n"
"}\n"
"$o = new MyHelloWorld();\n"
"$o->say();\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"trait Hello {\n"
" public function sayHello() {\n"
" echo \"Hello\\n\";\n"
" }\n"
"}\n"
"trait Hello1 {\n"
" use Hello;\n"
"}\n"
"trait Hello2 {\n"
" use Hello;\n"
"}\n"
"class MyClass {\n"
" use Hello1, Hello2 {\n"
" Hello1::sayHello insteadof Hello2;\n"
" }\n"
"}\n"
"$o = new MyClass();\n"
"$o->sayHello();\n"
,
"Hello\n"
);
MVCRO(
"<?php\n"
"trait Hello {\n"
" public function sayHello() {\n"
" echo \"Hello\\n\";\n"
" }\n"
"}\n"
"trait Hello1 {\n"
" public function sayNum() {\n"
" echo \"1\\n\";\n"
" }\n"
"}\n"
"trait Hello2 {\n"
" public function sayNum() {\n"
" echo \"2\\n\";\n"
" }\n"
"}\n"
"class MyClass {\n"
" use Hello1, Hello2 {\n"
" Hello1::sayNum insteadof Hello2;\n"
" }\n"
" use Hello2 {\n"
" }\n"
"}\n"
"$o = new MyClass();\n"
"$o->sayNum();\n"
,
"1\n"
);
MVCRO(
"<?php\n"
"trait Hello1 {\n"
" public function sayNum() {\n"
" echo \"1\\n\";\n"
" }\n"
"}\n"
"trait Hello2 {\n"
" public function sayNum() {\n"
" echo \"2\\n\";\n"
" }\n"
"}\n"
"class MyClass {\n"
" use Hello1 {\n"
" Hello1::sayNum insteadof Hello2;\n"
" }\n"
" use Hello2;\n"
"}\n"
"$o = new MyClass();\n"
"$o->sayNum();\n"
,
"1\n"
);
MVCRO(
"<?php\n"
"trait MyTrait {\n"
" public function say_meth() {\n"
" echo \"meth: MyTrait\\n\";\n"
" }\n"
"}\n"
"class MyBase {\n"
" public function say_meth() {\n"
" echo \"meth: MyBase\\n\";\n"
" }\n"
"}\n"
"class MyClass {\n"
" use MyTrait;\n"
" public function print_meth() {\n"
" echo \"meth: MyClass\\n\";\n"
" }\n"
"}\n"
"$o = new MyClass();\n"
"$o->print_meth();\n"
,
"meth: MyClass\n"
);
MVCRO(
"<?php\n"
"trait A {\n"
" public function say() {\n"
" echo \"Hello\";\n"
" }\n"
"}\n"
"trait B {\n"
" use A {\n"
" A::say as fala;\n"
" }\n"
"}\n"
"class Talker {\n"
" use B;\n"
"}\n"
"$talker = new Talker();\n"
"$talker->fala();\n"
"?>\n\n"
,
"Hello\n"
);
MVCRO(
"<?php\n"
"class Direct {\n"
" use TestTrait;\n"
"}\n"
"class IndirectInheritance extends Direct {\n"
"}\n"
"trait TestTraitIndirect {\n"
" use TestTrait;\n"
"}\n"
"class Indirect {\n"
" use TestTraitIndirect;\n"
"}\n"
"function test() {\n"
" return \"__TRAIT__: <\" . __TRAIT__ .\n"
" \"> __CLASS__: <\" . __CLASS__ .\n"
" \"> __METHOD__: <\" . __METHOD__ . \">\";\n"
"}\n"
"class NoTraitUsed {\n"
" public static function test() {\n"
" return \"__TRAIT__: <\" . __TRAIT__ .\n"
" \"> __CLASS__: <\" . __CLASS__ .\n"
" \"> __METHOD__: <\" . __METHOD__ . \">\";\n"
" }\n"
"}\n"
"trait TestTrait {\n"
" public static function test() {\n"
" return \"__TRAIT__: <\" . __TRAIT__ .\n"
" \"> __CLASS__: <\" . __CLASS__ .\n"
" \"> __METHOD__: <\" . __METHOD__ . \">\";\n"
" }\n"
"}\n"
"echo Direct::test().\"\\n\";\n"
"echo IndirectInheritance::test().\"\\n\";\n"
"echo Indirect::test().\"\\n\";\n"
"echo NoTraitUsed::test().\"\\n\";\n"
"echo test().\"\\n\";\n"
,
"__TRAIT__: <TestTrait> __CLASS__: <Direct> __METHOD__: <TestTrait::test>\n"
"__TRAIT__: <TestTrait> __CLASS__: <Direct> __METHOD__: <TestTrait::test>\n"
"__TRAIT__: <TestTrait> __CLASS__: <Indirect> __METHOD__: <TestTrait::test>\n"
"__TRAIT__: <> __CLASS__: <NoTraitUsed> __METHOD__: <NoTraitUsed::test>\n"
"__TRAIT__: <> __CLASS__: <> __METHOD__: <test>\n"
);
MVCRO(
"<?php\n"
"trait HelloWorld {\n"
" private function sayHello() {\n"
" echo \"Hello World 1!\\n\";\n"
" }\n"
"}\n"
"trait HelloWorld2 {\n"
" public function sayHello2() {\n"
" echo \"Hello World 2!\\n\";\n"
" }\n"
"}\n"
"class MyClass1 {\n"
" use HelloWorld2 {\n"
" sayHello as public;\n"
" }\n"
" use HelloWorld;\n"
"}\n"
"$a = new MyClass1;\n"
"$a->sayHello();\n"
"$a->sayHello2();\n"
"?>\n"
,
"Hello World 1!\n"
"Hello World 2!\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT {\n"
" public function sayHello() {\n"
" echo \"Hello World!\\n\";\n"
" }\n"
"}\n"
"class MY_CLASS {\n"
" use MY_TRAIT {\n"
" sayHello as falaOi;\n"
" }\n"
"}\n"
"$a = new MY_CLASS;\n"
"$a->falaOi();\n"
"?>\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"class this_is_a_class { }\n"
"interface this_is_an_interface {\n"
" public function this_is_an_interface_method();\n"
"}\n"
"trait this_is_a_trait { }\n"
"abstract class this_is_an_abstract_class { }\n"
"final class this_is_a_final_class { }\n"
"var_dump(get_declared_traits());\n"
"?>\n"
,
"array(1) {\n"
" [0]=>\n"
" string(15) \"this_is_a_trait\"\n"
"}\n"
);
MVCRO(
"<?php\n"
"class this_is_a_class {\n"
" function class_func() {}\n"
"}\n"
"trait this_is_a_trait {\n"
" function trait_func() {}\n"
"}\n"
"interface this_is_an_interface {\n"
" function interface_func();\n"
"}\n"
"$rclass = new ReflectionClass('this_is_a_class');\n"
"var_dump($rclass->isTrait());\n"
"$rtrait = new ReflectionClass('this_is_a_trait');\n"
"var_dump($rtrait->isTrait());\n"
"$rinterface = new ReflectionClass('this_is_an_interface');\n"
"var_dump($rinterface->isTrait());\n"
,
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
);
if (!hhvm) {
MVCRO(
"<?php\n"
"namespace test {\n"
" class a { }\n"
" interface b { }\n"
" trait c { }\n"
" abstract class d { }\n"
" final class e { }\n"
" var_dump(get_declared_traits());\n"
"}\n"
,
"array(1) {\n"
" [0]=>\n"
" string(6) \"test\\c\"\n"
"}\n"
);
}
MVCRO(
"<?php\n"
"class MY_CLASS { }\n"
"interface MY_INTERFACE { }\n"
"trait MY_TRAIT { }\n"
"abstract class MY_ABSTRCT_CLASS { }\n"
"final class MY_FINAL_CLASS { }\n"
"var_dump(get_declared_traits());\n"
"?>\n"
,
"array(1) {\n"
" [0]=>\n"
" string(8) \"MY_TRAIT\"\n"
"}\n"
);
MVCRO(
"<?php\n"
"class MY_CLASS {}\n"
"trait MY_TRAIT {}\n"
"interface MY_INTERFACE {}\n"
"var_dump(trait_exists('MY_CLASS'));\n"
"var_dump(trait_exists('MY_INTERFACE'));\n"
"var_dump(trait_exists('MY_TRAIT'));\n"
"var_dump(trait_exists('UNDECLARED'));\n"
"var_dump(trait_exists(1));\n"
"var_dump(trait_exists(NULL));\n"
,
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
);
if (!hhvm) {
MVCRO(
"<?php\n"
"namespace foo;\n"
"trait IFoo { }\n"
"trait ITest { }\n"
"var_dump(trait_exists('IFoo'));\n"
"var_dump(trait_exists('foo\\\\IFoo'));\n"
"var_dump(trait_exists('FOO\\\\ITEST'));\n"
"?>\n"
,
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
);
}
MVCRO(
"<?php\n"
"trait Foo {\n"
" public function Foo() {\n"
" }\n"
"}\n"
"class Bar {\n"
" use Foo;\n"
" public function Bar() {\n"
" }\n"
"}\n"
"$rfoofoo = new ReflectionMethod('Foo::Foo');\n"
"var_dump($rfoofoo->isConstructor());\n"
"$rbarfoo = new ReflectionMethod('Bar::Foo');\n"
"var_dump($rbarfoo->isConstructor());\n"
"$rbarbar = new ReflectionMethod('Bar::Bar');\n"
"var_dump($rbarbar->isConstructor());\n"
,
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
);
MVCRO(
"<?php\n"
"trait Test {\n"
" public function __construct() { }\n"
" public function __destruct() { }\n"
" public function func() { }\n"
"}\n"
"$rconstr = new ReflectionMethod('Test::__construct');\n"
"$rdestr = new ReflectionMethod('Test::__destruct');\n"
"$rfunc = new ReflectionMethod('Test::func');\n"
"var_dump($rconstr->isConstructor());\n"
"var_dump($rconstr->isDestructor());\n"
"var_dump($rdestr->isConstructor());\n"
"var_dump($rdestr->isDestructor());\n"
"var_dump($rfunc->isConstructor());\n"
"var_dump($rfunc->isDestructor());\n"
,
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
);
if (!hhvm) {
MVCRO(
"<?php\n"
"namespace N1 {\n"
" trait T1 {\n"
" public function hello() { return 'hello from t1'; }\n"
" }\n"
" trait T2 {\n"
" public function hello() { return 'hello from t2'; }\n"
" }\n"
"}\n"
"namespace N2 {\n"
" use N1\\T1;\n"
" use N1\\T2;\n"
" class A {\n"
" use T1, T2 {\n"
" T1::hello insteadof T2;\n"
" T2::hello as foo;\n"
" }\n"
" }\n"
" $a = new A;\n"
" echo $a->hello(), PHP_EOL;\n"
" echo $a->foo(), PHP_EOL;\n"
"}\n"
,
"hello from t1\n"
"hello from t2\n"
);
}
MVCRO(
"<?php\n"
"/* Prototype : proto array get_declared_traits()\n"
" * Description: Returns an array of all declared traits.\n"
" * Source code: Zend/zend_builtin_functions.c\n"
" * Alias to functions:\n"
" */\n"
"$traits = get_declared_traits();\n"
"var_dump($traits);\n"
"var_dump(in_array('T1', $traits));\n"
"var_dump(in_array('T1', get_declared_traits()));\n"
,
"array(0) {\n"
"}\n"
"bool(false)\n"
"bool(false)\n"
);
MVCRO(
"<?php\n"
"trait MY_TRAIT { }\n"
"class MY_CLASS { use MY_TRAIT; }\n"
"$r = new ReflectionClass('MY_CLASS');\n"
"var_dump($r->getTraitNames());\n"
"?>\n"
,
"array(1) {\n"
" [0]=>\n"
" string(8) \"MY_TRAIT\"\n"
"}\n"
);
MVCRO(
"<?php\n"
"trait T1 {}\n"
"trait T2 {}\n"
"trait T3 { use T2; }\n"
"class C1 {}\n"
"class C2 { use T1; }\n"
"class C3 { use T1, T2; }\n"
"class C4 { use T3; }\n"
"class C5 extends C4 {}\n"
"interface I1 {}\n"
"echo \"T1:\\n\";\n"
"var_dump(class_uses('T1'));\n"
"$rt1 = new ReflectionClass('T1');\n"
"var_dump($rt1->getTraitNames());\n"
"echo \"\\nT3:\\n\";\n"
"var_dump(class_uses('T3'));\n"
"$rt3 = new ReflectionClass('T3');\n"
"var_dump($rt3->getTraitNames());\n"
"echo \"\\nC1:\\n\";\n"
"var_dump(class_uses('C1'));\n"
"$rc1 = new ReflectionClass('C1');\n"
"var_dump($rc1->getTraitNames());\n"
"echo \"\\nC2:\\n\";\n"
"var_dump(class_uses('C2'));\n"
"$rc2 = new ReflectionClass('C2');\n"
"var_dump($rc2->getTraitNames());\n"
"echo \"\\nC3:\\n\";\n"
"var_dump(class_uses('C3'));\n"
"$rc3 = new ReflectionClass('C3');\n"
"var_dump($rc3->getTraitNames());\n"
"echo \"\\nC4:\\n\";\n"
"var_dump(class_uses('C4'));\n"
"$rc4 = new ReflectionClass('C4');\n"
"var_dump($rc4->getTraitNames());\n"
"echo \"\\nC5:\\n\";\n"
"var_dump(class_uses('C5'));\n"
"$rc5 = new ReflectionClass('C5');\n"
"var_dump($rc5->getTraitNames());\n"
"echo \"\\nI1:\\n\";\n"
"var_dump(class_uses('I1'));\n"
"$ri1 = new ReflectionClass('I1');\n"
"var_dump($ri1->getTraitNames());\n"
"?>\n"
,
"T1:\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n\n"
"T3:\n"
"array(1) {\n"
" [\"T2\"]=>\n"
" string(2) \"T2\"\n"
"}\n"
"array(1) {\n"
" [0]=>\n"
" string(2) \"T2\"\n"
"}\n\n"
"C1:\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n\n"
"C2:\n"
"array(1) {\n"
" [\"T1\"]=>\n"
" string(2) \"T1\"\n"
"}\n"
"array(1) {\n"
" [0]=>\n"
" string(2) \"T1\"\n"
"}\n\n"
"C3:\n"
"array(2) {\n"
" [\"T1\"]=>\n"
" string(2) \"T1\"\n"
" [\"T2\"]=>\n"
" string(2) \"T2\"\n"
"}\n"
"array(2) {\n"
" [0]=>\n"
" string(2) \"T1\"\n"
" [1]=>\n"
" string(2) \"T2\"\n"
"}\n\n"
"C4:\n"
"array(1) {\n"
" [\"T3\"]=>\n"
" string(2) \"T3\"\n"
"}\n"
"array(1) {\n"
" [0]=>\n"
" string(2) \"T3\"\n"
"}\n\n"
"C5:\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n\n"
"I1:\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
);
MVCRO(
"<?php\n"
"trait T2 {}\n"
"trait T3 { use T2; }\n"
"trait T1 {}\n"
"class C1 { }\n"
"class C2 { use T2; }\n"
"class C3 { use T3, T1; }\n"
"var_dump(class_uses(new C1));\n"
"var_dump(class_uses(new C2));\n"
"var_dump(class_uses(new C3));\n"
,
"array(0) {\n"
"}\n"
"array(1) {\n"
" [\"T2\"]=>\n"
" string(2) \"T2\"\n"
"}\n"
"array(2) {\n"
" [\"T3\"]=>\n"
" string(2) \"T3\"\n"
" [\"T1\"]=>\n"
" string(2) \"T1\"\n"
"}\n"
);
MVCRO(
"<?php\n"
"trait Hello1 {\n"
" public function sayNum() {\n"
" echo \"1\\n\";\n"
" }\n"
"}\n"
"trait Hello2 {\n"
" public function sayNum() {\n"
" echo \"2\\n\";\n"
" }\n"
"}\n"
"class MyClass {\n"
" use Hello1, Hello2 {\n"
" Hello1::sayNum insteadof Hello2;\n"
" }\n"
" use Hello2 {\n"
" }\n"
"}\n"
"var_dump(class_uses('MyClass'));\n"
,
"array(2) {\n"
" [\"Hello1\"]=>\n"
" string(6) \"Hello1\"\n"
" [\"Hello2\"]=>\n"
" string(6) \"Hello2\"\n"
"}\n"
);
MVCRO(
"<?php\n"
"trait T1 { function F() {} }\n"
"trait T2 { function F() {} }\n"
"trait T3 { use T2 { F as G; } }\n"
"class C1 {\n"
" use T1, T2 {\n"
" T1::F insteadof T2;\n"
" T2::F as G;\n"
" }\n"
"}\n"
"class C2 {\n"
" use T3;\n"
"}\n"
"$rc1 = new ReflectionClass('C1');\n"
"var_dump($rc1->getTraitAliases());\n"
"$rc2 = new ReflectionClass('C2');\n"
"var_dump($rc2->getTraitAliases());\n"
"$rc3 = new ReflectionClass('T3');\n"
"var_dump($rc3->getTraitAliases());\n"
,
"array(1) {\n"
" [\"G\"]=>\n"
" string(5) \"T2::F\"\n"
"}\n"
"array(0) {\n"
"}\n"
"array(1) {\n"
" [\"G\"]=>\n"
" string(9) \"(null)::F\"\n"
"}\n"
);
MVCRO(
"<?php\n"
"class C1 {}\n"
"trait T1 {}\n"
"interface I1 {}\n"
"var_dump(class_implements('C1'));\n"
"var_dump(class_parents('C1'));\n"
"var_dump(class_uses('C1'));\n"
"var_dump(class_implements('I1'));\n"
"var_dump(class_parents('I1'));\n"
"var_dump(class_uses('I1'));\n"
"var_dump(class_implements('T1'));\n"
"var_dump(class_parents('T1'));\n"
"var_dump(class_uses('T1'));\n"
,
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" function F(&$a, $b=\"default\") {\n"
" $a .= \" = \" . $b;\n"
" }\n"
"}\n"
"class C {\n"
" use T;\n"
"}\n"
"$o = new C;\n"
"$x = \"value\";\n"
"$o->F($x);\n"
"echo $x;\n"
"echo \"\\n\";\n"
"$y = \"zero\";\n"
"$o->F($y, \"0\");\n"
"echo $y;\n"
"?>\n\n"
,
"value = default\n"
"zero = 0\n"
);
// Zend tests
MVCRO(
"<?php\n"
"echo \"*** Testing class_uses() : basic ***\\n\";\n"
"\n"
"\n"
"trait foo { }\n"
"class fooUser { use foo; }\n"
"\n"
"trait bar { }\n"
"class barUser { use bar; }\n"
"\n"
"class foobarUser { use foo, bar; }\n"
"\n"
"/** There is no semantics for traits in the inheritance chain.\n"
" Traits are flattend into a class, and that semantics is nothing\n"
" like a type, or interface, and thus, not propergated. */\n"
"class fooViaBarUser extends barUser { use foo; }\n"
"\n"
"class fooExtended extends fooUser {}\n"
"\n"
"s_var_dump(class_uses(new foobarUser));\n"
"s_var_dump(class_uses('foobarUser'));\n"
"s_var_dump(class_uses(new fooViaBarUser));\n"
"s_var_dump(class_uses('fooViaBarUser'));\n"
"s_var_dump(class_uses(new fooExtended));\n"
"s_var_dump(class_uses('fooExtended'));\n"
"\n"
"\n"
"function s_var_dump($arr) {\n"
" krsort($arr);\n"
" var_dump($arr);\n"
"}\n"
"?>\n"
"===DONE===\n"
,
"*** Testing class_uses() : basic ***\n"
"array(2) {\n"
" [\"foo\"]=>\n"
" string(3) \"foo\"\n"
" [\"bar\"]=>\n"
" string(3) \"bar\"\n"
"}\n"
"array(2) {\n"
" [\"foo\"]=>\n"
" string(3) \"foo\"\n"
" [\"bar\"]=>\n"
" string(3) \"bar\"\n"
"}\n"
"array(1) {\n"
" [\"foo\"]=>\n"
" string(3) \"foo\"\n"
"}\n"
"array(1) {\n"
" [\"foo\"]=>\n"
" string(3) \"foo\"\n"
"}\n"
"array(0) {\n"
"}\n"
"array(0) {\n"
"}\n"
"===DONE===\n"
);
MVCRO(
"<?php\n"
"\n"
"interface a { }\n"
"\n"
"abstract class b { }\n"
"\n"
"final class c { }\n"
"\n"
"trait d {}\n"
"\n"
"var_dump(class_exists('a'));\n"
"var_dump(class_exists('b'));\n"
"var_dump(class_exists('c'));\n"
"var_dump(class_exists('d'));\n"
"\n"
"?>\n"
,
"bool(false)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait Hello {\n"
" public function saySomething() {\n"
" echo 'Hello';\n"
" }\n"
"}\n"
"\n"
"trait World {\n"
" public function saySomething() {\n"
" echo 'World';\n"
" }\n"
"}\n"
" \n"
"class MyHelloWorld {\n"
" use Hello, World {\n"
" Hello::saySomething insteadof World;\n"
" }\n"
"}\n"
" \n"
"$o = new MyHelloWorld();\n"
"$o->saySomething();\n"
"?>\n\n"
,
"Hello\n"
);
MVCRO(
"<?php\n"
"\n"
"trait Singleton {\n"
" protected static $instances=array();\n"
" abstract protected function __construct($config);\n"
" public static function getInstance($config) {\n"
" if (!isset(self::$instances[$serialize = serialize($config)])) {\n"
" self::$instances[$serialize] = new self($config);\n"
" }\n"
" return self::$instances[$serialize];\n"
" }\n"
"}\n"
"\n"
"class MyHelloWorld {\n"
" use Singleton;\n"
" public function __construct($config)\n"
" {\n"
" var_dump( $config);\n"
" }\n"
"}\n"
"\n"
"\n"
"$o= myHelloWorld::getInstance(1);\n"
"$o= myHelloWorld::getInstance(1);\n"
"$o= myHelloWorld::getInstance(2);\n"
"$o= myHelloWorld::getInstance(array(1=>2));\n"
"$o= myHelloWorld::getInstance(array(1=>2));\n"
"\n"
"?>\n"
,
"int(1)\n"
"int(2)\n"
"array(1) {\n"
" [1]=>\n"
" int(2)\n"
"}\n"
);
MVCRO(
"<?php\n"
"\n"
"trait foo { \n"
" public function __construct() {\n"
" var_dump(__FUNCTION__);\n"
" }\n"
" public function __destruct() {\n"
" var_dump(__FUNCTION__);\n"
" }\n"
"}\n"
"\n"
"class bar {\n"
" use foo;\n"
"}\n"
"\n"
"new bar;\n"
"\n"
"?>\n"
,
"string(11) \"__construct\"\n"
"string(10) \"__destruct\"\n"
);
MVCRO(
"<?php\n"
"\n"
" trait TestTrait {\n"
" public static function test() {\n"
" return 'Test';\n"
" }\n"
" }\n"
"\n"
" class A {\n"
" use TestTrait;\n"
" }\n"
"\n"
" $class = \"A\";\n"
" echo $class::test();\n"
"\n"
"?>\n\n"
,
"Test\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait Hello {\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"\n"
"trait World {\n"
" public function sayWorld() {\n"
" echo 'World!';\n"
" }\n"
"}\n"
"\n"
"trait HelloWorld {\n"
" use Hello, World;\n"
"}\n"
"\n"
"class MyHelloWorld {\n"
" use HelloWorld;\n"
"}\n"
"\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"$o->sayWorld();\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait Counter {\n"
" public function inc() {\n"
" static $c = 0;\n"
" $c = $c + 1;\n"
" echo \"$c\\n\";\n"
" }\n"
"}\n"
"\n"
"\n"
"class C1 {\n"
" use Counter;\n"
"}\n"
"\n"
"$o = new C1();\n"
"$o->inc();\n"
"$o->inc();\n"
"\n"
"?>\n"
,
"1\n"
"2\n"
);
MVCRO(
"<?php\n"
"trait T1 { function m1() { } function m2() { } }\n"
"\n"
"class C1 { }\n"
"class C2 { use T1; }\n"
"class C3 { use T1 { m1 as a1; } }\n"
"class C4 { use T1 { m1 as a1; m2 as a2; } }\n"
"\n"
"for ($c = \"C1\"; $c <= \"C4\"; $c++) {\n"
" echo \"class $c:\\n\";\n"
" $r = new ReflectionClass($c);\n"
" var_dump($r->getTraitAliases());\n"
" echo \"\\n\";\n"
"}\n"
"?>\n"
,
"class C1:\n"
"array(0) {\n"
"}\n"
"\n"
"class C2:\n"
"array(0) {\n"
"}\n"
"\n"
"class C3:\n"
"array(1) {\n"
" [\"a1\"]=>\n"
" string(10) \"(null)::m1\"\n"
"}\n"
"\n"
"class C4:\n"
"array(2) {\n"
" [\"a1\"]=>\n"
" string(10) \"(null)::m1\"\n"
" [\"a2\"]=>\n"
" string(10) \"(null)::m2\"\n"
"}\n"
"\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait Hello {\n"
" public function saySomething() {\n"
" echo 'Hello';\n"
" }\n"
"}\n"
"\n"
"trait World {\n"
" public function saySomething() {\n"
" echo ' World';\n"
" }\n"
"}\n"
" \n"
"class MyHelloWorld {\n"
" use Hello, World {\n"
" Hello::saySomething insteadof World;\n"
" World::saySomething as sayWorld;\n"
" }\n"
"}\n"
" \n"
"$o = new MyHelloWorld();\n"
"$o->saySomething();\n"
"$o->sayWorld();\n"
"?>\n\n"
,
"Hello World\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait THello1 {\n"
" public $hello = \"hello\";\n"
"}\n"
"\n"
"trait THello2 {\n"
" private $world = \"World!\";\n"
"}\n"
"\n"
"class TraitsTest {\n"
" use THello1;\n"
" use THello2;\n"
" function test() {\n"
" echo $this->hello . ' ' . $this->world;\n"
" }\n"
"}\n"
"\n"
"var_dump(property_exists('TraitsTest', 'hello'));\n"
"var_dump(property_exists('TraitsTest', 'world'));\n"
"\n"
"$t = new TraitsTest;\n"
"$t->test();\n"
"?>\n\n"
,
"bool(true)\n"
"bool(true)\n"
"hello World!\n"
);
MVCRO(
"<?php\n"
"\n"
"interface a { }\n"
"\n"
"abstract class b { }\n"
"\n"
"final class c { }\n"
"\n"
"trait d {}\n"
"\n"
"var_dump(trait_exists('a'));\n"
"var_dump(trait_exists('b'));\n"
"var_dump(trait_exists('c'));\n"
"var_dump(trait_exists('d'));\n"
"\n"
"?>\n"
,
"bool(false)\n"
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
);
MVCRO(
"<?php\n"
"\n"
" trait TestTrait {\n"
" public static function test() {\n"
" return get_called_class();\n"
" }\n"
" }\n"
"\n"
" class A {\n"
" use TestTrait;\n"
" }\n"
"\n"
" class B extends A { }\n"
"\n"
" echo B::test();\n"
"\n"
"?>\n\n"
,
"B\n"
);
MVCRO(
"<?php\n"
"\n"
"trait foo { \n"
" public function __toString() {\n"
" return '123';\n"
" }\n"
" \n"
" public function __get($x) {\n"
" var_dump($x);\n"
" }\n"
" \n"
" public function __set($attr, $val) {\n"
" var_dump($attr .'==='. $val);\n"
" }\n"
" \n"
" public function __clone() {\n"
" var_dump(__FUNCTION__);\n"
" }\n"
"}\n"
"\n"
"class bar {\n"
" use foo;\n"
"}\n"
"\n"
"$o = new bar;\n"
"echo $o, PHP_EOL;\n"
"$o->xyz;\n"
"$o->xyz = 2;\n"
"clone $o;\n"
"\n"
"?>\n"
,
"123\n"
"string(3) \"xyz\"\n"
"string(7) \"xyz===2\"\n"
"string(7) \"__clone\"\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait HelloWorld {\n"
" public function sayHello() {\n"
" echo 'Hello World!';\n"
" }\n"
"}\n"
"\n"
"class TheWorldIsNotEnough {\n"
" use HelloWorld;\n"
" public function sayHello() {\n"
" echo 'Hello Universe!';\n"
" }\n"
"}\n"
"\n"
"$o = new TheWorldIsNotEnough();\n"
"$o->sayHello(); // echos Hello Universe!\n"
"?>\n\n"
,
"Hello Universe!\n"
);
MVCRO(
"<?php\n"
"/* Prototype : proto array get_declared_traits()\n"
" * Description: Returns an array of all declared traits. \n"
" * Source code: Zend/zend_builtin_functions.c\n"
" * Alias to functions: \n"
" */\n"
"\n"
"\n"
"echo \"*** Testing get_declared_traits() : basic functionality ***\\n\";\n"
"\n"
"trait MyTrait {}\n"
"\n"
"// Zero arguments\n"
"echo \"\\n-- Testing get_declared_traits() function with Zero arguments --\\n\";\n"
"var_dump(get_declared_traits());\n"
"\n"
"foreach (get_declared_traits() as $trait) {\n"
" if (!trait_exists($trait)) {\n"
" echo \"Error: $trait is not a valid trait.\\n\"; \n"
" }\n"
"}\n"
"\n"
"echo \"\\n-- Ensure trait is listed --\\n\";\n"
"var_dump(in_array('MyTrait', get_declared_traits()));\n"
"\n"
"echo \"\\n-- Ensure userspace interfaces are not listed --\\n\";\n"
"interface I {}\n"
"var_dump(in_array( 'I', get_declared_traits()));\n"
"\n"
"echo \"\\n-- Ensure userspace classes are not listed --\\n\";\n"
"class MyClass {}\n"
"var_dump(in_array( 'MyClass', get_declared_traits()));\n"
"\n"
"\n"
"echo \"Done\";\n"
"?>\n\n"
,
"*** Testing get_declared_traits() : basic functionality ***\n"
"\n"
"-- Testing get_declared_traits() function with Zero arguments --\n"
"array(1) {\n"
" [0]=>\n"
" string(7) \"MyTrait\"\n"
"}\n"
"\n"
"-- Ensure trait is listed --\n"
"bool(true)\n"
"\n"
"-- Ensure userspace interfaces are not listed --\n"
"bool(false)\n"
"\n"
"-- Ensure userspace classes are not listed --\n"
"bool(false)\n"
"Done\n"
);
MVCRO(
"<?php\n"
"\n"
" class MyClass {\n"
" static function test() {\n"
" return __TRAIT__;\n"
" }\n"
" }\n"
" \n"
" function someFun() {\n"
" return __TRAIT__;\n"
" }\n"
" \n"
"\n"
" $t = __TRAIT__;\n"
" var_dump($t);\n"
" $t = MyClass::test();\n"
" var_dump($t);\n"
" $t = someFun();\n"
" var_dump($t);\n"
"?>\n"
,
"string(0) \"\"\n"
"string(0) \"\"\n"
"string(0) \"\"\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"class Base {\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
" \n"
"trait SayWorld {\n"
" public function sayHello() {\n"
" parent::sayHello();\n"
" echo 'World!';\n"
" }\n"
"}\n"
"\n"
"class MyHelloWorld extends Base {\n"
" use SayWorld;\n"
"}\n"
"\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait THello {\n"
" public function hello() {\n"
" echo 'Hello';\n"
" }\n"
"}\n"
"\n"
"class TraitsTest {\n"
" use THello;\n"
"}\n"
"\n"
"$test = new TraitsTest();\n"
"$test->hello();\n"
"?>\n\n"
,
"Hello\n"
);
MVCRO(
"<?php\n"
"trait Foo {\n"
" public function Foo() {\n"
" }\n"
"}\n"
"\n"
"class Bar {\n"
" use Foo;\n"
" public function Bar() {\n"
" }\n"
"}\n"
"\n"
"$rfoofoo = new ReflectionMethod('Foo::Foo');\n"
"var_dump($rfoofoo->isConstructor());\n"
"\n"
"$rbarfoo = new ReflectionMethod('Bar::Foo');\n"
"var_dump($rbarfoo->isConstructor());\n"
"\n"
"$rbarbar = new ReflectionMethod('Bar::Bar');\n"
"var_dump($rbarbar->isConstructor());\n"
"?>\n"
,
"bool(false)\n"
"bool(false)\n"
"bool(true)\n"
);
MVCRO(
"<?php\n"
"/* Prototype : proto bool trait_exists(string traitname [, bool autoload])\n"
" * Description: Checks if the trait exists \n"
" * Source code: Zend/zend_builtin_functions.c\n"
" * Alias to functions: \n"
" */\n"
"\n"
"trait caseSensitivityTest {}\n"
"var_dump(trait_exists('casesensitivitytest'));\n"
"\n"
"echo \"Done\"\n"
"?>\n\n"
,
"bool(true)\n"
"Done\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"abstract class Base {\n"
" abstract function sayWorld();\n"
"}\n"
"\n"
"trait Hello {\n"
" public function sayHello() {\n"
" echo 'Hello';\n"
" }\n"
" public function sayWorld() {\n"
" echo ' World!';\n"
" }\n"
" }\n"
"\n"
"class MyHelloWorld extends Base {\n"
" use Hello;\n"
"}\n"
"\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"$o->sayWorld();\n"
"\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"\n"
" trait TestTrait {\n"
" public static function test() {\n"
" return 'Test';\n"
" }\n"
" }\n"
"\n"
" class A {\n"
" use TestTrait;\n"
" }\n"
"\n"
" echo A::test();\n"
"\n"
"?>\n\n"
,
"Test\n"
);
MVCRO(
"<?php\n"
"\n"
"trait ATrait {\n"
" public static function get_class_name() {\n"
" return __CLASS__;\n"
" }\n"
" \n"
" public function get_class_name_obj() {\n"
" return __CLASS__;\n"
" }\n"
"}\n"
"\n"
"trait Indirect {\n"
" use ATrait;\n"
"}\n"
"\n"
"class SomeClass {\n"
" use ATrait;\n"
"}\n"
"\n"
"class UsingIndirect {\n"
" use Indirect;\n"
"}\n"
"\n"
"$r = SomeClass::get_class_name();\n"
"var_dump($r);\n"
"\n"
"$o = new SomeClass();\n"
"$r = $o->get_class_name_obj();\n"
"var_dump($r);\n"
"\n"
"$r = UsingIndirect::get_class_name();\n"
"var_dump($r);\n"
"\n"
"$o = new UsingIndirect();\n"
"$r = $o->get_class_name_obj();\n"
"var_dump($r);\n"
"\n"
"\n"
"?>\n"
,
"string(9) \"SomeClass\"\n"
"string(9) \"SomeClass\"\n"
"string(13) \"UsingIndirect\"\n"
"string(13) \"UsingIndirect\"\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait Hello {\n"
" public function sayHelloWorld() {\n"
" echo 'Hello'.$this->getWorld();\n"
" }\n"
" abstract public function getWorld();\n"
" }\n"
"\n"
"class MyHelloWorld {\n"
" private $world;\n"
" use Hello;\n"
" public function getWorld() {\n"
" return $this->world;\n"
" }\n"
" public function setWorld($val) {\n"
" $this->world = $val;\n"
" }\n"
"}\n"
"\n"
"$o = new MyHelloWorld();\n"
"$o->setWorld(' World!');\n"
"$o->sayHelloWorld();\n"
"\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait Hello {\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
"\n"
"trait World {\n"
" public function sayWorld() {\n"
" echo 'World';\n"
" }\n"
"}\n"
" \n"
"class MyHelloWorld {\n"
" use Hello, World;\n"
" public function sayExclamationMark() {\n"
" echo '!';\n"
" }\n"
"}\n"
" \n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"$o->sayWorld();\n"
"$o->sayExclamationMark();\n"
"?>\n\n"
,
"Hello World!\n"
);
MVCRO(
"<?php\n"
"\n"
" trait TestTrait {\n"
" public static function test() {\n"
" return static::$test;\n"
" }\n"
" }\n"
"\n"
" class A {\n"
" use TestTrait;\n"
" protected static $test = \"Test A\";\n"
" }\n"
"\n"
" class B extends A {\n"
" protected static $test = \"Test B\";\n"
" }\n"
"\n"
" echo B::test();\n"
"\n"
"?>\n\n"
,
"Test B\n"
);
MVCRO(
"<?php\n"
"/* Prototype : proto bool trait_exists(string traitname [, bool autoload])\n"
" * Description: Checks if the trait exists \n"
" * Source code: Zend/zend_builtin_functions.c\n"
" * Alias to functions: \n"
" */\n"
"\n"
"echo \"*** Testing trait_exists() : basic functionality ***\\n\";\n"
"\n"
"function __autoload($traitName) {\n"
" echo \"In __autoload($traitName)\\n\";\n"
"}\n"
"\n"
"trait MyTrait {}\n"
"\n"
"echo \"Calling trait_exists() on non-existent trait with autoload explicitly enabled:\\n\";\n"
"var_dump( trait_exists('C', true) );\n"
"echo \"\\nCalling trait_exists() on existing trait with autoload explicitly enabled:\\n\";\n"
"var_dump( trait_exists('MyTrait', true) );\n"
"\n"
"echo \"\\nCalling trait_exists() on non-existent trait with autoload explicitly enabled:\\n\";\n"
"var_dump( trait_exists('D', false) );\n"
"echo \"\\nCalling trait_exists() on existing trait with autoload explicitly disabled:\\n\";\n"
"var_dump( trait_exists('MyTrait', false) );\n"
"\n"
"echo \"\\nCalling trait_exists() on non-existent trait with autoload unspecified:\\n\";\n"
"var_dump( trait_exists('E') );\n"
"echo \"\\nCalling trait_exists() on existing trait with autoload unspecified:\\n\";\n"
"var_dump( trait_exists('MyTrait') );\n"
"\n"
"echo \"Done\";\n"
"?>\n\n"
,
"*** Testing trait_exists() : basic functionality ***\n"
"Calling trait_exists() on non-existent trait with autoload explicitly enabled:\n"
"In __autoload(C)\n"
"bool(false)\n"
"\n"
"Calling trait_exists() on existing trait with autoload explicitly enabled:\n"
"bool(true)\n"
"\n"
"Calling trait_exists() on non-existent trait with autoload explicitly enabled:\n"
"bool(false)\n"
"\n"
"Calling trait_exists() on existing trait with autoload explicitly disabled:\n"
"bool(true)\n"
"\n"
"Calling trait_exists() on non-existent trait with autoload unspecified:\n"
"In __autoload(E)\n"
"bool(false)\n"
"\n"
"Calling trait_exists() on existing trait with autoload unspecified:\n"
"bool(true)\n"
"Done\n"
);
MVCRO(
"<?php\n"
"\n"
"trait TestTrait {\n"
" public static function test() {\n"
" return __TRAIT__;\n"
" }\n"
"}\n"
"\n"
"class Direct {\n"
" use TestTrait;\n"
"}\n"
"\n"
"class IndirectInheritance extends Direct {\n"
" \n"
"}\n"
"\n"
"trait TestTraitIndirect {\n"
" use TestTrait;\n"
"}\n"
"\n"
"class Indirect {\n"
" use TestTraitIndirect;\n"
"}\n"
"\n"
"echo Direct::test().\"\\n\";\n"
"echo IndirectInheritance::test().\"\\n\";\n"
"echo Indirect::test().\"\\n\";\n"
"\n"
"?>\n"
,
"TestTrait\n"
"TestTrait\n"
"TestTrait\n"
);
MVCRO(
"<?php\n"
"\n"
" trait TestTrait {\n"
" public static function test() {\n"
" return 'Forwarded '.forward_static_call(array('A', 'test'));\n"
" }\n"
" }\n"
"\n"
" class A {\n"
" public static function test() {\n"
" return \"Test A\";\n"
" }\n"
" }\n"
"\n"
" class B extends A {\n"
" use TestTrait;\n"
" }\n"
"\n"
" echo B::test();\n"
"\n"
"?>\n\n"
,
"Forwarded Test A\n"
);
MVCRO(
"<?php\n"
"\n"
"trait foo {\n"
" public function abc() {\n"
" }\n"
"}\n"
"\n"
"interface baz {\n"
" public function abc();\n"
"}\n"
"\n"
"class bar implements baz {\n"
" use foo;\n"
"\n"
"}\n"
"\n"
"new bar;\n"
"print \"OK\\n\";\n"
"\n"
"?>\n"
,
"OK\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait Counter {\n"
" public function inc() {\n"
" static $c = 0;\n"
" $c = $c + 1;\n"
" echo \"$c\\n\";\n"
" }\n"
"}\n"
"\n"
"\n"
"class C1 {\n"
" use Counter;\n"
"}\n"
"\n"
"class C2 {\n"
" use Counter;\n"
"}\n"
"\n"
"$o = new C1();\n"
"$o->inc();\n"
"$o->inc();\n"
"\n"
"$p = new C2();\n"
"$p->inc();\n"
"$p->inc();\n"
"\n"
"?>\n"
,
"1\n"
"2\n"
"1\n"
"2\n"
);
MVCRO(
"<?php\n"
"\n"
"trait foo {\n"
" public function serialize() {\n"
" return 'foobar';\n"
" }\n"
" public function unserialize($x) {\n"
" var_dump($x);\n"
" }\n"
"}\n"
"\n"
"class bar implements Serializable {\n"
" use foo;\n"
"}\n"
"\n"
"var_dump($o = serialize(new bar));\n"
"var_dump(unserialize($o));\n"
"\n"
"?>\n"
,
"string(20) \"C:3:\"bar\":6:{foobar}\"\n"
"string(6) \"foobar\"\n"
"object(bar)#1 (0) {\n"
"}\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait A {\n"
" public function smallTalk() {\n"
" echo 'a';\n"
" }\n"
" public function bigTalk() {\n"
" echo 'A';\n"
" }\n"
"}\n"
"\n"
"trait B {\n"
" public function smallTalk() {\n"
" echo 'b';\n"
" }\n"
" public function bigTalk() {\n"
" echo 'B';\n"
" }\n"
"}\n"
"\n"
"class Talker {\n"
" use A, B {\n"
" B::smallTalk insteadof A; \n"
" A::bigTalk insteadof B;\n"
" B::bigTalk as talk;\n"
" }\n"
"}\n"
"\n"
"$t = new Talker;\n"
"$t->smallTalk();\n"
"$t->bigTalk();\n"
"$t->talk();\n"
"\n"
"?>\n\n"
,
"bAB\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait HelloWorld {\n"
" public function sayHello() {\n"
" echo 'Hello World!';\n"
" }\n"
"}\n"
"\n"
"trait HelloWorld2 {\n"
" public function sayHello() {\n"
" echo 'Hello World2!';\n"
" }\n"
"}\n"
"\n"
"\n"
"class TheWorldIsNotEnough {\n"
" use HelloWorld;\n"
" use HelloWorld2;\n"
" public function sayHello() {\n"
" echo 'Hello Universe!';\n"
" }\n"
"}\n"
"\n"
"$o = new TheWorldIsNotEnough();\n"
"$o->sayHello(); // echos Hello Universe!\n"
"?>\n\n"
,
"Hello Universe!\n"
);
MVCRO(
"<?php\n"
"\n"
"class a { }\n"
"interface b { }\n"
"trait c { }\n"
"abstract class d { }\n"
"final class e { }\n"
"\n"
"var_dump(get_declared_traits());\n"
"\n"
"?>\n"
,
"array(1) {\n"
" [0]=>\n"
" string(1) \"c\"\n"
"}\n"
);
MVCRO(
"<?php\n"
"\n"
"abstract class foo {\n"
"}\n"
"\n"
"trait bar {\n"
" \n"
"}\n"
"\n"
"final class baz {\n"
" \n"
"}\n"
"\n"
"$x = new ReflectionClass('foo');\n"
"var_dump($x->isTrait());\n"
"\n"
"$x = new ReflectionClass('bar');\n"
"var_dump($x->isTrait());\n"
"\n"
"$x = new ReflectionClass('baz');\n"
"var_dump($x->isTrait());\n"
"\n"
"?>\n"
,
"bool(false)\n"
"bool(true)\n"
"bool(false)\n"
);
MVCRO(
"<?php\n"
"\n"
"trait A {\n"
" protected static function foo() { echo \"abc\\n\"; }\n"
" private static function bar() { echo \"def\\n\"; }\n"
"}\n"
"\n"
"\n"
"class B {\n"
" use A {\n"
" A::foo as public;\n"
" A::bar as public baz;\n"
" }\n"
"}\n"
"\n"
"B::foo();\n"
"B::baz();\n"
"\n"
"\n"
"?>\n"
,
"abc\n"
"def\n"
);
MVCRO(
"<?php\n"
"/* Prototype : array class_uses(mixed what [, bool autoload ])\n"
" * Description: Return all traits used by a class\n"
" * Source code: ext/spl/php_spl.c\n"
" * Alias to functions: \n"
" */\n"
"\n"
"echo \"*** Testing class_uses() : basic ***\\n\";\n"
"\n"
"\n"
"trait foo { }\n"
"class bar { use foo; }\n"
"\n"
"var_dump(class_uses(new bar));\n"
"var_dump(class_uses('bar'));\n"
"\n"
"\n"
"?>\n"
"===DONE===\n"
,
"*** Testing class_uses() : basic ***\n"
"array(1) {\n"
" [\"foo\"]=>\n"
" string(3) \"foo\"\n"
"}\n"
"array(1) {\n"
" [\"foo\"]=>\n"
" string(3) \"foo\"\n"
"}\n"
"===DONE===\n"
);
MVCRO(
"<?php\n"
"\n"
" trait TestTrait {\n"
" public static function __callStatic($name, $arguments) {\n"
" return $name;\n"
" }\n"
" }\n"
"\n"
" class A {\n"
" use TestTrait;\n"
" }\n"
"\n"
" echo A::Test();\n"
"\n"
"?>\n\n"
,
"Test\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"class Base {\n"
" public function sayHello() {\n"
" echo 'Hello ';\n"
" }\n"
"}\n"
" \n"
"trait SayWorld {\n"
" public function sayHello() {\n"
" echo 'World!';\n"
" }\n"
"}\n"
"\n"
"class MyHelloWorld extends Base {\n"
" use SayWorld;\n"
"}\n"
"\n"
"$o = new MyHelloWorld();\n"
"$o->sayHello();\n"
"?>\n\n"
,
"World!\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait A {\n"
" public function foo() {\n"
" echo 'a';\n"
" }\n"
"}\n"
"\n"
"trait B {\n"
" public function foo() {\n"
" echo 'b';\n"
" }\n"
"}\n"
"\n"
"trait C {\n"
" public function foo() {\n"
" echo 'c';\n"
" }\n"
"}\n"
"\n"
"class Foo {\n"
" use C, A, B {\n"
" B::foo insteadof A, C; \n"
" }\n"
"}\n"
"\n"
"$t = new Foo;\n"
"$t->foo();\n"
"\n"
"?>\n\n"
,
"b\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL);\n"
"\n"
"trait T1 {\n"
" public function getText() {\n"
" return $this->text;\n"
" }\n"
"}\n"
"\n"
"trait T2 {\n"
" public function setTextT2($val) {\n"
" $this->text = $val;\n"
" }\n"
"}\n"
"\n"
"class TraitsTest {\n"
" use T1;\n"
" use T2;\n"
" private $text = 'test';\n"
" public function setText($val) {\n"
" $this->text = $val;\n"
" }\n"
"}\n"
"\n"
"$o = new TraitsTest();\n"
"var_dump($o->getText());\n"
"\n"
"$o->setText('foo');\n"
"\n"
"var_dump($o->getText());\n"
"\n"
"$o->setText('bar');\n"
"\n"
"var_dump($o->getText());\n"
"?>\n"
,
"string(4) \"test\"\n"
"string(3) \"foo\"\n"
"string(3) \"bar\"\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" static function foo() {\n"
" echo \"I'm in class \" . get_class() . \"\\n\";"
" }\n"
"}\n"
"class C { use T; }\n"
"class D extends C {}\n"
"trait T2 { use T; }\n"
"trait T3 { use T2; }\n"
"$x = new D();\n"
"$x->foo();\n"
"C::foo();\n"
"D::foo();\n"
"T::foo();\n"
"T2::foo();\n"
"T3::foo();\n"
"?>"
,
"I'm in class C\n"
"I'm in class C\n"
"I'm in class C\n"
"I'm in class T\n"
"I'm in class T2\n"
"I'm in class T3\n"
);
MVCRO(
"<?php\n"
"class Base {}\n"
"trait T {\n"
" public function sayClass() {\n"
" echo get_class() . \"\\n\";\n"
" }\n"
" public function sayParent() {\n"
" echo get_parent_class();\n"
" }\n"
"}\n"
"class Cls extends Base { use T; }\n"
"$o = new Cls();\n"
"$o->sayClass(); // echo Cls\n"
"$o->sayParent(); // echos Base\n"
"?>\n"
"\n"
,
"Cls\n"
"Base\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" public static $x=1;\n"
" public function printX() { var_dump(self::$x); }\n"
"}\n"
"class C1 { use T; }\n"
"class C2 { use T; }\n"
"$o1 = new C1;\n"
"$o2 = new C2;\n"
"var_dump(T::$x);\n"
"var_dump(C1::$x);\n"
"var_dump(C2::$x);\n"
"$o1->printX();\n"
"$o2->printX();\n"
"T::$x++;\n"
"var_dump(T::$x);\n"
"var_dump(C1::$x);\n"
"var_dump(C2::$x);\n"
"$o1->printX();\n"
"$o2->printX();\n"
"C1::$x++;\n"
"var_dump(T::$x);\n"
"var_dump(C1::$x);\n"
"var_dump(C2::$x);\n"
"$o1->printX();\n"
"$o2->printX();\n"
"C2::$x++;\n"
"var_dump(T::$x);\n"
"var_dump(C1::$x);\n"
"var_dump(C2::$x);\n"
"$o1->printX();\n"
"$o2->printX();\n"
"$o1->x++;\n"
"var_dump(T::$x);\n"
"var_dump(C1::$x);\n"
"var_dump(C2::$x);\n"
"$o1->printX();\n"
"$o2->printX();\n"
,
"int(1)\n"
"int(1)\n"
"int(1)\n"
"int(1)\n"
"int(1)\n"
"int(2)\n"
"int(1)\n"
"int(1)\n"
"int(1)\n"
"int(1)\n"
"int(2)\n"
"int(2)\n"
"int(1)\n"
"int(2)\n"
"int(1)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
);
MVCRO(
"<?php\n"
"trait MyTrait {\n"
" public static function callNew() {\n"
" new self(\"called via SELF\");\n"
" new parent(\"called via PARENT\");\n"
" }\n"
"}\n"
"class MyBaseClass {\n"
" public function __construct($arg) {\n"
" echo __class__ . \": \" . $arg . \"\\n\";\n"
" }\n"
"}\n"
"class MyDerivedClass extends MyBaseClass {\n"
" use MyTrait;\n"
" public function __construct($arg) {\n"
" echo __class__ . \": \" . $arg . \"\\n\";\n"
" }\n"
"}\n"
"$o= MyDerivedClass::callNew();\n"
,
"MyDerivedClass: called via SELF\n"
"MyBaseClass: called via PARENT\n"
);
MVCRO(
"<?php\n"
"trait my_trait {\n"
" abstract function foo();\n"
" public function bar() {\n"
" echo \"I am bar\\n\";\n"
" self::foo();\n"
" }\n"
"}\n"
"class my_class {\n"
" use my_trait;\n"
" private function foo() {\n"
" echo \"I am foo\\n\";\n"
" }\n"
"}\n"
"$o = new my_class;\n"
"$o->bar();\n"
,
"I am bar\n"
"I am foo\n"
);
MVCRO(
"<?php\n"
"trait T1 {\n"
" public function inc($who) {\n"
" static $x=0;\n"
" $x++;\n"
" echo $who . \" (\" . __class__ . \"): \" . $x . \"\\n\";\n"
" }\n"
"}\n"
"class B { use T1; }\n"
"class C { use T1; }\n"
"class D extends C {}\n"
"$c1 = new C;\n"
"$c2 = new C;\n"
"$d1 = new D;\n"
"$b1 = new B;\n"
"$c1->inc(\"c1\");\n"
"$c2->inc(\"c2\");\n"
"$d1->inc(\"d1\");\n"
"$b1->inc(\"b1\");\n"
"$b1->inc(\"b1\");\n"
"$c2->inc(\"c2\");\n"
"$d1->inc(\"d1\");\n"
"$c1->inc(\"c1\");\n"
,
"c1 (C): 1\n"
"c2 (C): 2\n"
"d1 (C): 1\n"
"b1 (B): 1\n"
"b1 (B): 2\n"
"c2 (C): 3\n"
"d1 (C): 2\n"
"c1 (C): 4\n"
);
MVCRO(
"<?php\n"
"trait T {\n"
" abstract public function bar();\n"
" public function foo() {\n"
" $this->bar();\n"
" }\n"
"}\n"
"class B {\n"
" public function bar() {\n"
" echo \"I'm bar\\n\";\n"
" }\n"
"}\n"
"class C extends B {\n"
" use T;\n"
"}\n"
"$o = new C;\n"
"$o->foo();\n"
"\n"
,
"I'm bar\n"
);
MVCRO(
"<?php\n"
"\n"
"trait T1 {\n"
" abstract function bar();\n"
" public function foo() {\n"
" $this->bar();\n"
" }\n"
"}\n"
"\n"
"trait T2 {\n"
" public function bar() {\n"
" echo \"Hello from bar()\\n\";\n"
" }\n"
"}\n"
"\n"
"class C {\n"
" use T1, T2;\n"
"}\n"
"\n"
"$o = new C;\n"
"$o->foo();\n"
"\n"
"\n"
,
"Hello from bar()\n"
);
MVCRO(
"<?php\n"
"error_reporting(E_ALL | E_STRICT);"
"trait T {"
" protected function f() {"
" return 1;"
" }"
" private function p() {"
" return 2;"
" }"
" function g() {"
" return $this->f();"
" }"
" function h() {"
" return $this->p();"
" }"
"}"
"class C {"
" use T;"
"}"
"$c = new C;"
"echo $c->g();"
"echo $c->h();",
"12");
MVCRO(
"<?php\n"
"trait A {"
" function test() {"
" static $x;"
" return ++$x;"
" }"
" function test8($a, $b, $c, $d, $e, $f, $g, $h) {"
" static $x;"
" return ++$x;"
" }"
"}"
"trait X {"
" use A;"
"}"
"trait Y {"
" use A;"
"}"
"class T {"
" use X, Y {"
" X::test insteadof Y;"
" X::test as test1;"
" Y::test as test2;"
" X::test8 insteadof Y;"
" X::test8 as test81;"
" Y::test8 as test82;"
" }"
"}"
"var_dump(T::test());"
"var_dump(T::test1());"
"var_dump(T::test2());"
"var_dump(call_user_func(\"T::test\"));"
"var_dump(call_user_func(\"T::test1\"));"
"var_dump(call_user_func(\"T::test2\"));"
"$obj = new T;"
"var_dump($obj->test());"
"var_dump($obj->test1());"
"var_dump($obj->test2());"
"var_dump(call_user_func(array($obj, \"test\")));"
"var_dump(call_user_func(array($obj, \"test1\")));"
"var_dump(call_user_func(array($obj, \"test2\")));"
"var_dump(T::test8(1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump(T::test81(1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump(T::test82(1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump(call_user_func(\"T::test8\", 1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump(call_user_func(\"T::test81\", 1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump(call_user_func(\"T::test82\", 1, 2, 3, 4, 5, 6, 7, 8));"
"$obj = new T;"
"var_dump($obj->test8(1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump($obj->test81(1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump($obj->test82(1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump(call_user_func(array($obj, \"test8\"), "
"1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump(call_user_func(array($obj, \"test81\"), "
"1, 2, 3, 4, 5, 6, 7, 8));"
"var_dump(call_user_func(array($obj, \"test82\"), "
"1, 2, 3, 4, 5, 6, 7, 8));",
"int(1)\n"
"int(1)\n"
"int(1)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(3)\n"
"int(3)\n"
"int(3)\n"
"int(4)\n"
"int(4)\n"
"int(4)\n"
"int(1)\n"
"int(1)\n"
"int(1)\n"
"int(2)\n"
"int(2)\n"
"int(2)\n"
"int(3)\n"
"int(3)\n"
"int(3)\n"
"int(4)\n"
"int(4)\n"
"int(4)\n"
);
MVCRO("<?php "
"define('MUST_PREPARE', 0);"
"function must_prepare($x) {"
" if ($x == MUST_PREPARE) {"
" $x = 2;"
" }"
" return $x;"
"}"
"trait EntWithViewerComments {"
" public $entCanComment = 1;"
" public function canViewerComment() {"
" var_dump($this->entCanComment);"
" var_dump(must_prepare($this->entCanComment));"
" }"
"}"
"class EntShare {"
" use EntWithViewerComments;"
"}"
"$obj1 = new EntShare;"
"$obj1->canViewerComment();"
,
"int(1)\nint(1)\n");
MVCROF(
"<?php\n"
"trait T {"
" private $x = 'init from T';"
" function useT() { $this->x = 'set from trait'; } }"
""
"class A {"
" function useA() { $this->x = 'set from A'; }"
"}"
"class B extends A {"
" use T;"
" function useB() { $this->x = 'set from B'; }"
"}"
"class C extends B {"
" function useC() { $this->x = 'set from C'; }"
"}"
"class D extends C {"
" function useD() { $this->x = 'set from D'; }"
"}"
"$x = new D(); echo serialize($x), \"\\n\";"
"$x = new D(); $x->useT(); echo serialize($x), \"\\n\";"
"$x = new D(); $x->useA(); echo serialize($x), \"\\n\";"
"$x = new D(); $x->useB(); echo serialize($x), \"\\n\";"
"$x = new D(); $x->useC(); echo serialize($x), \"\\n\";"
"$x = new D(); $x->useD(); echo serialize($x), \"\\n\";",
"test/output/trait1.out");
MVCRO("<?php\n"
"trait T1 { public $xT1 = 'xT1'; }\n"
"trait T2 { public $xT2 = 'xT2'; }\n"
"trait T3 { public $xT3 = 'xT3'; }\n"
"class B {\n"
" use T1;\n"
" public $xB = 'xB';\n"
" use T2;\n"
"}\n"
"class A extends B {\n"
" public $xA = 'xA';\n"
" use T3;\n"
"}\n"
"$x = new A();\n"
"$s = serialize($x);\n"
"echo $s . \"\\n\";\n"
"$y = unserialize($s);\n"
"var_dump($y->xT1);\n"
"var_dump($y->xT2);\n"
"var_dump($y->xT3);\n"
"var_dump($y->xA);\n"
"var_dump($y->xB);\n"
,
"O:1:\"A\":5:{s:2:\"xA\";s:2:\"xA\";s:3:\"xT3\";s:3:\"xT3\";"
"s:2:\"xB\";s:2:\"xB\";s:3:\"xT1\";s:3:\"xT1\";s:3:\"xT2\";"
"s:3:\"xT2\";}\n"
"string(3) \"xT1\"\n"
"string(3) \"xT2\"\n"
"string(3) \"xT3\"\n"
"string(2) \"xA\"\n"
"string(2) \"xB\"\n"
);
MVCRO(
"<?php\n"
"trait T { private $x = 0;}"
"class X { use T; function x() { return ++$this->x; } }"
"class Y extends X { use T; function y() { return ++$this->x; } }"
"class Z extends Y { function z() { return ++$this->x; } }"
"$a = new Z();"
"echo join(\" \", array($a->x(), $a->x(), $a->y(), $a->y(), "
"$a->z(), $a->z())), \"\\n\";",
"1 2 1 2 2 3\n");
MVCRO("<?php\n"
"trait T {\n"
" public function goo() {\n"
" return get_called_class();\n"
" }\n"
" public function foo() {\n"
" return self::goo();\n"
" }\n"
"}\n"
"class A { use T; }\n"
"var_dump(A::goo());\n"
"var_dump(A::foo());\n"
,
"string(1) \"A\"\n"
"string(1) \"A\"\n"
);
MVCRO("<?php\n"
"trait TraitFoo {"
" public function getStringThroughProtectedMethod() {"
" return $this->protectedMethod();"
" }"
" protected function protectedMethod() {"
" return 'fallback protected method';"
" }"
" public function getStringThroughPrivateMethod() {"
" return $this->privateMethod();"
" }"
" private function privateMethod() {"
" return 'fallback private method';"
" }"
"}"
""
"class A {"
" use TraitFoo;"
" protected function protectedMethod() {"
" return 'in a protectedMethod';"
" }"
" private function privateMethod() {"
" return 'in a privateMethod';"
" }"
"}"
"$a = new A();"
"echo $a->getStringThroughProtectedMethod().\"\\n\";"
"echo $a->getStringThroughPrivateMethod().\"\\n\";",
"in a protectedMethod\n"
"in a privateMethod\n");
{ // begin trait tests requiring EnableHipHopSyntax
HipHopSyntax w(this);
MVCRO("<?php\n"
"trait T {\n"
" function fruit() {\n"
" yield 'apple';\n"
" yield 'banana';\n"
" }\n"
"}\n"
"class C1 { use T; }\n"
"class C2 { use T; }\n"
"$o = new C1;\n"
"foreach ($o->fruit() as $fruit) {\n"
" var_dump($fruit);\n"
"}\n"
,
"string(5) \"apple\"\n"
"string(6) \"banana\"\n"
);
MVCRO("<?php\n"
"trait T1 {\n"
" function fruit() {\n"
" yield 'apple';\n"
" yield 'banana';\n"
" }\n"
"}\n"
"trait T2 {\n"
" function fruit() {\n"
" yield 'pear';\n"
" yield 'grape';\n"
" }\n"
"}\n"
"class C1 {\n"
" use T1, T2 {\n"
" T1::fruit insteadof T2;\n"
" T2::fruit as fruit2;\n"
" }\n"
"}\n"
"$o = new C1;\n"
"foreach ($o->fruit() as $fruit) {\n"
" var_dump($fruit);\n"
"}\n"
"foreach ($o->fruit2() as $fruit) {\n"
" var_dump($fruit);\n"
"}\n"
,
"string(5) \"apple\"\n"
"string(6) \"banana\"\n"
"string(4) \"pear\"\n"
"string(5) \"grape\"\n"
);
MVCRO("<?php trait T { function fruit() { yield 'apple'; yield 'banana';} }"
"class F { use T; }\n"
"foreach (F::fruit() as $fruit) { var_dump($fruit);} ",
"string(5) \"apple\"\n"
"string(6) \"banana\"\n"
);
MVCRO("<?php\n"
"trait T {\n"
" public function doIt() {\n"
" throw new Exception('foobar');\n"
" }\n"
"}\n"
"class X { use T; }\n"
"function f($obj) {\n"
" $res = null;\n"
" try {\n"
" $res = $obj->doIt();\n"
" } catch (Exception $e) {\n"
" $res = $e->getMessage();\n"
" }\n"
" yield $res;\n"
"}\n"
"$x = new X;\n"
"foreach (f($x) as $i) { var_dump($i); }\n"
,
"string(6) \"foobar\"\n"
);
MVCRO("<?php\n"
"trait T {\n"
" function foo($t) {\n"
" $$t = 5;\n"
" yield $this;\n"
" }\n"
"}\n"
"class X { use T; }\n"
"$x = new X;\n"
"foreach ($x->foo('this') as $v) { var_dump($v); }\n"
,
"int(5)\n"
);
MVCRO("<?php\n"
"function f($x) {\n"
" yield $x;\n"
"}\n"
"$c = f(32);\n"
"var_dump($c->getOrigFuncName());\n"
"trait T {\n"
" function f($x) { yield get_called_class(); }\n"
"}\n"
"class X { use T; }\n"
"$x = new X;\n"
"$c = $x->f(32);\n"
"var_dump($c->getOrigFuncName());\n"
"$fcn = function ($x) { yield $x; };\n"
"$c = $fcn(32);\n"
"var_dump($c->getOrigFuncName());\n"
,
"string(1) \"f\"\n"
"string(4) \"X::f\"\n"
"string(9) \"{closure}\"\n"
);
MVCRO("<?php "
"trait T {"
" public static function gen() {"
" static $x;"
" yield ++$x;"
" yield 2;"
" yield ++$x;"
" }"
"}"
"class X { use T; }\n"
"class Y extends X {}"
"$g = X::gen();"
"foreach ($g as $i) var_dump($i);"
,
"int(1)\n"
"int(2)\n"
"int(2)\n"
);
MVCRO("<?php\n"
"trait T {\n"
" function info() {\n"
" yield __METHOD__;\n"
" yield __CLASS__;\n"
" yield __TRAIT__;\n"
" }\n"
"}\n"
"class C1 { use T; }\n"
"class C2 { use T; }\n"
"$o1 = new C1;\n"
"foreach ($o1->info() as $info) {\n"
" var_dump($info);\n"
"}\n"
"$o2 = new C2;\n"
"foreach ($o2->info() as $info) {\n"
" var_dump($info);\n"
"}\n"
,
"string(7) \"T::info\"\n"
"string(2) \"C1\"\n"
"string(1) \"T\"\n"
"string(7) \"T::info\"\n"
"string(2) \"C2\"\n"
"string(1) \"T\"\n"
);
MVCRO("<?php\n"
"trait T {\n"
" function f() {\n"
" $a = function() { yield 1; yield 2; };\n"
" return $a;\n"
" }\n"
"}\n"
"class A { use T; }\n"
"$a = new A;\n"
"$f = $a->f();\n"
"foreach ($f() as $v) { var_dump($v); }\n"
,
"int(1)\n"
"int(2)\n"
);
MVCRO("<?php\n"
"trait T {"
" public function foo() {"
" $this->bar(function() {yield 1; yield 2; yield 3;});"
" }"
" public function bar(Closure $c) {"
" $a = $c();"
" foreach ($a as $b) {"
" echo $b.\"\\n\";"
" }"
" }"
"}"
"class A { use T; }"
"$a = new A();"
"$a->foo();"
,
"1\n"
"2\n"
"3\n"
);
MVCRO("<?php\n"
"trait U {\n"
" public function test() {\n"
" echo __CLASS__ . \"\\n\";\n"
" $this->foo();\n"
" yield null;\n"
" }\n"
"}\n"
"class D {\n"
" use U;\n"
" protected function foo() {\n"
" echo \"U::foo\\n\";\n"
" }\n"
"}\n"
"$obj = new D;\n"
"$x = $obj->test();\n"
"foreach ($x as $v) {}\n"
,
"D\n"
"U::foo\n"
);
MVCRO("<?php"
"trait baz {"
" public function bar() { yield 1; }"
"}"
"class foo {"
" use baz;"
" public function bar() {}"
"}",
"");
OptionSetter w1(this, OptionSetter::Env, "ENABLE_INTERCEPT=1");
OptionSetter w2(this, OptionSetter::RunTime,
"-vEval.JitEnableRenameFunction=true");
MVCRO("<?php\n"
"trait T {\n"
" public function m() { echo \"original\n\"; }\n"
"}\n"
"class A { use T; }\n"
"class B { use T; }\n"
"$a1 = new A;\n"
"$a1->m();\n"
"fb_intercept(\"A::m\", function() { echo \"new\n\"; });\n"
"$a2 = new A;\n"
"$a2->m();\n"
"$b1 = new B;\n"
"$b1->m();\n"
"T::m();\n"
,
"original\n"
"new\n"
"original\n"
"original\n");
MVCRO("<?php\n"
"trait T {\n"
" public function m() { echo \"original\n\"; }\n"
"}\n"
"class A { use T; }\n"
"class B { use T; }\n"
"T::m();\n"
"$a1 = new A;\n"
"$a1->m();\n"
"fb_intercept(\"T::m\", function() { echo \"new\n\"; });\n"
"$a2 = new A;\n"
"$a2->m();\n"
"$b1 = new B;\n"
"$b1->m();\n"
"T::m();\n"
,
"original\n"
"original\n"
"original\n"
"original\n"
"new\n");
MVCRONW("<?php "
"trait T1 { function foo() { yield 1; } }"
"class C { use T1 { T1::foo as static; } }",
"");
MVCRO("<?php"
"trait T1 { function foo() { yield 1; } }"
"trait T2 {"
" use T1 {"
" foo as bar;"
" }"
" function foo() { return bar(); }"
"}"
"class C { use T2; }"
"foreach (C::bar() as $x) var_dump($x);",
"int(1)\n");
} // end trait tests with EnableHipHopSyntax
MVCRO("<?php\n"
"trait Too {\n"
" function bar() {\n"
" $abc = 123;\n"
" $a = function ($abc) use ($abc) {\n"
" var_dump($abc);\n"
" };\n"
" return $a;\n"
" }\n"
"}\n"
"class Foo { use Too; }\n"
"$a = Foo::bar();\n"
"$a(456);\n"
,
"int(123)\n"
);
MVCRO("<?php\n"
"trait Too {\n"
" function bar() {\n"
" $abc = 123;\n"
" $a = function ($abc) use ($abc, $abc) {\n"
" var_dump($abc);\n"
" };\n"
" return $a;\n"
" }\n"
"}\n"
"class Foo { use Too; }\n"
"$a = Foo::bar();\n"
"$a(456);\n"
,
"int(123)\n"
);
MVCRO("<?php\n"
"trait Too {\n"
" function bar() {\n"
" $abc = 123;\n"
" $a = function ($abc) use (&$abc, &$abc) {\n"
" var_dump($abc);\n"
" };\n"
" return $a;\n"
" }\n"
"}\n"
"class Foo { use Too; }\n"
"$a = Foo::bar();\n"
"$a(456);\n"
,
"int(123)\n");
MVCRO("<?php\n"
"trait Too {\n"
" function bar() {\n"
" $abc = 123;\n"
" $a = function ($x) use ($abc) {\n"
" $n = func_num_args();\n"
" $args = func_get_args();\n"
" var_dump($n, $args);\n"
" };\n"
" return $a;\n"
" }\n"
"\n"
" function baz($obj) {\n"
" $abc = 456;\n"
" $obj(789);\n"
" }\n"
"}\n"
"class Foo { use Too; }\n"
"$a = Foo::bar();\n"
"Foo::baz($a);\n"
,
"int(1)\n"
"array(1) {\n"
" [0]=>\n"
" int(789)\n"
"}\n"
);
MVCRO("<?php\n"
"trait Too {\n"
" function bar() {\n"
" $a = function () { var_dump(__CLASS__, __FUNCTION__);};\n"
" $a();\n"
" }\n"
"}\n"
"class Foo { use Too; }\n"
"Foo::bar();\n"
,
"string(0) \"\"\n"
"string(9) \"{closure}\"\n"
);
MVCRO("<?php\n"
"trait T {"
" public function foo() {"
" $values = array(1, 2, 3);"
" $values = array_map(function($p) use ($this) {"
" return $this->goo($p);"
" }, $values);"
" var_dump($values);"
" }"
" public function bar() { return $this; }"
" public function goo($p) { return $p; }"
"}"
"class A { use T;}\n"
"$obj = new A;"
"var_dump($obj->bar());"
"$obj->foo();",
"object(A)#1 (0) {\n"
"}\n"
"array(3) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" int(2)\n"
" [2]=>\n"
" int(3)\n"
"}\n");
MVCRO("<?php\n"
"trait Too {\n"
" function gen() {\n"
" $abc = $this->input();\n"
" $a = function ($arg) use ($abc, $this) {\n"
" var_dump($arg);\n"
" var_dump($abc);\n"
" return $this->output();\n"
" };\n"
" return $a;\n"
" }\n"
" function input() { return 1; }\n"
" function output() { return 2; }\n"
"}\n"
"class Foo {\n"
" use Too;\n"
" function input() { return \"str1\"; }\n"
" function output() { return \"str2\"; }\n"
"}\n"
"class Goo {\n"
" use Too;\n"
" function input() { return false; }\n"
" function output() { return true; }\n"
"}\n"
"$of = new Foo;\n"
"$f = $of->gen();\n"
"var_dump($f(1000));\n"
"$og = new Goo;\n"
"$g = $og->gen();\n"
"var_dump($g(2000));\n"
,
"int(1000)\n"
"string(4) \"str1\"\n"
"string(4) \"str2\"\n"
"int(2000)\n"
"bool(false)\n"
"bool(true)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"trait t1 { public $x = INIT1; }\n"
"class c { use t1; }\n"
"$obj = new c;\n"
"var_dump($obj->x);\n"
,
"int(123)\n"
);
MVCRO("<?php\n"
"define('INIT1', \"1\");\n"
"define('INIT2', \"2\");\n"
"trait t1 { public $x = INIT1; }\n"
"trait t2 { public $y = INIT2; }\n"
"trait t { use t1, t2; }\n"
"class c { use t; }\n"
"$obj = new c;\n"
"var_dump($obj->x);\n"
"var_dump($obj->y);\n"
,
"string(1) \"1\"\n"
"string(1) \"2\"\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"trait t1 {}\n"
"class c { use t1; public $x = INIT1; }\n"
"$obj = new c;\n"
"var_dump($obj->x);\n"
,
"int(123)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"define('INIT2', 456);\n"
"trait t1 { public $x = INIT1; }\n"
"class c { use t1; public $y = INIT2; }\n"
"$obj = new c;\n"
"var_dump($obj->x);\n"
"var_dump($obj->y);\n"
,
"int(123)\n"
"int(456)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"trait t2 { public $x = INIT1; }\n"
"trait t1 { use t2; }\n"
"class c { use t1; }\n"
"$obj = new c;\n"
"var_dump($obj->x);\n"
,
"int(123)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"define('INIT2', 456);\n"
"trait t2 { public $y = INIT2; }\n"
"trait t1 { use t2; public $x = INIT1; }\n"
"class c { use t1; }\n"
"$obj = new c;\n"
"var_dump($obj->x);\n"
"var_dump($obj->y);\n"
,
"int(123)\n"
"int(456)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"trait t1 { static public $x = INIT1; }\n"
"class c { use t1; }\n"
"var_dump(c::$x);\n"
,
"int(123)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"trait t1 { static public $x = INIT1; }\n"
"class c { use t1; }\n"
"var_dump(c::$x++);\n"
"var_dump(t1::$x++);\n"
"var_dump(c::$x++);\n"
"var_dump(t1::$x++);\n"
,
"int(123)\n"
"int(123)\n"
"int(124)\n"
"int(124)\n"
);
MVCRO("<?php\n"
"define('INIT1', \"1\");\n"
"define('INIT2', \"2\");\n"
"trait t1 { static public $x = INIT1; }\n"
"trait t2 { static public $y = INIT2; }\n"
"trait t { use t1, t2; }\n"
"class c { use t; }\n"
"var_dump(c::$x);\n"
"var_dump(c::$y);\n"
,
"string(1) \"1\"\n"
"string(1) \"2\"\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"trait t1 {}\n"
"class c { use t1; static public $x = INIT1; }\n"
"var_dump(c::$x);\n"
,
"int(123)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"define('INIT2', 456);\n"
"trait t1 { static public $x = INIT1; }\n"
"class c { use t1; static public $y = INIT2; }\n"
"var_dump(c::$x);\n"
"var_dump(c::$y);\n"
,
"int(123)\n"
"int(456)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"trait t2 { static public $x = INIT1; }\n"
"trait t1 { use t2; }\n"
"class c { use t1; }\n"
"var_dump(c::$x);\n"
,
"int(123)\n"
);
MVCRO("<?php\n"
"define('INIT1', 123);\n"
"define('INIT2', 456);\n"
"trait t2 { static public $y = INIT2; }\n"
"trait t1 { use t2; static public $x = INIT1; }\n"
"class c { use t1; }\n"
"var_dump(c::$x);\n"
"var_dump(c::$y);\n"
,
"int(123)\n"
"int(456)\n"
);
MVCRO("<?\n"
"define('INIT1', 1000);\n"
"trait t { static public $x = INIT1; }\n"
"class c { use t; }\n"
"class d { use t; }\n"
"class e extends d {}\n"
"var_dump(t::$x++);\n"
"var_dump(c::$x++);\n"
"var_dump(d::$x++);\n"
"var_dump(e::$x++);\n"
"var_dump(t::$x++);\n"
"var_dump(c::$x++);\n"
"var_dump(d::$x++);\n"
"var_dump(e::$x++);\n"
,
"int(1000)\n"
"int(1000)\n"
"int(1000)\n"
"int(1001)\n"
"int(1001)\n"
"int(1001)\n"
"int(1002)\n"
"int(1003)\n"
);
MVCRO("<?php\n"
"trait TraitFoo {\n"
" public function testDoSomethingInTrait() {\n"
" return call_user_func(array($this, 'doSomethingInTrait'));\n"
" }\n"
" public function testDoSomethingPublicInTrait() {\n"
" return call_user_func(array($this, 'doSomethingPublicInTrait'));\n"
" }\n"
"}\n"
"class A {\n"
" use TraitFoo;\n"
" public function testDoSomething() {\n"
" return call_user_func(array($this, 'doSomething'));\n"
" }\n"
" public function __call($name, $args) {\n"
" echo \"**calling __call $name**\";\n"
" }\n"
" protected function doSomething() {\n"
" return 'doSomething';\n"
" }\n"
" protected function doSomethingInTrait() {\n"
" return 'doSomethingInTrait';\n"
" }\n"
" public function doSomethingPublicInTrait() {\n"
" return 'doSomethingPublicInTrait';\n"
" }\n"
"}\n"
"$a = new A();\n"
"echo $a->testDoSomething().\"\n\";\n"
"echo $a->testDoSomethingInTrait().\"\n\";\n"
"echo $a->testDoSomethingPublicInTrait().\"\n\";\n"
,
"doSomething\n"
"doSomethingInTrait\n"
"doSomethingPublicInTrait\n"
);
MVCRO("<?php\n"
"trait T {\n"
" public $x=1;\n"
" function dump_vars() {\n"
" var_dump(get_class_vars('C'));\n"
" }\n"
"}\n"
"class C {\n"
" private $y=2;\n"
" use T;\n"
"}\n"
"$o = new C;\n"
"$o->dump_vars();\n"
,
"array(2) {\n"
" [\"y\"]=>\n"
" int(2)\n"
" [\"x\"]=>\n"
" int(1)\n"
"}\n"
);
MVCRO("<?php\n"
"trait T {"
" public function foo() {"
" $this->bar();"
" }"
" private function bar() {"
" echo \"in bar...\\n\";"
" }"
"}"
"class B { use T; }"
"class C extends B { }"
"$obj = new C;"
"$obj->foo();",
"in bar...\n");
MVCRO("<?php\n"
"trait PrivateState {"
" private $foo = 2;"
""
" public function getFoo() {"
" return $this->foo;"
" }"
"}"
""
"class Base {"
" public static function create() {"
" return new static();"
" }"
"}"
""
"class UsePrivateState extends Base {"
" use PrivateState;"
"}"
""
"class DerivedUsePrivateState extends UsePrivateState {"
""
"}"
""
""
"$state = new DerivedUsePrivateState();"
"$method = new ReflectionMethod('DerivedUsePrivateState', 'getFoo');"
"echo $method->invoke($state).\"\\n\";"
"",
"2\n");
MVCRO("<?php\n"
"trait T {\n"
" public static function foo() {\n"
" $bt = debug_backtrace();\n"
" echo $bt[0]['function'] . \"\\n\";\n"
" }\n"
"}\n"
"class C {\n"
" use T {\n"
" T::foo as public bar1;\n"
" T::foo as public bar2;\n"
" }\n"
"}\n"
"C::bar1();\n"
"C::bar2();\n"
,
"bar1\n"
"bar2\n"
);
MVCRO("<?php\n"
"trait T {\n"
" abstract public function foo($x);\n"
"}\n"
"interface I {\n"
" public function foo($x);\n"
"}\n"
"abstract class B implements I {\n"
" use T;\n"
"}\n"
"class C extends B {\n"
" public function foo($x){ echo \"$x \\n\";}\n"
"}\n"
"$obj = new C;\n"
"$obj->foo(1);\n"
,
"1 \n"
);
MVCRO("<?php\n"
"trait T {"
" public function init() {"
" parent::init();"
" }"
"}"
"class A {"
" public function init() {"
" echo 'A::init';"
" }"
"}"
"class B extends A {"
" use T;"
"}"
"class C extends B {"
" public function init() {"
" parent::init();"
" }"
"}"
"$obj = new C;"
"$obj->init();",
"A::init");
MVCRO("<?php\n"
"trait T {\n"
" private function foo() {}\n"
"}\n"
"class C {\n"
" protected function foo() {}\n"
"}\n"
"class D extends C {\n"
" use T;\n"
" protected function foo() {}\n"
"}\n"
"class E extends C {\n"
" public static function test($obj) {\n"
" $obj->foo();\n"
" }\n"
"}\n"
"$d = new D;\n"
"E::test($d);\n"
"echo \"Done\\n\";\n"
,
"Done\n"
);
MVCRO("<?php\n"
"class C {\n"
" protected function foo() { echo \"C::foo\\n\"; }\n"
"}\n"
"trait T {\n"
" protected function foo() { echo \"T::foo\\n\"; }\n"
"}\n"
"class D extends C {\n"
" use T;\n"
"}\n"
"class E extends C {\n"
" public static function test($obj) {\n"
" $obj->foo();\n"
" }\n"
"}\n"
"$d = new D;\n"
"E::test($d);\n"
"echo \"Done\\n\";\n"
,
"T::foo\n"
"Done\n"
);
MVCRO("<?php\n"
"trait T {\n"
" private static function blarg() {\n"
" echo \"T::blarg\\n\";\n"
" }\n"
" private static function test() {\n"
" echo __CLASS__ . \"\\n\";\n"
" echo get_called_class() . \"\\n\";\n"
" self::blarg();\n"
" }\n"
" public static function doTest() {\n"
" self::test();\n"
" }\n"
"}\n"
"class C {\n"
" use T;\n"
"}\n"
"class D extends C {\n"
" protected static function test() {\n"
" echo \"D::test\\n\";\n"
" }\n"
" public static function doTest() {\n"
" parent::doTest();\n"
" }\n"
"}\n"
"D::doTest();\n"
"echo \"Done\\n\";\n"
,
"C\n"
"D\n"
"T::blarg\n"
"Done\n"
);
MVCRO("<?php\n"
"trait T {\n"
" final public function foo() {\n"
" return 'Bar';\n"
" }\n"
"}\n"
"class Bar {\n"
" use T;\n"
" final public function foo() {\n"
" return 'Foo';\n"
" }\n"
"}\n"
"$bar = new Bar();\n"
"echo $bar->foo().\"\\n\";\n"
,
"Foo\n");
MVCRO("<?php\n"
"class Foo {\n"
" protected function f() {\n"
" return 'Foo';\n"
" }\n"
"}\n"
"trait T {\n"
" public function f() {\n"
" return 'Bar';\n"
" }\n"
"}\n"
"class Bar extends Foo {\n"
" use T;\n"
"}\n"
"$b = new Bar();\n"
"echo $b->f().\"\\n\";\n"
,
"Bar\n");
MVCRO("<?php\n"
"class Foo {\n"
" private function f() {\n"
" return 'Foo';\n"
" }\n"
"}\n"
"trait T {\n"
" private function f() {\n"
" return 'Bar';\n"
" }\n"
"}\n"
"class Bar extends Foo {\n"
" use T;\n"
" function inv() {\n"
" return $this->f();\n"
" }\n"
"}\n"
"$b = new Bar();\n"
"echo $b->inv().\"\\n\";\n"
,
"Bar\n");
MVCRO("<?php\n"
"class Foo {\n"
" private function f() {\n"
" return 'Foo';\n"
" }\n"
"}\n"
"trait T {\n"
" protected function f() {\n"
" return 'Bar';\n"
" }\n"
"}\n"
"class Bar extends Foo {\n"
" use T;\n"
" function inv() {\n"
" return $this->f();\n"
" }\n"
"}\n"
"$b = new Bar();\n"
"echo $b->inv().\"\\n\";\n"
,
"Bar\n");
MVCRO("<?php\n"
"class Foo {\n"
" protected function f() {\n"
" return 'Foo';\n"
" }\n"
"}\n"
"trait T {\n"
" protected function f() {\n"
" return 'Bar';\n"
" }\n"
"}\n"
"class Bar extends Foo {\n"
" use T;\n"
" function inv() {\n"
" return $this->f();\n"
" }\n"
"}\n"
"$b = new Bar();\n"
"echo $b->inv().\"\\n\";\n"
,
"Bar\n");
MVCRO("<?php\n"
"trait T {\n"
" abstract static function f();\n"
"}\n"
"abstract class Foo {\n"
" abstract static function f();\n"
"}\n"
"class Bar extends Foo {\n"
" use T;\n"
" static function f() {\n"
" echo \"Foo\\n\";\n"
" }\n"
"}\n"
"Bar::f();\n"
,
"Foo\n");
MVCRO("<?php\n"
"trait T {\n"
" function hello() { echo \"Hello from T!\n\"; }\n"
"}\n"
"class B {\n"
" use T;\n"
" function hello() { echo \"Hello from B!\n\"; }\n"
"}\n"
"class C extends B {}\n"
"class D extends C {}\n"
"$ob = new B();\n"
"$ob->hello();\n"
"$oc = new C();\n"
"$oc->hello();\n"
"$od = new D();\n"
"$od->hello();\n"
,
"Hello from B!\n"
"Hello from B!\n"
"Hello from B!\n"
);
MVCRO("<?php\n"
"trait T1 { abstract function foo(); }\n"
"trait T2 { abstract function foo(); }\n"
"class B {\n"
" function foo() { return \"hello\\n\"; }\n"
"}\n"
"class C extends B {\n"
" use T1, T2;\n"
"}\n"
"$o = new C;\n"
"echo $o->foo();\n"
,
"hello\n");
MVCRO("<?php\n"
"trait T1 { abstract function foo(); }\n"
"trait T2 { abstract function foo(); }\n"
"abstract class B {\n"
" use T1, T2;\n"
"}\n"
"class C extends B {\n"
" function foo() { return \"hello\\n\"; }\n"
"}\n"
"$o = new C;\n"
"echo $o->foo();\n"
,
"hello\n");
MVCRO("<?php\n"
"class A {\n"
" static public $bp = \"hello\\n\";\n"
"}\n"
"trait T {\n"
" function foo() {\n"
" echo A::$bp;\n"
" }\n"
"}\n"
"class C { use T; }\n"
"$o = new C;\n"
"$o->foo();\n"
,
"hello\n");
MVCRO("<?php\n"
"class B {\n"
" static public $bp = \"B::hello\\n\";\n"
"}\n"
"trait T {\n"
" function foo() {\n"
" echo self::$bp;\n"
" }\n"
"}\n"
"class C extends B {\n"
" static public $bp = \"C::hello\\n\";\n"
" use T;\n"
"}\n"
"$o = new C;\n"
"$o->foo();\n"
,
"C::hello\n");
MVCRO("<?php\n"
"class B {\n"
" static public $bp = \"B::hello\\n\";\n"
"}\n"
"trait T {\n"
" function foo() {\n"
" echo parent::$bp;\n"
" }\n"
"}\n"
"class C extends B {\n"
" static public $bp = \"C::hello\\n\";\n"
" use T;\n"
"}\n"
"$o = new C;\n"
"$o->foo();\n"
,
"B::hello\n");
MVCRO("<?php "
"class A {"
" function foo() { var_dump('fail'); }"
" function bar() { $this->foo(); }"
"}"
"trait BT {"
" function foo() { var_dump('ok'); }"
"}"
"class B extends A {"
" use BT;"
"}"
"function test() {"
" $b = new B;"
" $b->bar();"
"}"
"test();",
"string(2) \"ok\"\n");
MVCRO("<?php\n"
"trait T { public function y() {} }\n"
"interface I { public function y();}\n"
"class C { use T ; }\n"
"var_dump(method_exists('T', 'y'));\n"
"var_dump(method_exists('C', 'y'));\n"
"var_dump(method_exists('I', 'y'));\n"
"var_dump(method_exists('T', 'x'));\n"
"var_dump(method_exists('C', 'x'));\n"
"var_dump(method_exists('I', 'x'));\n"
,
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(false)\n"
"bool(false)\n"
"bool(false)\n");
MVCRO("<?php\n"
"if (true) {\n"
" trait T { public static function foo() { echo \"Foo\\n\"; } }\n"
" class C { use T; }\n"
"}\n"
"C::foo();\n"
,
"Foo\n"
);
MVCRO("<?php\n"
"final class Foo {\n"
" use Bar;\n"
" private static $a = 3;\n"
"}\n"
"trait Bar {\n"
" private static $a = 3;\n"
"}\n"
"echo \"Done\\n\";\n"
,
"Done\n"
);
MVCRO("<?php\n"
"function show_without_extra_vardump_nonsense($arr) {\n"
" echo 'array (' . count($arr) . \") {\\n\";\n"
" foreach ($arr as $val) {\n"
" echo \" $val\\n\";\n"
" }\n"
" echo \"}\\n\";\n"
"}\n"
"function do_wonderful_things_with($r) {\n"
" echo \"yall know what time it is. time to show you some properties\\n\";\n"
" $props = array();\n"
" foreach ($r->getProperties() as $prop) {\n"
" $props[] = $prop->getName();\n"
" }\n"
" asort($props);\n"
" show_without_extra_vardump_nonsense($props);\n"
" $meths = array();\n"
" echo \"yall know what time it is now too. time to show you some methods\\n\";\n"
" foreach ($r->getMethods() as $meth) {\n"
" $meths[] = $meth->getName();\n"
" }\n"
" asort($meths);\n"
" show_without_extra_vardump_nonsense($meths);\n"
"}\n"
"\n"
"trait T {\n"
" private $priv;\n"
" protected $prot;\n"
" public $pub;\n"
"\n"
" private static $priv_st;\n"
" protected static $prot_st;\n"
" public static $pub_st;\n"
"\n"
" private function fpriv() {}\n"
" protected function fprot() {}\n"
" public function fpub() {}\n"
"\n"
" private static function fpriv_st() {}\n"
" protected static function fprot_st() {}\n"
" public static function fpub_st() {}\n"
"}\n"
"\n"
"trait U {\n"
" public $foo;\n"
" public static $static;\n"
"\n"
" public function ffoo() {}\n"
" public static function fstatic() {}\n"
"}\n"
"\n"
"class C {\n"
" use T;\n"
"\n"
" private $c_priv;\n"
"}\n"
"\n"
"class D extends C {\n"
" use U;\n"
"\n"
" public $class_prop;\n"
" public function class_method() {}\n"
"\n"
"}\n"
"\n"
"$r = new ReflectionClass('C');\n"
"do_wonderful_things_with($r);\n"
"\n"
"$r = new ReflectionClass('D');\n"
"do_wonderful_things_with($r);\n"
,
"yall know what time it is. time to show you some properties\n"
"array (7) {\n"
" c_priv\n"
" priv\n"
" priv_st\n"
" prot\n"
" prot_st\n"
" pub\n"
" pub_st\n"
"}\n"
"yall know what time it is now too. time to show you some methods\n"
"array (6) {\n"
" fpriv\n"
" fpriv_st\n"
" fprot\n"
" fprot_st\n"
" fpub\n"
" fpub_st\n"
"}\n"
"yall know what time it is. time to show you some properties\n"
"array (7) {\n"
" class_prop\n"
" foo\n"
" prot\n"
" prot_st\n"
" pub\n"
" pub_st\n"
" static\n"
"}\n"
"yall know what time it is now too. time to show you some methods\n"
"array (9) {\n"
" class_method\n"
" ffoo\n"
" fpriv\n"
" fpriv_st\n"
" fprot\n"
" fprot_st\n"
" fpub\n"
" fpub_st\n"
" fstatic\n"
"}\n"
);
return true;
}
bool TestCodeRun::TestUConverter() {
// ext/intl/tests/uconverter_enum.phpt
MVCRO("<?php "
"$avail = UConverter::getAvailable();"
"var_dump(count($avail) > 100);"
"var_dump(in_array('UTF-7', $avail));"
"var_dump(in_array('CESU-8', $avail));"
"var_dump(in_array('ISO-8859-1', $avail));"
"$latin1 = UConverter::getAliases('latin1');"
"var_dump(in_array('ISO-8859-1', $latin1));"
,
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
);
// ext/intl/tests/uconverter_func_basic.phpt
MVCRO("<?php "
"var_dump(UConverter::transcode(\"This is an ascii string\", 'utf-8', 'latin1'));"
"var_dump(urlencode(UConverter::transcode(\"Espa\\xF1ol\", 'utf-8', 'latin1')));"
"var_dump(urlencode(UConverter::transcode(\"Stra\\xDFa\", 'utf-8', 'latin1')));"
"var_dump(bin2hex(UConverter::transcode(\"\\xE4\", 'utf-8', 'koi8-r')));"
,
"string(23) \"This is an ascii string\"\n"
"string(12) \"Espa%C3%B1ol\"\n"
"string(11) \"Stra%C3%9Fa\"\n"
"string(4) \"d094\"\n"
);
// ext/intl/tests/uconverter_func_subst.phpt
MVCRO("<?php "
"foreach(array('?','','?" /* this is not a trigraph */ "?') as $subst) {"
" $opts = array('to_subst' => $subst);"
" $ret = UConverter::transcode(\"This is an ascii string\", 'ascii', 'utf-8', $opts);"
" if ($ret === NULL) {"
" echo \"Error: \", intl_get_error_message(), \"\\n\";"
" } else {"
" var_dump($ret);"
" }"
" $ret = UConverter::transcode(\"Snowman: (\\xE2\\x98\\x83)\", 'ascii', 'utf-8', $opts);"
" if ($ret === NULL) {"
" echo \"Error: \", intl_get_error_message(), \"\\n\";"
" } else {"
" var_dump($ret);"
" }"
"}"
,
"string(23) \"This is an ascii string\"\n"
"string(12) \"Snowman: (?)\"\n"
"Error: ucnv_setSubstChars() returned error 1: U_ILLEGAL_ARGUMENT_ERROR\n"
"Error: ucnv_setSubstChars() returned error 1: U_ILLEGAL_ARGUMENT_ERROR\n"
"Error: ucnv_setSubstChars() returned error 1: U_ILLEGAL_ARGUMENT_ERROR\n"
"Error: ucnv_setSubstChars() returned error 1: U_ILLEGAL_ARGUMENT_ERROR\n"
);
// ext/intl/tests/uconverter_oop_algo.phpt
MVCRO("<?php "
"$c = new UConverter('utf-8', 'latin1');"
"var_dump(UConverter::LATIN_1 === $c->getSourceType());"
"var_dump(UConverter::UTF8 === $c->getDestinationType());"
"$c = new UConverter('koi8-r', 'utf-32be');"
"var_dump(UConverter::UTF32_BigEndian === $c->getSourceType());"
"var_dump(UConverter::SBCS === $c->getDestinationType());"
,
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
"bool(true)\n"
);
// ext/intl/tests/uconverter_oop_basic.phpt
MVCRO("<?php "
"$c = new UConverter('utf-8', 'latin1');"
"var_dump($c->convert(\"This is an ascii string\"));"
"var_dump(urlencode($c->convert(\"Espa\\xF1ol\")));"
"var_dump(urlencode($c->convert(\"Stra\\xDFa\")));"
"var_dump(urlencode($c->convert(\"Stra\\xC3\\x9Fa\", true)));"
"$k = new UConverter('utf-8', 'koi8-r');"
"var_dump(bin2hex($k->convert(\"\\xE4\")));"
,
"string(23) \"This is an ascii string\"\n"
"string(12) \"Espa%C3%B1ol\"\n"
"string(11) \"Stra%C3%9Fa\"\n"
"string(8) \"Stra%DFa\"\n"
"string(4) \"d094\"\n"
);
// ext/intl/tests/uconverter_oop_callback.phpt
MVCRO("<?php "
"class MyConverter extends UConverter {"
" public function toUCallback($reason, $source, $codeUnits, &$error) {"
" echo \"toUCallback(\", UConverter::reasonText($reason), \", ...)\\n\";"
" return parent::toUCallback($reason, $source, $codeUnits, $error);"
" }"
" public function fromUCallback($reason, $source, $codePoint, &$error) {"
" echo \"fromUCallback(\", UConverter::reasonText($reason), \", ...)\\n\";"
" return parent::fromUCallback($reason, $source, $codePoint, $error);"
" }"
"}"
"$c = new MyConverter('ascii', 'utf-8');"
"foreach(array(\"regular\", \"irregul\\xC1\\xA1r\", \"\\xC2\\xA1unsupported!\") as $word) {"
" $c->convert($word);"
"}"
"unset($c);"
,
"toUCallback(REASON_RESET, ...)\n"
"toUCallback(REASON_RESET, ...)\n"
"fromUCallback(REASON_RESET, ...)\n"
"fromUCallback(REASON_RESET, ...)\n"
"toUCallback(REASON_RESET, ...)\n"
"toUCallback(REASON_ILLEGAL, ...)\n"
"toUCallback(REASON_RESET, ...)\n"
"toUCallback(REASON_ILLEGAL, ...)\n"
"fromUCallback(REASON_RESET, ...)\n"
"fromUCallback(REASON_RESET, ...)\n"
"toUCallback(REASON_RESET, ...)\n"
"toUCallback(REASON_RESET, ...)\n"
"fromUCallback(REASON_RESET, ...)\n"
"fromUCallback(REASON_UNASSIGNED, ...)\n"
"fromUCallback(REASON_RESET, ...)\n"
"fromUCallback(REASON_UNASSIGNED, ...)\n"
"toUCallback(REASON_CLOSE, ...)\n"
"fromUCallback(REASON_CLOSE, ...)\n"
"toUCallback(REASON_CLOSE, ...)\n"
"fromUCallback(REASON_CLOSE, ...)\n"
);
// ext/intl/tests/uconverter_oop_callback_return.phpt
MVCRO("<?php "
"class MyConverter extends UConverter {"
" public function toUCallback($reason, $source, $codeUnits, &$error) {"
" $error = U_ZERO_ERROR;"
" switch ($codeUnits) {"
" case \"\\x80\": return NULL;"
" case \"\\x81\": return 'a';"
" case \"\\x82\": return ord('b');"
" case \"\\x83\": return array('c');"
" }"
" }"
" public function fromUCallback($reason, $source, $codePoint, &$error) {"
" $error = U_ZERO_ERROR;"
" switch ($codePoint) {"
" case 0x00F1: return \"A\";"
" case 0x00F2: return ord(\"B\");"
" case 0x00F3: return array(\"C\");"
" case 0x00F4: return NULL;"
" }"
" }"
"}"
"$c = new MyConverter('ascii', 'utf-8');"
"var_dump($c->convert(\"\\x80\\x81\\x82\\x83\"));"
"var_dump($c->convert(\"\\xC3\\xB1\\xC3\\xB2\\xC3\\xB3\\xC3\\xB4\"));"
,
"string(3) \"abc\"\n"
"string(3) \"ABC\"\n"
);
// ext/intl/tests/uconverter_oop_subst.phpt
MVCRO("<?php "
"$c = new UConverter('ascii', 'utf-8');"
"foreach(array('?','','<unknown>') as $subst) {"
" if (!$c->setSubstChars($subst)) {"
" echo \"**Disallowed\\n\";"
" continue;"
" }"
" var_dump($c->convert(\"This is an ascii string\"));"
" var_dump($c->convert(\"Snowman: (\\xE2\\x98\\x83)\"));"
"}"
,
"string(23) \"This is an ascii string\"\n"
"string(12) \"Snowman: (?)\"\n"
"**Disallowed\n"
"**Disallowed\n"
);
return true;
}
bool TestCodeRun::TestStrictMode() {
HipHopSyntax w(this);
MVCRO("<?hh\necho 42;\n", "42");
MVCRONW(" <?hh\necho 42;\n", "");
MVCRONW("<?hh\necho 42;\n?>", "");
// Wrong type, fail
MVCRONW("<?hh\nfunction t(X $a) { echo 1; } t(42);", "");
// My
MVCRO("<?hh\nfunction t(?X $a) { echo 1; } t(42);", "1");
// Now a typevar, pass
MVCRO("<?hh\nfunction t<X>(X $a) { echo 1; } t(42);", "1");
// Generic with as
MVCRO("<?hh\nclass C<T as I>{}", "");
// Silent type hint
MVCRO("<?hh\nfunction foo(@int $x){ echo 1; } foo('hi');", "1");
// Combination of optional + generic
MVCRO("<?hh\nfunction foo(): Map<int, ?Vector<int>> {}", "");
// Arrays with generic types
MVCRO("<?hh\nfunction foo(array<int> $x) {}", "");
MVCRO("<?hh\nfunction foo(array<string, int> $x) {}", "");
// Kitchen sink
MVCRO("<?hh\n"
"function vidx<X>(blarg<X> $list, int $idx):X {\n"
" return $list->d[$idx];\n"
"}\n"
"function pair<X,Y>(X $x, Y $y):(X,Y) { return array($x, $y); }\n"
"function car<X,Y>((X,?Y) $pair):X {\n"
" return $pair[0];\n"
"}\n"
"interface Face<A> {\n"
"}\n"
"class blarg<X> { function __construct($x) { $this->d = $x; } }\n"
"function blarg<X>(/*...*/):blarg<X> { return new blarg(func_get_args()); }\n"
"\n"
"class Foo<X> implements Face<X> {\n"
" const string BLEH = \"b\";\n"
"}\n"
"\n"
"$blork = pair('c', '-');\n"
"\n"
"function right_shift_hack(Foo<Foo<Foo<Foo<Foo<Foo<Foo<Foo<Foo<Foo<"
"Foo>,Foo>>,Foo>>>,Foo>>>> $bonk,\n"
" (function(Foo,Bar):C) $d) {\n"
"}\n"
"\n"
"$a = blarg('a','aa','aaa');\n"
"$d = (function():UNICORNS{return 'd';});\n"
"echo vidx($a, 0), Foo::BLEH, car($blork), $d();\n",
"abcd");
MVCRO("<?hh\n"
"function f() {\n"
" $x = new Foo<Bar>();\n"
" $x = new Foo<Blah<Bar>>();\n"
" $y = new Foo<array,int>();\n"
" $z = new Foo<Blah<array>,Blah<int>>();\n"
" yo<int>();\n"
" yo<Blah<int>>();\n"
" yo<string,:my:xhp:class>();\n"
" yo<Blah<string>,Blah<:my:xhp:class>>();\n"
" $x->baz<int>();\n"
" $x->baz<Blah<int>>();\n"
" $y->baz<string,:my:xhp:class>();\n"
" $y->baz<Blah<string>,Blah<:my:xhp:class>>();\n"
" Foo<Bar>::biz();\n"
" Foo<Blah<Bar>>::biz();\n"
" Foo<Bar>::biz<string>();\n"
" Foo<Blah<Bar>>::biz<Blah<string>>();\n"
" Foo<Bar>::biz<bool,:my:xhp:class>();\n"
" Foo<Blah<Bar>>::biz<Blah<bool>,Blah<:my:xhp:class>>();\n"
" Foo<array,int>::biz();\n"
" Foo<Blah<array>,Blah<int>>::biz();\n"
" Foo<array,int>::biz<string>();\n"
" Foo<Blah<array>,Blah<int>>::biz<Blah<string>>();\n"
" Foo<array,int>::biz<bool,:my:xhp:class>();\n"
" Foo<Blah<array>,Blah<int>>::biz<Blah<bool>,Blah<:my:xhp:class>>();\n"
" var_dump(Foo<Bar>::SOME_CONST);\n"
" var_dump(Foo<Blah<Bar>>::SOME_CONST);\n"
" var_dump(Foo<array,int>::SOME_CONST);\n"
" var_dump(Foo<Blah<array>,Blah<int>>::SOME_CONST);\n"
" var_dump(Foo<Bar>::$staticProp);\n"
" var_dump(Foo<Blah<Bar>>::$staticProp);\n"
" var_dump(Foo<array,int>::$staticProp);\n"
" var_dump(Foo<Blah<array>,Blah<int>>::$staticProp);\n"
"}\n"
"echo \"Done\\n\";\n"
,
"Done\n"
);
MVCRO("<?hh\n"
"abstract class Foo {\n"
" abstract function f1() : (function():void);\n"
" abstract function f2() : (function(int):void);\n"
" abstract function f3() : (function(int,string):void);\n"
" abstract function f4() : (function(...):void);\n"
" abstract function f5() : (function(int,...):void);\n"
" abstract function f6() : (function(int,string,...):void);\n"
" abstract function g1() : Foo<(function():void)>;\n"
" abstract function g2() : Foo<(function(int):void)>;\n"
" abstract function g3() : Foo<(function(int,string):void)>;\n"
" abstract function g4() : Foo<(function(...):void)>;\n"
" abstract function g5() : Foo<(function(int,...):void)>;\n"
" abstract function g6() : Foo<(function(int,string,...):void)>;\n"
" abstract function h1((function():void) $x) : void;\n"
" abstract function h2((function(int):void) $x) : void;\n"
" abstract function h3((function(int,string):void) $x) : void;\n"
" abstract function h4((function(...):void) $x) : void;\n"
" abstract function h5((function(int,...):void) $x) : void;\n"
" abstract function h6((function(int,string,...):void) $x) : void;\n"
" abstract function j1(Foo<(function():void)> $x) : void;\n"
" abstract function j2(Foo<(function(int):void)> $x) : void;\n"
" abstract function j3(Foo<(function(int,string):void)> $x) : void;\n"
" abstract function j4(Foo<(function(...):void)> $x): void;\n"
" abstract function j5(Foo<(function(int,...):void)> $x): void;\n"
" abstract function j6(Foo<(function(int,string,...):void)> $x): "
"void;\n"
"}\n"
"echo \"Done\\n\";\n"
,
"Done\n"
);
return true;
}
// please leave this unit test at last for debugging ad hoc code
bool TestCodeRun::TestAdHoc() {
return true;
}