| Index: test/cctest/test-debug.cc
|
| diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
|
| index a9ee93194f98c567b8cb8487f3380569864fb244..0268cb0b67094957d67a56b6744b1ce45d9475b4 100644
|
| --- a/test/cctest/test-debug.cc
|
| +++ b/test/cctest/test-debug.cc
|
| @@ -5788,242 +5788,6 @@ TEST(DebuggerClearMessageHandlerWhileActive) {
|
| }
|
|
|
|
|
| -/* Test DebugMessageDispatch */
|
| -/* In this test, the V8 thread waits for a message from the debug thread.
|
| - * The DebugMessageDispatchHandler is executed from the debugger thread
|
| - * which signals the V8 thread to wake up.
|
| - */
|
| -
|
| -class DebugMessageDispatchV8Thread : public v8::internal::Thread {
|
| - public:
|
| - DebugMessageDispatchV8Thread() : Thread("DebugMessageDispatchV8Thread") { }
|
| - void Run();
|
| -};
|
| -
|
| -class DebugMessageDispatchDebuggerThread : public v8::internal::Thread {
|
| - public:
|
| - DebugMessageDispatchDebuggerThread()
|
| - : Thread("DebugMessageDispatchDebuggerThread") { }
|
| - void Run();
|
| -};
|
| -
|
| -Barriers* debug_message_dispatch_barriers;
|
| -
|
| -
|
| -static void DebugMessageHandler() {
|
| - debug_message_dispatch_barriers->semaphore_1.Signal();
|
| -}
|
| -
|
| -
|
| -void DebugMessageDispatchV8Thread::Run() {
|
| - v8::Isolate::Scope isolate_scope(CcTest::isolate());
|
| - DebugLocalContext env;
|
| - v8::HandleScope scope(env->GetIsolate());
|
| -
|
| - // Set up debug message dispatch handler.
|
| - v8::Debug::SetDebugMessageDispatchHandler(DebugMessageHandler);
|
| -
|
| - CompileRun("var y = 1 + 2;\n");
|
| - debug_message_dispatch_barriers->barrier_1.Wait();
|
| - debug_message_dispatch_barriers->semaphore_1.Wait();
|
| - debug_message_dispatch_barriers->barrier_2.Wait();
|
| -}
|
| -
|
| -
|
| -void DebugMessageDispatchDebuggerThread::Run() {
|
| - debug_message_dispatch_barriers->barrier_1.Wait();
|
| - SendContinueCommand();
|
| - debug_message_dispatch_barriers->barrier_2.Wait();
|
| -}
|
| -
|
| -
|
| -TEST(DebuggerDebugMessageDispatch) {
|
| - DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread;
|
| - DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread;
|
| -
|
| - // Create a V8 environment
|
| - Barriers stack_allocated_debug_message_dispatch_barriers;
|
| - debug_message_dispatch_barriers =
|
| - &stack_allocated_debug_message_dispatch_barriers;
|
| -
|
| - debug_message_dispatch_v8_thread.Start();
|
| - debug_message_dispatch_debugger_thread.Start();
|
| -
|
| - debug_message_dispatch_v8_thread.Join();
|
| - debug_message_dispatch_debugger_thread.Join();
|
| -}
|
| -
|
| -
|
| -TEST(DebuggerAgent) {
|
| - v8::V8::Initialize();
|
| - i::Debugger* debugger = CcTest::i_isolate()->debugger();
|
| - // Make sure these ports is not used by other tests to allow tests to run in
|
| - // parallel.
|
| - const int kPort1 = 5858 + FlagDependentPortOffset();
|
| - const int kPort2 = 5857 + FlagDependentPortOffset();
|
| - const int kPort3 = 5856 + FlagDependentPortOffset();
|
| -
|
| - // Make a string with the port2 number.
|
| - const int kPortBufferLen = 6;
|
| - char port2_str[kPortBufferLen];
|
| - OS::SNPrintF(i::Vector<char>(port2_str, kPortBufferLen), "%d", kPort2);
|
| -
|
| - bool ok;
|
| -
|
| - // Test starting and stopping the agent without any client connection.
|
| - debugger->StartAgent("test", kPort1);
|
| - debugger->StopAgent();
|
| - // Test starting the agent, connecting a client and shutting down the agent
|
| - // with the client connected.
|
| - ok = debugger->StartAgent("test", kPort2);
|
| - CHECK(ok);
|
| - debugger->WaitForAgent();
|
| - i::Socket* client = new i::Socket;
|
| - ok = client->Connect("localhost", port2_str);
|
| - CHECK(ok);
|
| - // It is important to wait for a message from the agent. Otherwise,
|
| - // we can close the server socket during "accept" syscall, making it failing
|
| - // (at least on Linux), and the test will work incorrectly.
|
| - char buf;
|
| - ok = client->Receive(&buf, 1) == 1;
|
| - CHECK(ok);
|
| - debugger->StopAgent();
|
| - delete client;
|
| -
|
| - // Test starting and stopping the agent with the required port already
|
| - // occoupied.
|
| - i::Socket* server = new i::Socket;
|
| - ok = server->Bind(kPort3);
|
| - CHECK(ok);
|
| -
|
| - debugger->StartAgent("test", kPort3);
|
| - debugger->StopAgent();
|
| -
|
| - delete server;
|
| -}
|
| -
|
| -
|
| -class DebuggerAgentProtocolServerThread : public i::Thread {
|
| - public:
|
| - explicit DebuggerAgentProtocolServerThread(int port)
|
| - : Thread("DebuggerAgentProtocolServerThread"),
|
| - port_(port),
|
| - server_(NULL),
|
| - client_(NULL),
|
| - listening_(0) {
|
| - }
|
| - ~DebuggerAgentProtocolServerThread() {
|
| - // Close both sockets.
|
| - delete client_;
|
| - delete server_;
|
| - }
|
| -
|
| - void Run();
|
| - void WaitForListening() { listening_.Wait(); }
|
| - char* body() { return body_.get(); }
|
| -
|
| - private:
|
| - int port_;
|
| - i::SmartArrayPointer<char> body_;
|
| - i::Socket* server_; // Server socket used for bind/accept.
|
| - i::Socket* client_; // Single client connection used by the test.
|
| - i::Semaphore listening_; // Signalled when the server is in listen mode.
|
| -};
|
| -
|
| -
|
| -void DebuggerAgentProtocolServerThread::Run() {
|
| - bool ok;
|
| -
|
| - // Create the server socket and bind it to the requested port.
|
| - server_ = new i::Socket;
|
| - CHECK(server_ != NULL);
|
| - ok = server_->Bind(port_);
|
| - CHECK(ok);
|
| -
|
| - // Listen for new connections.
|
| - ok = server_->Listen(1);
|
| - CHECK(ok);
|
| - listening_.Signal();
|
| -
|
| - // Accept a connection.
|
| - client_ = server_->Accept();
|
| - CHECK(client_ != NULL);
|
| -
|
| - // Receive a debugger agent protocol message.
|
| - i::DebuggerAgentUtil::ReceiveMessage(client_);
|
| -}
|
| -
|
| -
|
| -TEST(DebuggerAgentProtocolOverflowHeader) {
|
| - // Make sure this port is not used by other tests to allow tests to run in
|
| - // parallel.
|
| - const int kPort = 5860 + FlagDependentPortOffset();
|
| - static const char* kLocalhost = "localhost";
|
| -
|
| - // Make a string with the port number.
|
| - const int kPortBufferLen = 6;
|
| - char port_str[kPortBufferLen];
|
| - OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
|
| -
|
| - // Create a socket server to receive a debugger agent message.
|
| - DebuggerAgentProtocolServerThread* server =
|
| - new DebuggerAgentProtocolServerThread(kPort);
|
| - server->Start();
|
| - server->WaitForListening();
|
| -
|
| - // Connect.
|
| - i::Socket* client = new i::Socket;
|
| - CHECK(client != NULL);
|
| - bool ok = client->Connect(kLocalhost, port_str);
|
| - CHECK(ok);
|
| -
|
| - // Send headers which overflow the receive buffer.
|
| - static const int kBufferSize = 1000;
|
| - char buffer[kBufferSize];
|
| -
|
| - // Long key and short value: XXXX....XXXX:0\r\n.
|
| - for (int i = 0; i < kBufferSize - 4; i++) {
|
| - buffer[i] = 'X';
|
| - }
|
| - buffer[kBufferSize - 4] = ':';
|
| - buffer[kBufferSize - 3] = '0';
|
| - buffer[kBufferSize - 2] = '\r';
|
| - buffer[kBufferSize - 1] = '\n';
|
| - int result = client->Send(buffer, kBufferSize);
|
| - CHECK_EQ(kBufferSize, result);
|
| -
|
| - // Short key and long value: X:XXXX....XXXX\r\n.
|
| - buffer[0] = 'X';
|
| - buffer[1] = ':';
|
| - for (int i = 2; i < kBufferSize - 2; i++) {
|
| - buffer[i] = 'X';
|
| - }
|
| - buffer[kBufferSize - 2] = '\r';
|
| - buffer[kBufferSize - 1] = '\n';
|
| - result = client->Send(buffer, kBufferSize);
|
| - CHECK_EQ(kBufferSize, result);
|
| -
|
| - // Add empty body to request.
|
| - const char* content_length_zero_header = "Content-Length:0\r\n";
|
| - int length = StrLength(content_length_zero_header);
|
| - result = client->Send(content_length_zero_header, length);
|
| - CHECK_EQ(length, result);
|
| - result = client->Send("\r\n", 2);
|
| - CHECK_EQ(2, result);
|
| -
|
| - // Wait until data is received.
|
| - server->Join();
|
| -
|
| - // Check for empty body.
|
| - CHECK(server->body() == NULL);
|
| -
|
| - // Close the client before the server to avoid TIME_WAIT issues.
|
| - client->Shutdown();
|
| - delete client;
|
| - delete server;
|
| -}
|
| -
|
| -
|
| // Test for issue http://code.google.com/p/v8/issues/detail?id=289.
|
| // Make sure that DebugGetLoadedScripts doesn't return scripts
|
| // with disposed external source.
|
| @@ -6783,7 +6547,7 @@ TEST(NoDebugBreakInAfterCompileMessageHandler) {
|
| static int counting_message_handler_counter;
|
|
|
| static void CountingMessageHandler(const v8::Debug::Message& message) {
|
| - counting_message_handler_counter++;
|
| + if (message.IsResponse()) counting_message_handler_counter++;
|
| }
|
|
|
|
|
| @@ -6830,6 +6594,83 @@ TEST(ProcessDebugMessages) {
|
| }
|
|
|
|
|
| +class SendCommandThread : public v8::internal::Thread {
|
| + public:
|
| + explicit SendCommandThread(v8::Isolate* isolate)
|
| + : Thread("SendCommandThread"),
|
| + semaphore_(0),
|
| + isolate_(isolate) { }
|
| +
|
| + static void ProcessDebugMessages(v8::Isolate* isolate, void* data) {
|
| + v8::Debug::ProcessDebugMessages();
|
| + reinterpret_cast<v8::internal::Semaphore*>(data)->Signal();
|
| + }
|
| +
|
| + virtual void Run() {
|
| + semaphore_.Wait();
|
| + const int kBufferSize = 1000;
|
| + uint16_t buffer[kBufferSize];
|
| + const char* scripts_command =
|
| + "{\"seq\":0,"
|
| + "\"type\":\"request\","
|
| + "\"command\":\"scripts\"}";
|
| + int length = AsciiToUtf16(scripts_command, buffer);
|
| + // Send scripts command.
|
| +
|
| + for (int i = 0; i < 100; i++) {
|
| + CHECK_EQ(i, counting_message_handler_counter);
|
| + // Queue debug message.
|
| + v8::Debug::SendCommand(isolate_, buffer, length);
|
| + // Synchronize with the main thread to force message processing.
|
| + isolate_->RequestInterrupt(ProcessDebugMessages, &semaphore_);
|
| + semaphore_.Wait();
|
| + }
|
| +
|
| + v8::V8::TerminateExecution(isolate_);
|
| + }
|
| +
|
| + void StartSending() {
|
| + semaphore_.Signal();
|
| + }
|
| +
|
| + private:
|
| + v8::internal::Semaphore semaphore_;
|
| + v8::Isolate* isolate_;
|
| +};
|
| +
|
| +
|
| +static SendCommandThread* send_command_thread_ = NULL;
|
| +
|
| +static void StartSendingCommands(
|
| + const v8::FunctionCallbackInfo<v8::Value>& info) {
|
| + send_command_thread_->StartSending();
|
| +}
|
| +
|
| +
|
| +TEST(ProcessDebugMessagesThreaded) {
|
| + DebugLocalContext env;
|
| + v8::Isolate* isolate = env->GetIsolate();
|
| + v8::HandleScope scope(isolate);
|
| +
|
| + counting_message_handler_counter = 0;
|
| +
|
| + v8::Debug::SetMessageHandler2(CountingMessageHandler);
|
| + send_command_thread_ = new SendCommandThread(isolate);
|
| + send_command_thread_->Start();
|
| +
|
| + v8::Handle<v8::FunctionTemplate> start =
|
| + v8::FunctionTemplate::New(isolate, StartSendingCommands);
|
| + env->Global()->Set(v8_str("start"), start->GetFunction());
|
| +
|
| + CompileRun("start(); while (true) { }");
|
| +
|
| + CHECK_EQ(100, counting_message_handler_counter);
|
| +
|
| + v8::Debug::SetMessageHandler2(NULL);
|
| + CheckDebuggerUnloaded();
|
| +}
|
| +
|
| +
|
| struct BacktraceData {
|
| static int frame_counter;
|
| static void MessageHandler(const v8::Debug::Message& message) {
|
|
|