Use PHP test framework for testing hphpd in sandbox server mode
Debugger tests that run hphp in non local mode (i.e. with the "-h some-server:some-port" option specified) currently use a clunky specialized C++ test harness that invokes PHP scripts that talk to the debugger client via the obsolete client API. This revision moves those tests to the new PHP only framework. The debugger client is now controlled by piping in commands, just like the other debugger tests. The main difference is that the debugger client is connected to a server instance and a separate PHP driver is used to load the server, load the client, and then load pages from the server so that the client can hit breakpoints. It also checks that the client can respond to ctrl-c by actually sending a SIGINT signal to the client process.
Esse commit está contido em:
@@ -1141,6 +1141,7 @@ static int execute_program_impl(int argc, char** argv) {
|
||||
StackTraceNoHeap::AddExtraLogging("IsDebugger", "True");
|
||||
RuntimeOption::EnableDebugger = true;
|
||||
po.debugger_options.fileName = file;
|
||||
po.debugger_options.user = po.user;
|
||||
Eval::DebuggerProxyPtr localProxy =
|
||||
Eval::Debugger::StartClient(po.debugger_options);
|
||||
if (!localProxy) {
|
||||
@@ -1456,7 +1457,7 @@ bool hphp_invoke(ExecutionContext *context, const std::string &cmd,
|
||||
funcRet->assignVal(invoke(cmd.c_str(), funcParams));
|
||||
} else {
|
||||
if (isServer) hphp_chdir_file(cmd);
|
||||
include_impl_invoke(cmd.c_str(), once);
|
||||
include_impl_invoke(cmd.c_str(), once);
|
||||
}
|
||||
} catch (...) {
|
||||
handle_invoke_exception(ret, context, errorMsg, error, richErrorMsg);
|
||||
|
||||
@@ -118,6 +118,9 @@ void DebuggerClient::onSignal(int sig) {
|
||||
|
||||
int DebuggerClient::pollSignal() {
|
||||
TRACE(2, "DebuggerClient::pollSignal\n");
|
||||
if (m_scriptMode) {
|
||||
print(".....Debugger client still waiting for server response.....");
|
||||
}
|
||||
int ret = m_signum;
|
||||
m_signum = CmdSignal::SignalNone;
|
||||
return ret;
|
||||
@@ -397,7 +400,7 @@ String DebuggerClient::FormatTitle(const char *title) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebuggerClient::DebuggerClient(std::string name /* = "" */)
|
||||
: m_tutorial(0), m_printFunction(""),
|
||||
: m_tutorial(0), m_printFunction(""), m_scriptMode(false),
|
||||
m_logFile(""), m_logFileHandler(nullptr),
|
||||
m_mainThread(this, &DebuggerClient::run), m_stopped(false),
|
||||
m_inputState(TakingCommand),
|
||||
@@ -608,13 +611,19 @@ void DebuggerClient::init(const DebuggerClientOptions &options) {
|
||||
if (!options.configFName.empty()) {
|
||||
m_configFileName = options.configFName;
|
||||
}
|
||||
m_options.user = Process::GetCurrentUser();
|
||||
if (options.user.empty())
|
||||
m_options.user = Process::GetCurrentUser();
|
||||
}
|
||||
|
||||
usageLogEvent("init");
|
||||
|
||||
loadConfig();
|
||||
|
||||
if (m_scriptMode) {
|
||||
print("running in script mode, pid=%d\n",
|
||||
(int32_t)Process::GetProcessId());
|
||||
}
|
||||
|
||||
if (!options.cmds.empty()) {
|
||||
RuntimeOption::EnableDebuggerColor = false;
|
||||
RuntimeOption::EnableDebuggerPrompt = false;
|
||||
@@ -1122,6 +1131,9 @@ DebuggerCommandPtr DebuggerClient::eventLoop(EventLoopKind loopKind,
|
||||
console(); // Prompt loop
|
||||
m_inputState = TakingInterrupt;
|
||||
m_machine->m_interrupting = false; // Machine is running again.
|
||||
if (m_scriptMode) {
|
||||
print("Waiting for server response");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw DebuggerClientExitException(); // Stopped, so exit.
|
||||
@@ -2347,6 +2359,7 @@ void DebuggerClient::loadConfig() {
|
||||
}
|
||||
|
||||
m_tutorial = m_config["Tutorial"].getInt32(0);
|
||||
m_scriptMode = m_config["ScriptMode"].getBool();
|
||||
std::string pprint = m_config["PrettyPrint"].getString("hphpd_print_value");
|
||||
setDebuggerBypassCheck(m_config["BypassAccessCheck"].getBool());
|
||||
setDebuggerClientSmallStep(m_config["SmallStep"].getBool());
|
||||
|
||||
@@ -365,6 +365,7 @@ private:
|
||||
int m_tutorial;
|
||||
std::string m_printFunction;
|
||||
std::set<std::string> m_tutorialVisited;
|
||||
bool m_scriptMode; // Is this client being scripted by a test?
|
||||
|
||||
DECLARE_DBG_SETTING
|
||||
DECLARE_DBG_CLIENT_SETTING
|
||||
@@ -378,7 +379,7 @@ private:
|
||||
|
||||
InputState m_inputState;
|
||||
int m_signum; // Set when ctrl-c is pressed, used by signal polling
|
||||
int m_sigTime; // The last time ctrl-c was recgonized
|
||||
int m_sigTime; // The last time ctrl-c was recognized
|
||||
|
||||
// auto-completion states
|
||||
int m_acLen;
|
||||
|
||||
@@ -1,66 +1,4 @@
|
||||
UTF8 = 1
|
||||
Color = 0
|
||||
Color {
|
||||
SupportedNames {
|
||||
1 = black
|
||||
2 = red
|
||||
3 = green
|
||||
4 = brown
|
||||
5 = blue
|
||||
6 = magenta
|
||||
7 = cyan
|
||||
8 = gray
|
||||
9 = dark_gray
|
||||
10 = light_red
|
||||
11 = light_green
|
||||
12 = yellow
|
||||
13 = light_blue
|
||||
14 = light_magenta
|
||||
15 = light_cyan
|
||||
16 = white
|
||||
}
|
||||
Palette {
|
||||
emacs {
|
||||
Keyword = CYAN
|
||||
Comment = RED
|
||||
String = GREEN
|
||||
Variable = BROWN
|
||||
Html = GRAY
|
||||
Tag = MAGENTA
|
||||
Declaration = BLUE
|
||||
Constant = MAGENTA
|
||||
LineNo = GRAY
|
||||
}
|
||||
vim {
|
||||
Keyword = MAGENTA
|
||||
Comment = BLUE
|
||||
String = RED
|
||||
Variable = CYAN
|
||||
Html = GRAY
|
||||
Tag = MAGENTA
|
||||
Declaration = WHITE
|
||||
Constant = WHITE
|
||||
LineNo = GRAY
|
||||
}
|
||||
}
|
||||
Help = BROWN
|
||||
Info = GREEN
|
||||
Output = CYAN
|
||||
Error = RED
|
||||
ItemName = GRAY
|
||||
HighlightForeground = RED
|
||||
HighlightBackground = GRAY
|
||||
Code {
|
||||
Keyword = CYAN
|
||||
Comment = RED
|
||||
String = GREEN
|
||||
Variable = BROWN
|
||||
Html = GRAY
|
||||
Tag = MAGENTA
|
||||
Declaration = BLUE
|
||||
Constant = MAGENTA
|
||||
LineNo = GRAY
|
||||
}
|
||||
}
|
||||
Tutorial = -1
|
||||
MaxCodeLines = -1
|
||||
|
||||
@@ -163,6 +163,7 @@ function map_convenience_filename($file) {
|
||||
$mappage = array(
|
||||
'quick' => 'hphp/test/quick',
|
||||
'slow' => 'hphp/test/slow',
|
||||
'debugger' => 'hphp/test/server/debugger/tests',
|
||||
'zend' => 'hphp/test/zend/good',
|
||||
'zend_bad' => 'hphp/test/zend/bad',
|
||||
'facebook' => 'hphp/facebook/test',
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
Eval {
|
||||
EnableXHP = true
|
||||
AllowHhas = true
|
||||
EnableHipHopSyntax = true
|
||||
EnableObjDestructCall = true
|
||||
JitASize = 10485760 # 10 MB
|
||||
JitAStubsSize = 10485760 # 10 MB
|
||||
JitGlobalDataSize = 2097152 # 2 MB
|
||||
Debugger {
|
||||
EnableDebugger = true
|
||||
EnableDebuggerColor = false
|
||||
EnableDebuggerPrompt = false
|
||||
}
|
||||
}
|
||||
|
||||
Repo {
|
||||
Local.Mode = --
|
||||
Eval.Mode = readonly
|
||||
Commit = true
|
||||
DebugInfo = true
|
||||
}
|
||||
|
||||
MySQL {
|
||||
ReadTimeout = 5000
|
||||
}
|
||||
|
||||
EnvVariables {
|
||||
HPHP_INTERPRETER = 1
|
||||
}
|
||||
|
||||
ServerVariables {
|
||||
ALPHA_CONSOLE = 1
|
||||
TFBENV = 16777216
|
||||
}
|
||||
|
||||
ErrorHandling {
|
||||
NoticeFrequency = 1
|
||||
WarningFrequency = 1
|
||||
}
|
||||
|
||||
ResourceLimit {
|
||||
SerializationSizeLimit=134217728
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
Log {
|
||||
AlwaysLogUnhandledExceptions = false
|
||||
}
|
||||
|
||||
Server {
|
||||
AllowedFiles {
|
||||
* = hello.php
|
||||
* = hphpd.php
|
||||
}
|
||||
}
|
||||
|
||||
Eval {
|
||||
Debugger {
|
||||
EnableDebugger = true
|
||||
EnableDebuggerServer = true
|
||||
StartupDocument = hphpd_startup.php
|
||||
SignalTimeout = 5
|
||||
}
|
||||
}
|
||||
|
||||
Sandbox {
|
||||
SandboxMode = true
|
||||
ConfFile = sandbox_conf
|
||||
# only match hphpd.<user>.sth.sth, not any requests
|
||||
Pattern = hphpd\.([a-z0-9_-]+)\.[a-z0-9_-]+\.[a-z0-9_-]+
|
||||
}
|
||||
|
||||
Repo {
|
||||
Local.Mode = --
|
||||
Eval.Mode = readonly
|
||||
Commit = true
|
||||
DebugInfo = true
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
UTF8 = 1
|
||||
Color = 0
|
||||
ScriptMode = true
|
||||
Tutorial = -1
|
||||
MaxCodeLines = -1
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
// Warning: line numbers are sensitive, do not change
|
||||
|
||||
function foo($x) {
|
||||
$y = $x.'_suffix';
|
||||
error_log($y);
|
||||
}
|
||||
|
||||
class cls {
|
||||
public function pubObj($x) {
|
||||
error_log("pubObj:".$x);
|
||||
}
|
||||
public static function pubCls($x) {
|
||||
error_log("pubCls:".$x);
|
||||
}
|
||||
public function pubHardBreak($x) {
|
||||
error_log("pubHardBreak:".$x);
|
||||
hphpd_break();
|
||||
error_log("pubHardBreak:done");
|
||||
}
|
||||
}
|
||||
|
||||
class derived extends cls {
|
||||
public function callPubObj($x) {
|
||||
$this->pubObj($x);
|
||||
}
|
||||
public function callCallPubObj($x) {
|
||||
$this->callPubObj($x);
|
||||
}
|
||||
}
|
||||
|
||||
error_log('break1.php loaded');
|
||||
@@ -0,0 +1 @@
|
||||
<?php echo "Hello, World!";
|
||||
@@ -0,0 +1 @@
|
||||
<?php
|
||||
@@ -0,0 +1,4 @@
|
||||
default.path = .
|
||||
default.accesslog = /tmp/hphpd_test_sandbox_access.log
|
||||
default.ServerVars {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
break break1.php:7
|
||||
continue
|
||||
variable
|
||||
break clear all
|
||||
break foo()
|
||||
continue
|
||||
break clear all
|
||||
break cls::pubObj()
|
||||
continue
|
||||
break clear all
|
||||
break cls::pubCls()
|
||||
continue
|
||||
break clear all
|
||||
continue
|
||||
continue
|
||||
@ $a = 0
|
||||
break test1.php:18
|
||||
continue
|
||||
p $a
|
||||
break clear all
|
||||
break end test1.php
|
||||
continue
|
||||
break psp test1.php
|
||||
continue
|
||||
quit
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
include 'break1.php';
|
||||
|
||||
function test_break() {
|
||||
$x = 'test_break() in test1.php';
|
||||
foo($x);
|
||||
foo($x);
|
||||
$obj = new cls();
|
||||
$obj->pubObj($x);
|
||||
cls::pubCls($x);
|
||||
$obj->pubHardBreak($x);
|
||||
}
|
||||
|
||||
function test_sleep() {
|
||||
$a = 1;
|
||||
// $a will be set to 0 by debugger after interrupt
|
||||
while ($a == 1) { sleep(1); }
|
||||
return $a;
|
||||
}
|
||||
|
||||
test_break();
|
||||
test_sleep();
|
||||
echo "request done\n";
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
require_once('test_base.php');
|
||||
|
||||
function test1Controller($hphpdOutput, $hphpdProcessId, $serverPort) {
|
||||
// Request a page so that the client can debug it.
|
||||
waitForClientToOutput($hphpdOutput, "Waiting for server response");
|
||||
$url = "http://".php_uname('n').':'.$serverPort.'/test1.php';
|
||||
echo "Requesting test1.php\n";
|
||||
request($url, 1); // proceed without waiting for a response
|
||||
|
||||
// Send ctrl-c to client, which is waiting for a hung server
|
||||
waitForClientToOutput($hphpdOutput, "Break at cls::pubHardBreak()");
|
||||
waitForClientToOutput($hphpdOutput, "Waiting for server response");
|
||||
sleep(2); // give server a chance to get itself in the enless loop
|
||||
echo "sending SIGINT to the debugger client.\n";
|
||||
posix_kill($hphpdProcessId, SIGINT);
|
||||
|
||||
// Let client run until script quits
|
||||
waitForClientToOutput($hphpdOutput, "quit");
|
||||
}
|
||||
|
||||
runTest('test1', "test1Controller");
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
Connecting to %s
|
||||
Attaching to debugger's default sandbox and pre-loading, please wait...
|
||||
break break1.php:7
|
||||
Breakpoint 1 set on line 7 of break1.php
|
||||
But wont break until file break1.php has been loaded.
|
||||
continue
|
||||
Waiting for server response
|
||||
Requesting test1.php
|
||||
Breakpoint 1 reached at foo() on line 7 of %s/break1.php
|
||||
6 $y = $x.'_suffix';
|
||||
7 error_log($y);
|
||||
8 }
|
||||
|
||||
variable
|
||||
$x = "test_break() in test1.php"
|
||||
$y = "test_break() in test1.php_suffix"
|
||||
break clear all
|
||||
All breakpoints are cleared.
|
||||
break foo()
|
||||
Breakpoint 1 set upon entering foo()
|
||||
continue
|
||||
Waiting for server response
|
||||
Breakpoint 1 reached at foo() on line 6 of %s/break1.php
|
||||
5 function foo($x) {
|
||||
6 $y = $x.'_suffix';
|
||||
7 error_log($y);
|
||||
|
||||
break clear all
|
||||
All breakpoints are cleared.
|
||||
break cls::pubObj()
|
||||
Breakpoint 1 set upon entering cls::pubObj()
|
||||
continue
|
||||
Waiting for server response
|
||||
Breakpoint 1 reached at cls::pubObj() on line 12 of %s/break1.php
|
||||
11 public function pubObj($x) {
|
||||
12 error_log("pubObj:".$x);
|
||||
13 }
|
||||
|
||||
break clear all
|
||||
All breakpoints are cleared.
|
||||
break cls::pubCls()
|
||||
Breakpoint 1 set upon entering cls::pubCls()
|
||||
continue
|
||||
Waiting for server response
|
||||
Breakpoint 1 reached at cls::pubCls() on line 15 of %s/break1.php
|
||||
14 public static function pubCls($x) {
|
||||
15 error_log("pubCls:".$x);
|
||||
16 }
|
||||
|
||||
break clear all
|
||||
All breakpoints are cleared.
|
||||
continue
|
||||
Waiting for server response
|
||||
Break at cls::pubHardBreak() on line 19 of %s/break1.php
|
||||
18 error_log("pubHardBreak:".$x);
|
||||
19 hphpd_break();
|
||||
20 error_log("pubHardBreak:done");
|
||||
|
||||
continue
|
||||
Waiting for server response
|
||||
sending SIGINT to the debugger client.
|
||||
Pausing program execution, please wait...
|
||||
Break at test_sleep() on line 17 of %s/test1.php
|
||||
16 // $a will be set to 0 by debugger after interrupt
|
||||
17 while ($a == 1) { sleep(1); }
|
||||
18 return $a;
|
||||
|
||||
@ $a = 0
|
||||
|
||||
break test1.php:18
|
||||
Breakpoint 1 set on line 18 of test1.php
|
||||
continue
|
||||
Waiting for server response
|
||||
Breakpoint 1 reached at test_sleep() on line 18 of %s/test1.php
|
||||
17 while ($a == 1) { sleep(1); }
|
||||
18 return $a;
|
||||
19 }
|
||||
|
||||
p $a
|
||||
0
|
||||
break clear all
|
||||
All breakpoints are cleared.
|
||||
break end test1.php
|
||||
Breakpoint 1 set end of request or start of psp when request is test1.php
|
||||
continue
|
||||
Waiting for server response
|
||||
Web request /test1.php ended.
|
||||
break psp test1.php
|
||||
Breakpoint 2 set end of psp when request is test1.php
|
||||
continue
|
||||
Waiting for server response
|
||||
Post-Send Processing for /test1.php was ended.
|
||||
quit
|
||||
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
$test_run_id = rand(100000, 999999);
|
||||
$error_log_file = fopen("/tmp/hphpd_test$test_run_id.log", 'w');
|
||||
|
||||
function tlog($str) {
|
||||
global $error_log_file;
|
||||
|
||||
fwrite($error_log_file, $str);
|
||||
fwrite($error_log_file, "\n");
|
||||
// error_log($str);
|
||||
}
|
||||
|
||||
function dumpLogFilesToStdoutAndDie() {
|
||||
global $error_log_file;
|
||||
global $test_run_id;
|
||||
|
||||
sleep(1);
|
||||
error_log('-------------------------------------------');
|
||||
error_log("Contents of '/tmp/hphpd_test$test_run_id.log'");
|
||||
readfile("/tmp/hphpd_test$test_run_id.log");
|
||||
echo "\n";
|
||||
error_log('-------------------------------------------');
|
||||
error_log("Contents of '/tmp/hphpd_test_server$test_run_id.log'");
|
||||
readfile("/tmp/hphpd_test_server$test_run_id.log");
|
||||
echo "\n";
|
||||
error_log('-------------------------------------------');
|
||||
error_log("Contents of '/tmp/hphpd_test_server_stdout$test_run_id.log'");
|
||||
readfile("/tmp/hphpd_test_server_stdout$test_run_id.log");
|
||||
echo "\n";
|
||||
error_log('-------------------------------------------');
|
||||
error_log("Contents of '/tmp/hphpd_test_server_stderr$test_run_id.log'");
|
||||
readfile("/tmp/hphpd_test_server_stderr$test_run_id.log");
|
||||
echo "\n";
|
||||
error_log('-------------------------------------------');
|
||||
error_log("Contents of '/tmp/hphpd_test_client$test_run_id.log'");
|
||||
readfile("/tmp/hphpd_test_client$test_run_id.log");
|
||||
echo "\n";
|
||||
error_log('-------------------------------------------');
|
||||
error_log("Contents of '/tmp/hphpd_test_sandbox_access.log'");
|
||||
readfile("/tmp/hphpd_test_sandbox_access.log");
|
||||
echo "\n";
|
||||
error_log('-------------------------------------------');
|
||||
throw new Exception("test failed");
|
||||
}
|
||||
|
||||
function hphp_home() {
|
||||
// __DIR__ == result.'hphp/test/server/debugger/tests'
|
||||
return realpath(__DIR__.'/../../../../..');
|
||||
}
|
||||
|
||||
function bin_root() {
|
||||
$dir = hphp_home() . '/' . '_bin';
|
||||
return is_dir($dir) ?
|
||||
$dir : # fbmake
|
||||
hphp_home() # github
|
||||
;
|
||||
}
|
||||
|
||||
function get_random_port() {
|
||||
$BasePort = 20000;
|
||||
$PortRange = 3000;
|
||||
return rand($BasePort, $BasePort+$PortRange);
|
||||
}
|
||||
|
||||
function startServer($serverPort, $adminPort, $debugPort) {
|
||||
global $test_run_id;
|
||||
|
||||
$home = hphp_home().'/hphp/test/server/debugger';
|
||||
$portConfig = ' -vServer.Port='.$serverPort;
|
||||
$serverConfig = ' --config='.$home.'/config/debugger-server.hdf';
|
||||
$logFileConfig = ' -vLog.File='."/tmp/hphpd_test_server$test_run_id.log";
|
||||
$srcRootConfig = ' -vServer.SourceRoot='.$home.'/debugger';
|
||||
$includePathConfig = ' -vServer.IncludeSearchPaths.0='.$home.'/debugger';
|
||||
$adminPortConfig = ' -vAdminServer.Port='.$adminPort;
|
||||
$debugPortConfig = ' -vEval.Debugger.Port='.$debugPort;
|
||||
$repoConfig = " -vRepo.Central.Path=/tmp/hphpd_server$test_run_id.hhbc";
|
||||
$useJit = array_key_exists('HHVM_JIT', $_ENV) && $_ENV['HHVM_JIT'] == 1;
|
||||
$jitConfig = ' -vEval.Jit='.($useJit ? "true" : "false");
|
||||
// To emulate sandbox setup, let Sandbox.Home be '$home'
|
||||
// and user name be 'debugger', so that the server can find the sandbox_conf
|
||||
// in '$home'.'/debugger'.
|
||||
$sandboxHomeConfig = ' -vSandbox.Home='.$home;
|
||||
|
||||
$hhvm = bin_root().'/hphp/hhvm/hhvm';
|
||||
|
||||
$cmd = $hhvm.' --mode=server' . $serverConfig . $logFileConfig .
|
||||
' -vEval.JitWarmupRequests=0' . $portConfig . $srcRootConfig .
|
||||
$includePathConfig . $sandboxHomeConfig . $adminPortConfig .
|
||||
$debugPortConfig . $repoConfig . $jitConfig .
|
||||
" > /tmp/hphpd_test_server_stdout$test_run_id.log" .
|
||||
" 2> /tmp/hphpd_test_server_stderr$test_run_id.log";
|
||||
|
||||
tlog('Starting server with command: '.$cmd);
|
||||
$pipes = array();
|
||||
$serverProc = proc_open($cmd, array(), $pipes);
|
||||
if (!is_resource($serverProc)) {
|
||||
tlog('Failed to start a shell process for the server');
|
||||
dumpLogFilesToStdoutAndDie();
|
||||
}
|
||||
return $serverProc;
|
||||
}
|
||||
|
||||
function waitForServerToGetGoing($serverPort) {
|
||||
$url = "http://".php_uname('n').':'.$serverPort.'/hello.php';
|
||||
$r = "";
|
||||
for ($i = 1; $i <= 20; $i++) {
|
||||
sleep(1);
|
||||
$r = request($url);
|
||||
if ($r === "Hello, World!") break;
|
||||
}
|
||||
|
||||
if ($r !== "Hello, World!") {
|
||||
tlog('Server is not responding.');
|
||||
dumpLogFilesToStdoutAndDie();
|
||||
}
|
||||
}
|
||||
|
||||
function stopServer($adminPort) {
|
||||
global $test_run_id;
|
||||
|
||||
$url = "http://".php_uname('n').':'.$adminPort.'/stop';
|
||||
$r = "";
|
||||
for ($i = 1; $i <= 10; $i++) {
|
||||
$r = request($url);
|
||||
if ($r == "OK\n") break;
|
||||
usleep(100000);
|
||||
}
|
||||
if ($r != "OK\n") {
|
||||
tlog("Server did not stop.");
|
||||
dumpLogFilesToStdoutAndDie();
|
||||
}
|
||||
unlink("/tmp/hphpd_test$test_run_id.log");
|
||||
unlink("/tmp/hphpd_test_server$test_run_id.log");
|
||||
unlink("/tmp/hphpd_test_server_stderr$test_run_id.log");
|
||||
unlink("/tmp/hphpd_test_server_stdout$test_run_id.log");
|
||||
unlink("/tmp/hphpd_test_client$test_run_id.log");
|
||||
unlink("/tmp/hphpd_server$test_run_id.hhbc");
|
||||
unlink("/tmp/hphpd_client$test_run_id.hhbc");
|
||||
}
|
||||
|
||||
function request($url, $timeout = 1200) {
|
||||
tlog("Fetching: $url");
|
||||
$ch = curl_init();
|
||||
$host = "hphpd.debugger.".php_uname('n');
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: $host"));
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
||||
$result = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function startDebuggerClient($debugPort, $input_path, &$pipes) {
|
||||
global $test_run_id;
|
||||
|
||||
$home = hphp_home().'/hphp/test/server/debugger';
|
||||
$hhvm = bin_root().'/hphp/hhvm/hhvm';
|
||||
$host = ' -h '.php_uname('n');
|
||||
$port = ' --debug-port '.$debugPort;
|
||||
$user = ' --user debugger';
|
||||
$config = ' --config '.$home.'/config/debugger-client.hdf';
|
||||
$logFileConfig = ' -vLog.File='."/tmp/hphpd_test_client$test_run_id.log";
|
||||
$repoConfig = " -vRepo.Central.Path=/tmp/hphpd_client$test_run_id.hhbc";
|
||||
$debugConfig = ' --debug-config '.$home.'/config/hphpd.hdf';
|
||||
|
||||
$cmd = $hhvm.' -m debug' . $host . $port . $user .
|
||||
$config . $logFileConfig . $repoConfig . $debugConfig .
|
||||
' <'.$home.$input_path;
|
||||
|
||||
$descriptorspec = array(
|
||||
0 => array("pipe", "r"),
|
||||
1 => array("pipe", "w"),
|
||||
2 => array("pipe", "w"),
|
||||
);
|
||||
|
||||
$env = $_ENV;
|
||||
$env["TERM"] = "dumb";
|
||||
|
||||
tlog('Starting debugger client with command: '.$cmd);
|
||||
$process = proc_open("$cmd 2>&1", $descriptorspec, $pipes, null, $env);
|
||||
if (!is_resource($process)) {
|
||||
tlog('Failed to start a shell process for the server');
|
||||
dumpLogFilesToStdoutAndDie();
|
||||
}
|
||||
}
|
||||
|
||||
function runTest($testName, $testController) {
|
||||
try {
|
||||
$serverPort = get_random_port();
|
||||
$adminPort = get_random_port();
|
||||
while ($adminPort === $serverPort) {
|
||||
$adminPort = get_random_port();
|
||||
}
|
||||
$debugPort = get_random_port();
|
||||
while ($debugPort === $serverPort || $debugPort === $adminPort) {
|
||||
$debugPort = get_random_port();
|
||||
}
|
||||
|
||||
$pid = posix_getpid();
|
||||
$serverProc = null;
|
||||
$clientProcessId = 0;
|
||||
$serverProc = startServer($serverPort, $adminPort, $debugPort);
|
||||
waitForServerToGetGoing($serverPort);
|
||||
startDebuggerClient($debugPort, "/debugger/$testName.in", $pipes);
|
||||
$clientProcessId = getClientProcessId($pipes[1]);
|
||||
if (!$clientProcessId ||
|
||||
($clientProcessId = intval($clientProcessId)) <= 0) {
|
||||
tlog('Failed to communicate with the debugger client process');
|
||||
dumpLogFilesToStdoutAndDie();
|
||||
}
|
||||
tlog("Debugger client process id = $clientProcessId");
|
||||
$testController($pipes[1], $clientProcessId, $serverPort);
|
||||
// Echo stderr, just in case.
|
||||
// (It was redirected to stdout, so this should be empty).
|
||||
echo stream_get_contents($pipes[2]);
|
||||
stopServer($adminPort);
|
||||
} catch (Exception $e) {
|
||||
error_log("Caught exception, test failed, pid=$pid");
|
||||
killChildren(posix_getpid());
|
||||
error_log('test failed');
|
||||
}
|
||||
}
|
||||
|
||||
function killChildren($pid) {
|
||||
$childIds = exec("pgrep -f -d , -P $pid");
|
||||
foreach (explode(",", $childIds) as $cid) {
|
||||
if (!$cid) continue;
|
||||
killChildren($cid);
|
||||
error_log("killing $cid");
|
||||
posix_kill($cid, SIGKILL);
|
||||
}
|
||||
}
|
||||
|
||||
function getClientProcessId($pipe) {
|
||||
tlog("reading initial client output for client process id");
|
||||
while (!feof($pipe)) {
|
||||
$clientOutput = fgets($pipe);
|
||||
tlog($clientOutput);
|
||||
if (strpos($clientOutput, "running in script mode, pid=") === 0) {
|
||||
return substr($clientOutput, 28);
|
||||
}
|
||||
}
|
||||
if (feof($pipe)) tlog("client closed the pipe.");
|
||||
tlog("done reading client output for client process id");
|
||||
}
|
||||
|
||||
function waitForClientToOutput($pipe, $string1, $retryCount = 20) {
|
||||
tlog("reading client output");
|
||||
$rc = $retryCount;
|
||||
while (!feof($pipe)) {
|
||||
$clientOutput = fgets($pipe);
|
||||
tlog($clientOutput);
|
||||
if (strpos($clientOutput,
|
||||
".....Debugger client still waiting for server response.....") === 0) {
|
||||
if (--$rc > 0) continue;
|
||||
dumpLogFilesToStdoutAndDie();
|
||||
}
|
||||
echo $clientOutput;
|
||||
if (strpos($clientOutput, $string1) === 0) break;
|
||||
$rc = $retryCount;
|
||||
}
|
||||
if (feof($pipe)) tlog("client closed the pipe.");
|
||||
tlog("done reading client output");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
echo 'skip';
|
||||
Referência em uma Nova Issue
Bloquear um usuário